|
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
31
|
31
|
#include <byteswap.h>
|
32
|
32
|
#include <ipxe/io.h>
|
33
|
33
|
#include <ipxe/pci.h>
|
|
34
|
+#include <ipxe/pcibackup.h>
|
34
|
35
|
#include <ipxe/malloc.h>
|
35
|
36
|
#include <ipxe/umalloc.h>
|
36
|
37
|
#include <ipxe/iobuf.h>
|
|
@@ -1991,7 +1992,7 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
|
1991
|
1992
|
struct arbelprm_query_fw fw;
|
1992
|
1993
|
struct arbelprm_access_lam lam;
|
1993
|
1994
|
unsigned int fw_pages;
|
1994
|
|
- size_t fw_size;
|
|
1995
|
+ size_t fw_len;
|
1995
|
1996
|
physaddr_t fw_base;
|
1996
|
1997
|
uint64_t eq_set_ci_base_addr;
|
1997
|
1998
|
int rc;
|
|
@@ -2019,17 +2020,22 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
|
2019
|
2020
|
arbel_cmd_enable_lam ( arbel, &lam );
|
2020
|
2021
|
|
2021
|
2022
|
/* Allocate firmware pages and map firmware area */
|
2022
|
|
- fw_size = ( fw_pages * ARBEL_PAGE_SIZE );
|
2023
|
|
- arbel->firmware_area = umalloc ( fw_size );
|
|
2023
|
+ fw_len = ( fw_pages * ARBEL_PAGE_SIZE );
|
2024
|
2024
|
if ( ! arbel->firmware_area ) {
|
2025
|
|
- rc = -ENOMEM;
|
2026
|
|
- goto err_alloc_fa;
|
|
2025
|
+ arbel->firmware_len = fw_len;
|
|
2026
|
+ arbel->firmware_area = umalloc ( arbel->firmware_len );
|
|
2027
|
+ if ( ! arbel->firmware_area ) {
|
|
2028
|
+ rc = -ENOMEM;
|
|
2029
|
+ goto err_alloc_fa;
|
|
2030
|
+ }
|
|
2031
|
+ } else {
|
|
2032
|
+ assert ( arbel->firmware_len == fw_len );
|
2027
|
2033
|
}
|
2028
|
2034
|
fw_base = user_to_phys ( arbel->firmware_area, 0 );
|
2029
|
2035
|
DBGC ( arbel, "Arbel %p firmware area at [%08lx,%08lx)\n",
|
2030
|
|
- arbel, fw_base, ( fw_base + fw_size ) );
|
|
2036
|
+ arbel, fw_base, ( fw_base + fw_len ) );
|
2031
|
2037
|
if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_fa,
|
2032
|
|
- 0, fw_base, fw_size ) ) != 0 ) {
|
|
2038
|
+ 0, fw_base, fw_len ) ) != 0 ) {
|
2033
|
2039
|
DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
|
2034
|
2040
|
arbel, strerror ( rc ) );
|
2035
|
2041
|
goto err_map_fa;
|
|
@@ -2048,8 +2054,6 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
|
2048
|
2054
|
err_run_fw:
|
2049
|
2055
|
arbel_cmd_unmap_fa ( arbel );
|
2050
|
2056
|
err_map_fa:
|
2051
|
|
- ufree ( arbel->firmware_area );
|
2052
|
|
- arbel->firmware_area = UNULL;
|
2053
|
2057
|
err_alloc_fa:
|
2054
|
2058
|
err_query_fw:
|
2055
|
2059
|
return rc;
|
|
@@ -2067,10 +2071,9 @@ static void arbel_stop_firmware ( struct arbel *arbel ) {
|
2067
|
2071
|
DBGC ( arbel, "Arbel %p FATAL could not stop firmware: %s\n",
|
2068
|
2072
|
arbel, strerror ( rc ) );
|
2069
|
2073
|
/* Leak memory and return; at least we avoid corruption */
|
|
2074
|
+ arbel->firmware_area = UNULL;
|
2070
|
2075
|
return;
|
2071
|
2076
|
}
|
2072
|
|
- ufree ( arbel->firmware_area );
|
2073
|
|
- arbel->firmware_area = UNULL;
|
2074
|
2077
|
}
|
2075
|
2078
|
|
2076
|
2079
|
/***************************************************************************
|
|
@@ -2180,6 +2183,7 @@ static int arbel_alloc_icm ( struct arbel *arbel,
|
2180
|
2183
|
unsigned int log_num_uars, log_num_qps, log_num_srqs, log_num_ees;
|
2181
|
2184
|
unsigned int log_num_cqs, log_num_mtts, log_num_mpts, log_num_rdbs;
|
2182
|
2185
|
unsigned int log_num_eqs, log_num_mcs;
|
|
2186
|
+ size_t icm_len, icm_aux_len;
|
2183
|
2187
|
size_t len;
|
2184
|
2188
|
physaddr_t icm_phys;
|
2185
|
2189
|
int rc;
|
|
@@ -2351,7 +2355,7 @@ static int arbel_alloc_icm ( struct arbel *arbel,
|
2351
|
2355
|
|
2352
|
2356
|
/* Record amount of ICM to be allocated */
|
2353
|
2357
|
icm_offset = icm_align ( icm_offset, ARBEL_PAGE_SIZE );
|
2354
|
|
- arbel->icm_len = icm_offset;
|
|
2358
|
+ icm_len = icm_offset;
|
2355
|
2359
|
|
2356
|
2360
|
/* User access region contexts
|
2357
|
2361
|
*
|
|
@@ -2376,24 +2380,29 @@ static int arbel_alloc_icm ( struct arbel *arbel,
|
2376
|
2380
|
|
2377
|
2381
|
/* Get ICM auxiliary area size */
|
2378
|
2382
|
memset ( &icm_size, 0, sizeof ( icm_size ) );
|
2379
|
|
- MLX_FILL_1 ( &icm_size, 1, value, arbel->icm_len );
|
|
2383
|
+ MLX_FILL_1 ( &icm_size, 1, value, icm_len );
|
2380
|
2384
|
if ( ( rc = arbel_cmd_set_icm_size ( arbel, &icm_size,
|
2381
|
2385
|
&icm_aux_size ) ) != 0 ) {
|
2382
|
2386
|
DBGC ( arbel, "Arbel %p could not set ICM size: %s\n",
|
2383
|
2387
|
arbel, strerror ( rc ) );
|
2384
|
2388
|
goto err_set_icm_size;
|
2385
|
2389
|
}
|
2386
|
|
- arbel->icm_aux_len =
|
2387
|
|
- ( MLX_GET ( &icm_aux_size, value ) * ARBEL_PAGE_SIZE );
|
|
2390
|
+ icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * ARBEL_PAGE_SIZE );
|
2388
|
2391
|
|
2389
|
2392
|
/* Allocate ICM data and auxiliary area */
|
2390
|
2393
|
DBGC ( arbel, "Arbel %p requires %zd kB ICM and %zd kB AUX ICM\n",
|
2391
|
|
- arbel, ( arbel->icm_len / 1024 ),
|
2392
|
|
- ( arbel->icm_aux_len / 1024 ) );
|
2393
|
|
- arbel->icm = umalloc ( arbel->icm_len + arbel->icm_aux_len );
|
|
2394
|
+ arbel, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
|
2394
|
2395
|
if ( ! arbel->icm ) {
|
2395
|
|
- rc = -ENOMEM;
|
2396
|
|
- goto err_alloc_icm;
|
|
2396
|
+ arbel->icm_len = icm_len;
|
|
2397
|
+ arbel->icm_aux_len = icm_aux_len;
|
|
2398
|
+ arbel->icm = umalloc ( arbel->icm_len + arbel->icm_aux_len );
|
|
2399
|
+ if ( ! arbel->icm ) {
|
|
2400
|
+ rc = -ENOMEM;
|
|
2401
|
+ goto err_alloc_icm;
|
|
2402
|
+ }
|
|
2403
|
+ } else {
|
|
2404
|
+ assert ( arbel->icm_len == icm_len );
|
|
2405
|
+ assert ( arbel->icm_aux_len == icm_aux_len );
|
2397
|
2406
|
}
|
2398
|
2407
|
icm_phys = user_to_phys ( arbel->icm, 0 );
|
2399
|
2408
|
|
|
@@ -2459,8 +2468,6 @@ static int arbel_alloc_icm ( struct arbel *arbel,
|
2459
|
2468
|
free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE );
|
2460
|
2469
|
arbel->db_rec= NULL;
|
2461
|
2470
|
err_alloc_doorbell:
|
2462
|
|
- ufree ( arbel->icm );
|
2463
|
|
- arbel->icm = UNULL;
|
2464
|
2471
|
err_alloc_icm:
|
2465
|
2472
|
err_set_icm_size:
|
2466
|
2473
|
return rc;
|
|
@@ -2483,17 +2490,41 @@ static void arbel_free_icm ( struct arbel *arbel ) {
|
2483
|
2490
|
arbel_cmd_unmap_icm_aux ( arbel );
|
2484
|
2491
|
free_dma ( arbel->db_rec, ARBEL_PAGE_SIZE );
|
2485
|
2492
|
arbel->db_rec = NULL;
|
2486
|
|
- ufree ( arbel->icm );
|
2487
|
|
- arbel->icm = UNULL;
|
2488
|
2493
|
}
|
2489
|
2494
|
|
2490
|
2495
|
/***************************************************************************
|
2491
|
2496
|
*
|
2492
|
|
- * Initialisation
|
|
2497
|
+ * Initialisation and teardown
|
2493
|
2498
|
*
|
2494
|
2499
|
***************************************************************************
|
2495
|
2500
|
*/
|
2496
|
2501
|
|
|
2502
|
+/**
|
|
2503
|
+ * Reset device
|
|
2504
|
+ *
|
|
2505
|
+ * @v arbel Arbel device
|
|
2506
|
+ */
|
|
2507
|
+static void arbel_reset ( struct arbel *arbel ) {
|
|
2508
|
+ struct pci_device *pci = arbel->pci;
|
|
2509
|
+ struct pci_config_backup backup;
|
|
2510
|
+ static const uint8_t backup_exclude[] =
|
|
2511
|
+ PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
|
|
2512
|
+ uint16_t vendor;
|
|
2513
|
+ unsigned int i;
|
|
2514
|
+
|
|
2515
|
+ /* Perform device reset and preserve PCI configuration */
|
|
2516
|
+ pci_backup ( pci, &backup, backup_exclude );
|
|
2517
|
+ writel ( ARBEL_RESET_MAGIC,
|
|
2518
|
+ ( arbel->config + ARBEL_RESET_OFFSET ) );
|
|
2519
|
+ for ( i = 0 ; i < ARBEL_RESET_WAIT_TIME_MS ; i++ ) {
|
|
2520
|
+ mdelay ( 1 );
|
|
2521
|
+ pci_read_config_word ( pci, PCI_VENDOR_ID, &vendor );
|
|
2522
|
+ if ( vendor != 0xffff )
|
|
2523
|
+ break;
|
|
2524
|
+ }
|
|
2525
|
+ pci_restore ( pci, &backup, backup_exclude );
|
|
2526
|
+}
|
|
2527
|
+
|
2497
|
2528
|
/**
|
2498
|
2529
|
* Set up memory protection table
|
2499
|
2530
|
*
|
|
@@ -2572,6 +2603,115 @@ static int arbel_configure_special_qps ( struct arbel *arbel ) {
|
2572
|
2603
|
return 0;
|
2573
|
2604
|
}
|
2574
|
2605
|
|
|
2606
|
+/**
|
|
2607
|
+ * Start Arbel device
|
|
2608
|
+ *
|
|
2609
|
+ * @v arbel Arbel device
|
|
2610
|
+ * @v running Firmware is already running
|
|
2611
|
+ * @ret rc Return status code
|
|
2612
|
+ */
|
|
2613
|
+static int arbel_start ( struct arbel *arbel, int running ) {
|
|
2614
|
+ struct arbelprm_init_hca init_hca;
|
|
2615
|
+ unsigned int i;
|
|
2616
|
+ int rc;
|
|
2617
|
+
|
|
2618
|
+ /* Start firmware if not already running */
|
|
2619
|
+ if ( ! running ) {
|
|
2620
|
+ if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 )
|
|
2621
|
+ goto err_start_firmware;
|
|
2622
|
+ }
|
|
2623
|
+
|
|
2624
|
+ /* Allocate ICM */
|
|
2625
|
+ memset ( &init_hca, 0, sizeof ( init_hca ) );
|
|
2626
|
+ if ( ( rc = arbel_alloc_icm ( arbel, &init_hca ) ) != 0 )
|
|
2627
|
+ goto err_alloc_icm;
|
|
2628
|
+
|
|
2629
|
+ /* Initialise HCA */
|
|
2630
|
+ if ( ( rc = arbel_cmd_init_hca ( arbel, &init_hca ) ) != 0 ) {
|
|
2631
|
+ DBGC ( arbel, "Arbel %p could not initialise HCA: %s\n",
|
|
2632
|
+ arbel, strerror ( rc ) );
|
|
2633
|
+ goto err_init_hca;
|
|
2634
|
+ }
|
|
2635
|
+
|
|
2636
|
+ /* Set up memory protection */
|
|
2637
|
+ if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 )
|
|
2638
|
+ goto err_setup_mpt;
|
|
2639
|
+ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
|
|
2640
|
+ arbel->ibdev[i]->rdma_key = arbel->lkey;
|
|
2641
|
+
|
|
2642
|
+ /* Set up event queue */
|
|
2643
|
+ if ( ( rc = arbel_create_eq ( arbel ) ) != 0 )
|
|
2644
|
+ goto err_create_eq;
|
|
2645
|
+
|
|
2646
|
+ /* Configure special QPs */
|
|
2647
|
+ if ( ( rc = arbel_configure_special_qps ( arbel ) ) != 0 )
|
|
2648
|
+ goto err_conf_special_qps;
|
|
2649
|
+
|
|
2650
|
+ return 0;
|
|
2651
|
+
|
|
2652
|
+ err_conf_special_qps:
|
|
2653
|
+ arbel_destroy_eq ( arbel );
|
|
2654
|
+ err_create_eq:
|
|
2655
|
+ err_setup_mpt:
|
|
2656
|
+ arbel_cmd_close_hca ( arbel );
|
|
2657
|
+ err_init_hca:
|
|
2658
|
+ arbel_free_icm ( arbel );
|
|
2659
|
+ err_alloc_icm:
|
|
2660
|
+ arbel_stop_firmware ( arbel );
|
|
2661
|
+ err_start_firmware:
|
|
2662
|
+ return rc;
|
|
2663
|
+}
|
|
2664
|
+
|
|
2665
|
+/**
|
|
2666
|
+ * Stop Arbel device
|
|
2667
|
+ *
|
|
2668
|
+ * @v arbel Arbel device
|
|
2669
|
+ */
|
|
2670
|
+static void arbel_stop ( struct arbel *arbel ) {
|
|
2671
|
+ arbel_destroy_eq ( arbel );
|
|
2672
|
+ arbel_cmd_close_hca ( arbel );
|
|
2673
|
+ arbel_free_icm ( arbel );
|
|
2674
|
+ arbel_stop_firmware ( arbel );
|
|
2675
|
+ arbel_reset ( arbel );
|
|
2676
|
+}
|
|
2677
|
+
|
|
2678
|
+/**
|
|
2679
|
+ * Open Arbel device
|
|
2680
|
+ *
|
|
2681
|
+ * @v arbel Arbel device
|
|
2682
|
+ * @ret rc Return status code
|
|
2683
|
+ */
|
|
2684
|
+static int arbel_open ( struct arbel *arbel ) {
|
|
2685
|
+ int rc;
|
|
2686
|
+
|
|
2687
|
+ /* Start device if applicable */
|
|
2688
|
+ if ( arbel->open_count == 0 ) {
|
|
2689
|
+ if ( ( rc = arbel_start ( arbel, 0 ) ) != 0 )
|
|
2690
|
+ return rc;
|
|
2691
|
+ }
|
|
2692
|
+
|
|
2693
|
+ /* Increment open counter */
|
|
2694
|
+ arbel->open_count++;
|
|
2695
|
+
|
|
2696
|
+ return 0;
|
|
2697
|
+}
|
|
2698
|
+
|
|
2699
|
+/**
|
|
2700
|
+ * Close Arbel device
|
|
2701
|
+ *
|
|
2702
|
+ * @v arbel Arbel device
|
|
2703
|
+ */
|
|
2704
|
+static void arbel_close ( struct arbel *arbel ) {
|
|
2705
|
+
|
|
2706
|
+ /* Decrement open counter */
|
|
2707
|
+ assert ( arbel->open_count != 0 );
|
|
2708
|
+ arbel->open_count--;
|
|
2709
|
+
|
|
2710
|
+ /* Stop device if applicable */
|
|
2711
|
+ if ( arbel->open_count == 0 )
|
|
2712
|
+ arbel_stop ( arbel );
|
|
2713
|
+}
|
|
2714
|
+
|
2575
|
2715
|
/***************************************************************************
|
2576
|
2716
|
*
|
2577
|
2717
|
* Infiniband link-layer operations
|
|
@@ -2585,11 +2725,16 @@ static int arbel_configure_special_qps ( struct arbel *arbel ) {
|
2585
|
2725
|
* @v ibdev Infiniband device
|
2586
|
2726
|
* @ret rc Return status code
|
2587
|
2727
|
*/
|
2588
|
|
-static int arbel_open ( struct ib_device *ibdev ) {
|
|
2728
|
+static int arbel_ib_open ( struct ib_device *ibdev ) {
|
2589
|
2729
|
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
2590
|
2730
|
struct arbelprm_init_ib init_ib;
|
2591
|
2731
|
int rc;
|
2592
|
2732
|
|
|
2733
|
+ /* Open hardware */
|
|
2734
|
+ if ( ( rc = arbel_open ( arbel ) ) != 0 )
|
|
2735
|
+ goto err_open;
|
|
2736
|
+
|
|
2737
|
+ /* Initialise IB */
|
2593
|
2738
|
memset ( &init_ib, 0, sizeof ( init_ib ) );
|
2594
|
2739
|
MLX_FILL_3 ( &init_ib, 0,
|
2595
|
2740
|
mtu_cap, ARBEL_MTU_2048,
|
|
@@ -2601,13 +2746,18 @@ static int arbel_open ( struct ib_device *ibdev ) {
|
2601
|
2746
|
&init_ib ) ) != 0 ) {
|
2602
|
2747
|
DBGC ( arbel, "Arbel %p port %d could not intialise IB: %s\n",
|
2603
|
2748
|
arbel, ibdev->port, strerror ( rc ) );
|
2604
|
|
- return rc;
|
|
2749
|
+ goto err_init_ib;
|
2605
|
2750
|
}
|
2606
|
2751
|
|
2607
|
2752
|
/* Update MAD parameters */
|
2608
|
2753
|
ib_smc_update ( ibdev, arbel_mad );
|
2609
|
2754
|
|
2610
|
2755
|
return 0;
|
|
2756
|
+
|
|
2757
|
+ err_init_ib:
|
|
2758
|
+ arbel_close ( arbel );
|
|
2759
|
+ err_open:
|
|
2760
|
+ return rc;
|
2611
|
2761
|
}
|
2612
|
2762
|
|
2613
|
2763
|
/**
|
|
@@ -2615,15 +2765,19 @@ static int arbel_open ( struct ib_device *ibdev ) {
|
2615
|
2765
|
*
|
2616
|
2766
|
* @v ibdev Infiniband device
|
2617
|
2767
|
*/
|
2618
|
|
-static void arbel_close ( struct ib_device *ibdev ) {
|
|
2768
|
+static void arbel_ib_close ( struct ib_device *ibdev ) {
|
2619
|
2769
|
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
2620
|
2770
|
int rc;
|
2621
|
2771
|
|
|
2772
|
+ /* Close IB */
|
2622
|
2773
|
if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
|
2623
|
2774
|
DBGC ( arbel, "Arbel %p port %d could not close IB: %s\n",
|
2624
|
2775
|
arbel, ibdev->port, strerror ( rc ) );
|
2625
|
2776
|
/* Nothing we can do about this */
|
2626
|
2777
|
}
|
|
2778
|
+
|
|
2779
|
+ /* Close hardware */
|
|
2780
|
+ arbel_close ( arbel );
|
2627
|
2781
|
}
|
2628
|
2782
|
|
2629
|
2783
|
/**
|
|
@@ -2753,8 +2907,8 @@ static struct ib_device_operations arbel_ib_operations = {
|
2753
|
2907
|
.post_recv = arbel_post_recv,
|
2754
|
2908
|
.poll_cq = arbel_poll_cq,
|
2755
|
2909
|
.poll_eq = arbel_poll_eq,
|
2756
|
|
- .open = arbel_open,
|
2757
|
|
- .close = arbel_close,
|
|
2910
|
+ .open = arbel_ib_open,
|
|
2911
|
+ .close = arbel_ib_close,
|
2758
|
2912
|
.mcast_attach = arbel_mcast_attach,
|
2759
|
2913
|
.mcast_detach = arbel_mcast_detach,
|
2760
|
2914
|
.set_port_info = arbel_inform_sma,
|
|
@@ -2768,6 +2922,52 @@ static struct ib_device_operations arbel_ib_operations = {
|
2768
|
2922
|
***************************************************************************
|
2769
|
2923
|
*/
|
2770
|
2924
|
|
|
2925
|
+/**
|
|
2926
|
+ * Allocate Arbel device
|
|
2927
|
+ *
|
|
2928
|
+ * @ret arbel Arbel device
|
|
2929
|
+ */
|
|
2930
|
+static struct arbel * arbel_alloc ( void ) {
|
|
2931
|
+ struct arbel *arbel;
|
|
2932
|
+
|
|
2933
|
+ /* Allocate Arbel device */
|
|
2934
|
+ arbel = zalloc ( sizeof ( *arbel ) );
|
|
2935
|
+ if ( ! arbel )
|
|
2936
|
+ goto err_arbel;
|
|
2937
|
+
|
|
2938
|
+ /* Allocate space for mailboxes */
|
|
2939
|
+ arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
|
|
2940
|
+ if ( ! arbel->mailbox_in )
|
|
2941
|
+ goto err_mailbox_in;
|
|
2942
|
+ arbel->mailbox_out = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
|
|
2943
|
+ if ( ! arbel->mailbox_out )
|
|
2944
|
+ goto err_mailbox_out;
|
|
2945
|
+
|
|
2946
|
+ return arbel;
|
|
2947
|
+
|
|
2948
|
+ free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
|
|
2949
|
+ err_mailbox_out:
|
|
2950
|
+ free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
|
|
2951
|
+ err_mailbox_in:
|
|
2952
|
+ free ( arbel );
|
|
2953
|
+ err_arbel:
|
|
2954
|
+ return NULL;
|
|
2955
|
+}
|
|
2956
|
+
|
|
2957
|
+/**
|
|
2958
|
+ * Free Arbel device
|
|
2959
|
+ *
|
|
2960
|
+ * @v arbel Arbel device
|
|
2961
|
+ */
|
|
2962
|
+static void arbel_free ( struct arbel *arbel ) {
|
|
2963
|
+
|
|
2964
|
+ ufree ( arbel->icm );
|
|
2965
|
+ ufree ( arbel->firmware_area );
|
|
2966
|
+ free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
|
|
2967
|
+ free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
|
|
2968
|
+ free ( arbel );
|
|
2969
|
+}
|
|
2970
|
+
|
2771
|
2971
|
/**
|
2772
|
2972
|
* Probe PCI device
|
2773
|
2973
|
*
|
|
@@ -2778,17 +2978,17 @@ static struct ib_device_operations arbel_ib_operations = {
|
2778
|
2978
|
static int arbel_probe ( struct pci_device *pci ) {
|
2779
|
2979
|
struct arbel *arbel;
|
2780
|
2980
|
struct ib_device *ibdev;
|
2781
|
|
- struct arbelprm_init_hca init_hca;
|
2782
|
2981
|
int i;
|
2783
|
2982
|
int rc;
|
2784
|
2983
|
|
2785
|
2984
|
/* Allocate Arbel device */
|
2786
|
|
- arbel = zalloc ( sizeof ( *arbel ) );
|
|
2985
|
+ arbel = arbel_alloc();
|
2787
|
2986
|
if ( ! arbel ) {
|
2788
|
2987
|
rc = -ENOMEM;
|
2789
|
|
- goto err_alloc_arbel;
|
|
2988
|
+ goto err_alloc;
|
2790
|
2989
|
}
|
2791
|
2990
|
pci_set_drvdata ( pci, arbel );
|
|
2991
|
+ arbel->pci = pci;
|
2792
|
2992
|
|
2793
|
2993
|
/* Allocate Infiniband devices */
|
2794
|
2994
|
for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) {
|
|
@@ -2814,17 +3014,8 @@ static int arbel_probe ( struct pci_device *pci ) {
|
2814
|
3014
|
ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ),
|
2815
|
3015
|
ARBEL_PCI_UAR_SIZE );
|
2816
|
3016
|
|
2817
|
|
- /* Allocate space for mailboxes */
|
2818
|
|
- arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
|
2819
|
|
- if ( ! arbel->mailbox_in ) {
|
2820
|
|
- rc = -ENOMEM;
|
2821
|
|
- goto err_mailbox_in;
|
2822
|
|
- }
|
2823
|
|
- arbel->mailbox_out = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
|
2824
|
|
- if ( ! arbel->mailbox_out ) {
|
2825
|
|
- rc = -ENOMEM;
|
2826
|
|
- goto err_mailbox_out;
|
2827
|
|
- }
|
|
3017
|
+ /* Reset device */
|
|
3018
|
+ arbel_reset ( arbel );
|
2828
|
3019
|
|
2829
|
3020
|
/* Start firmware */
|
2830
|
3021
|
if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 )
|
|
@@ -2834,31 +3025,9 @@ static int arbel_probe ( struct pci_device *pci ) {
|
2834
|
3025
|
if ( ( rc = arbel_get_limits ( arbel ) ) != 0 )
|
2835
|
3026
|
goto err_get_limits;
|
2836
|
3027
|
|
2837
|
|
- /* Allocate ICM */
|
2838
|
|
- memset ( &init_hca, 0, sizeof ( init_hca ) );
|
2839
|
|
- if ( ( rc = arbel_alloc_icm ( arbel, &init_hca ) ) != 0 )
|
2840
|
|
- goto err_alloc_icm;
|
2841
|
|
-
|
2842
|
|
- /* Initialise HCA */
|
2843
|
|
- if ( ( rc = arbel_cmd_init_hca ( arbel, &init_hca ) ) != 0 ) {
|
2844
|
|
- DBGC ( arbel, "Arbel %p could not initialise HCA: %s\n",
|
2845
|
|
- arbel, strerror ( rc ) );
|
2846
|
|
- goto err_init_hca;
|
2847
|
|
- }
|
2848
|
|
-
|
2849
|
|
- /* Set up memory protection */
|
2850
|
|
- if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 )
|
2851
|
|
- goto err_setup_mpt;
|
2852
|
|
- for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
|
2853
|
|
- arbel->ibdev[i]->rdma_key = arbel->lkey;
|
2854
|
|
-
|
2855
|
|
- /* Set up event queue */
|
2856
|
|
- if ( ( rc = arbel_create_eq ( arbel ) ) != 0 )
|
2857
|
|
- goto err_create_eq;
|
2858
|
|
-
|
2859
|
|
- /* Configure special QPs */
|
2860
|
|
- if ( ( rc = arbel_configure_special_qps ( arbel ) ) != 0 )
|
2861
|
|
- goto err_conf_special_qps;
|
|
3028
|
+ /* Start device */
|
|
3029
|
+ if ( ( rc = arbel_start ( arbel, 1 ) ) != 0 )
|
|
3030
|
+ goto err_start;
|
2862
|
3031
|
|
2863
|
3032
|
/* Initialise parameters using SMC */
|
2864
|
3033
|
for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ )
|
|
@@ -2874,33 +3043,27 @@ static int arbel_probe ( struct pci_device *pci ) {
|
2874
|
3043
|
}
|
2875
|
3044
|
}
|
2876
|
3045
|
|
|
3046
|
+ /* Leave device quiescent until opened */
|
|
3047
|
+ if ( arbel->open_count == 0 )
|
|
3048
|
+ arbel_stop ( arbel );
|
|
3049
|
+
|
2877
|
3050
|
return 0;
|
2878
|
3051
|
|
2879
|
3052
|
i = ARBEL_NUM_PORTS;
|
2880
|
3053
|
err_register_ibdev:
|
2881
|
3054
|
for ( i-- ; i >= 0 ; i-- )
|
2882
|
3055
|
unregister_ibdev ( arbel->ibdev[i] );
|
2883
|
|
- err_conf_special_qps:
|
2884
|
|
- arbel_destroy_eq ( arbel );
|
2885
|
|
- err_create_eq:
|
2886
|
|
- err_setup_mpt:
|
2887
|
|
- arbel_cmd_close_hca ( arbel );
|
2888
|
|
- err_init_hca:
|
2889
|
|
- arbel_free_icm ( arbel );
|
2890
|
|
- err_alloc_icm:
|
|
3056
|
+ arbel_stop ( arbel );
|
|
3057
|
+ err_start:
|
2891
|
3058
|
err_get_limits:
|
2892
|
3059
|
arbel_stop_firmware ( arbel );
|
2893
|
3060
|
err_start_firmware:
|
2894
|
|
- free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
|
2895
|
|
- err_mailbox_out:
|
2896
|
|
- free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
|
2897
|
|
- err_mailbox_in:
|
2898
|
3061
|
i = ARBEL_NUM_PORTS;
|
2899
|
3062
|
err_alloc_ibdev:
|
2900
|
3063
|
for ( i-- ; i >= 0 ; i-- )
|
2901
|
3064
|
ibdev_put ( arbel->ibdev[i] );
|
2902
|
|
- free ( arbel );
|
2903
|
|
- err_alloc_arbel:
|
|
3065
|
+ arbel_free ( arbel );
|
|
3066
|
+ err_alloc:
|
2904
|
3067
|
return rc;
|
2905
|
3068
|
}
|
2906
|
3069
|
|
|
@@ -2915,15 +3078,9 @@ static void arbel_remove ( struct pci_device *pci ) {
|
2915
|
3078
|
|
2916
|
3079
|
for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
|
2917
|
3080
|
unregister_ibdev ( arbel->ibdev[i] );
|
2918
|
|
- arbel_destroy_eq ( arbel );
|
2919
|
|
- arbel_cmd_close_hca ( arbel );
|
2920
|
|
- arbel_free_icm ( arbel );
|
2921
|
|
- arbel_stop_firmware ( arbel );
|
2922
|
|
- free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
|
2923
|
|
- free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
|
2924
|
3081
|
for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- )
|
2925
|
3082
|
ibdev_put ( arbel->ibdev[i] );
|
2926
|
|
- free ( arbel );
|
|
3083
|
+ arbel_free ( arbel );
|
2927
|
3084
|
}
|
2928
|
3085
|
|
2929
|
3086
|
static struct pci_device_id arbel_nics[] = {
|