Browse Source

[hermon] Ensure hardware is quiescent when no interfaces are open

WinPE has been observed to call PXENV_UNDI_SHUTDOWN but not
PXENV_STOP_UNDI.  This means that Hermon hardware is left partially
active (firmware running and one event queue mapped) when WinPE starts
up, which can cause a Blue Screen of Death.

Fix by ensuring that the hardware is left quiescent (with the firmware
stopped) when no interfaces are open.

Reported-by: Itay Gazit <itayg@mellanox.co.il>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
6dd4ac77e5
2 changed files with 217 additions and 81 deletions
  1. 194
    79
      src/drivers/infiniband/hermon.c
  2. 23
    2
      src/drivers/infiniband/hermon.h

+ 194
- 79
src/drivers/infiniband/hermon.c View File

2136
 static int hermon_start_firmware ( struct hermon *hermon ) {
2136
 static int hermon_start_firmware ( struct hermon *hermon ) {
2137
 	struct hermonprm_query_fw fw;
2137
 	struct hermonprm_query_fw fw;
2138
 	unsigned int fw_pages;
2138
 	unsigned int fw_pages;
2139
-	size_t fw_size;
2139
+	size_t fw_len;
2140
 	physaddr_t fw_base;
2140
 	physaddr_t fw_base;
2141
 	int rc;
2141
 	int rc;
2142
 
2142
 
2154
 	       hermon, fw_pages, ( fw_pages * 4 ) );
2154
 	       hermon, fw_pages, ( fw_pages * 4 ) );
2155
 
2155
 
2156
 	/* Allocate firmware pages and map firmware area */
2156
 	/* Allocate firmware pages and map firmware area */
2157
-	fw_size = ( fw_pages * HERMON_PAGE_SIZE );
2158
-	hermon->firmware_area = umalloc ( fw_size );
2157
+	fw_len = ( fw_pages * HERMON_PAGE_SIZE );
2159
 	if ( ! hermon->firmware_area ) {
2158
 	if ( ! hermon->firmware_area ) {
2160
-		rc = -ENOMEM;
2161
-		goto err_alloc_fa;
2159
+		hermon->firmware_len = fw_len;
2160
+		hermon->firmware_area = umalloc ( hermon->firmware_len );
2161
+		if ( ! hermon->firmware_area ) {
2162
+			rc = -ENOMEM;
2163
+			goto err_alloc_fa;
2164
+		}
2165
+	} else {
2166
+		assert ( hermon->firmware_len == fw_len );
2162
 	}
2167
 	}
2163
 	fw_base = user_to_phys ( hermon->firmware_area, 0 );
2168
 	fw_base = user_to_phys ( hermon->firmware_area, 0 );
2164
 	DBGC ( hermon, "Hermon %p firmware area at physical [%08lx,%08lx)\n",
2169
 	DBGC ( hermon, "Hermon %p firmware area at physical [%08lx,%08lx)\n",
2165
-	       hermon, fw_base, ( fw_base + fw_size ) );
2170
+	       hermon, fw_base, ( fw_base + fw_len ) );
2166
 	if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa,
2171
 	if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa,
2167
-				     0, fw_base, fw_size ) ) != 0 ) {
2172
+				     0, fw_base, fw_len ) ) != 0 ) {
2168
 		DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
2173
 		DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
2169
 		       hermon, strerror ( rc ) );
2174
 		       hermon, strerror ( rc ) );
2170
 		goto err_map_fa;
2175
 		goto err_map_fa;
2183
  err_run_fw:
2188
  err_run_fw:
2184
  err_map_fa:
2189
  err_map_fa:
2185
 	hermon_cmd_unmap_fa ( hermon );
2190
 	hermon_cmd_unmap_fa ( hermon );
2186
-	ufree ( hermon->firmware_area );
2187
-	hermon->firmware_area = UNULL;
2188
  err_alloc_fa:
2191
  err_alloc_fa:
2189
  err_query_fw:
2192
  err_query_fw:
2190
 	return rc;
2193
 	return rc;
2202
 		DBGC ( hermon, "Hermon %p FATAL could not stop firmware: %s\n",
2205
 		DBGC ( hermon, "Hermon %p FATAL could not stop firmware: %s\n",
2203
 		       hermon, strerror ( rc ) );
2206
 		       hermon, strerror ( rc ) );
2204
 		/* Leak memory and return; at least we avoid corruption */
2207
 		/* Leak memory and return; at least we avoid corruption */
2208
+		hermon->firmware_area = UNULL;
2205
 		return;
2209
 		return;
2206
 	}
2210
 	}
2207
-	ufree ( hermon->firmware_area );
2208
-	hermon->firmware_area = UNULL;
2209
 }
2211
 }
2210
 
2212
 
2211
 /***************************************************************************
2213
 /***************************************************************************
2285
 }
2287
 }
2286
 
2288
 
2287
 /**
2289
 /**
2288
- * Allocate ICM
2290
+ * Map ICM (allocating if necessary)
2289
  *
2291
  *
2290
  * @v hermon		Hermon device
2292
  * @v hermon		Hermon device
2291
  * @v init_hca		INIT_HCA structure to fill in
2293
  * @v init_hca		INIT_HCA structure to fill in
2292
  * @ret rc		Return status code
2294
  * @ret rc		Return status code
2293
  */
2295
  */
2294
-static int hermon_alloc_icm ( struct hermon *hermon,
2295
-			      struct hermonprm_init_hca *init_hca ) {
2296
+static int hermon_map_icm ( struct hermon *hermon,
2297
+			    struct hermonprm_init_hca *init_hca ) {
2296
 	struct hermonprm_scalar_parameter icm_size;
2298
 	struct hermonprm_scalar_parameter icm_size;
2297
 	struct hermonprm_scalar_parameter icm_aux_size;
2299
 	struct hermonprm_scalar_parameter icm_aux_size;
2298
 	uint64_t icm_offset = 0;
2300
 	uint64_t icm_offset = 0;
2519
 	/* Allocate ICM data and auxiliary area */
2521
 	/* Allocate ICM data and auxiliary area */
2520
 	DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
2522
 	DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
2521
 	       hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
2523
 	       hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
2522
-	hermon->icm = umalloc ( icm_aux_len + icm_len );
2523
 	if ( ! hermon->icm ) {
2524
 	if ( ! hermon->icm ) {
2524
-		rc = -ENOMEM;
2525
-		goto err_alloc;
2525
+		hermon->icm_len = icm_len;
2526
+		hermon->icm_aux_len = icm_aux_len;
2527
+		hermon->icm = umalloc ( hermon->icm_aux_len + hermon->icm_len );
2528
+		if ( ! hermon->icm ) {
2529
+			rc = -ENOMEM;
2530
+			goto err_alloc;
2531
+		}
2532
+	} else {
2533
+		assert ( hermon->icm_len == icm_len );
2534
+		assert ( hermon->icm_aux_len == icm_aux_len );
2526
 	}
2535
 	}
2527
 	icm_phys = user_to_phys ( hermon->icm, 0 );
2536
 	icm_phys = user_to_phys ( hermon->icm, 0 );
2528
 
2537
 
2559
 	assert ( i == 0 ); /* We don't handle partial failure at present */
2568
 	assert ( i == 0 ); /* We don't handle partial failure at present */
2560
  err_map_icm_aux:
2569
  err_map_icm_aux:
2561
 	hermon_cmd_unmap_icm_aux ( hermon );
2570
 	hermon_cmd_unmap_icm_aux ( hermon );
2562
-	ufree ( hermon->icm );
2563
-	hermon->icm = UNULL;
2564
  err_alloc:
2571
  err_alloc:
2565
  err_set_icm_size:
2572
  err_set_icm_size:
2566
 	return rc;
2573
 	return rc;
2567
 }
2574
 }
2568
 
2575
 
2569
 /**
2576
 /**
2570
- * Free ICM
2577
+ * Unmap ICM
2571
  *
2578
  *
2572
  * @v hermon		Hermon device
2579
  * @v hermon		Hermon device
2573
  */
2580
  */
2574
-static void hermon_free_icm ( struct hermon *hermon ) {
2581
+static void hermon_unmap_icm ( struct hermon *hermon ) {
2575
 	struct hermonprm_scalar_parameter unmap_icm;
2582
 	struct hermonprm_scalar_parameter unmap_icm;
2576
 	int i;
2583
 	int i;
2577
 
2584
 
2587
 				       &unmap_icm );
2594
 				       &unmap_icm );
2588
 	}
2595
 	}
2589
 	hermon_cmd_unmap_icm_aux ( hermon );
2596
 	hermon_cmd_unmap_icm_aux ( hermon );
2590
-	ufree ( hermon->icm );
2591
-	hermon->icm = UNULL;
2592
 }
2597
 }
2593
 
2598
 
2594
 /***************************************************************************
2599
 /***************************************************************************
2595
  *
2600
  *
2596
- * Initialisation
2601
+ * Initialisation and teardown
2597
  *
2602
  *
2598
  ***************************************************************************
2603
  ***************************************************************************
2599
  */
2604
  */
2602
  * Reset device
2607
  * Reset device
2603
  *
2608
  *
2604
  * @v hermon		Hermon device
2609
  * @v hermon		Hermon device
2605
- * @v pci		PCI device
2606
  */
2610
  */
2607
-static void hermon_reset ( struct hermon *hermon,
2608
-			   struct pci_device *pci ) {
2611
+static void hermon_reset ( struct hermon *hermon ) {
2612
+	struct pci_device *pci = hermon->pci;
2609
 	struct pci_config_backup backup;
2613
 	struct pci_config_backup backup;
2610
 	static const uint8_t backup_exclude[] =
2614
 	static const uint8_t backup_exclude[] =
2611
 		PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
2615
 		PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
2612
 
2616
 
2617
+	/* Perform device reset and preserve PCI configuration */
2613
 	pci_backup ( pci, &backup, backup_exclude );
2618
 	pci_backup ( pci, &backup, backup_exclude );
2614
 	writel ( HERMON_RESET_MAGIC,
2619
 	writel ( HERMON_RESET_MAGIC,
2615
 		 ( hermon->config + HERMON_RESET_OFFSET ) );
2620
 		 ( hermon->config + HERMON_RESET_OFFSET ) );
2616
 	mdelay ( HERMON_RESET_WAIT_TIME_MS );
2621
 	mdelay ( HERMON_RESET_WAIT_TIME_MS );
2617
 	pci_restore ( pci, &backup, backup_exclude );
2622
 	pci_restore ( pci, &backup, backup_exclude );
2623
+
2624
+	/* Reset command interface toggle */
2625
+	hermon->toggle = 0;
2618
 }
2626
 }
2619
 
2627
 
2620
 /**
2628
 /**
2686
 	return 0;
2694
 	return 0;
2687
 }
2695
 }
2688
 
2696
 
2697
+/**
2698
+ * Start Hermon device
2699
+ *
2700
+ * @v hermon		Hermon device
2701
+ * @v running		Firmware is already running
2702
+ * @ret rc		Return status code
2703
+ */
2704
+static int hermon_start ( struct hermon *hermon, int running ) {
2705
+	struct hermonprm_init_hca init_hca;
2706
+	unsigned int i;
2707
+	int rc;
2708
+
2709
+	/* Start firmware if not already running */
2710
+	if ( ! running ) {
2711
+		if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
2712
+			goto err_start_firmware;
2713
+	}
2714
+
2715
+	/* Allocate and map ICM */
2716
+	memset ( &init_hca, 0, sizeof ( init_hca ) );
2717
+	if ( ( rc = hermon_map_icm ( hermon, &init_hca ) ) != 0 )
2718
+		goto err_map_icm;
2719
+
2720
+	/* Initialise HCA */
2721
+	MLX_FILL_1 ( &init_hca, 0, version, 0x02 /* "Must be 0x02" */ );
2722
+	MLX_FILL_1 ( &init_hca, 5, udp, 1 );
2723
+	MLX_FILL_1 ( &init_hca, 74, uar_parameters.log_max_uars, 8 );
2724
+	if ( ( rc = hermon_cmd_init_hca ( hermon, &init_hca ) ) != 0 ) {
2725
+		DBGC ( hermon, "Hermon %p could not initialise HCA: %s\n",
2726
+		       hermon, strerror ( rc ) );
2727
+		goto err_init_hca;
2728
+	}
2729
+
2730
+	/* Set up memory protection */
2731
+	if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
2732
+		goto err_setup_mpt;
2733
+	for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
2734
+		hermon->port[i].ibdev->rdma_key = hermon->lkey;
2735
+
2736
+	/* Set up event queue */
2737
+	if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
2738
+		goto err_create_eq;
2739
+
2740
+	/* Configure special QPs */
2741
+	if ( ( rc = hermon_configure_special_qps ( hermon ) ) != 0 )
2742
+		goto err_conf_special_qps;
2743
+
2744
+	return 0;
2745
+
2746
+ err_conf_special_qps:
2747
+	hermon_destroy_eq ( hermon );
2748
+ err_create_eq:
2749
+ err_setup_mpt:
2750
+	hermon_cmd_close_hca ( hermon );
2751
+ err_init_hca:
2752
+	hermon_unmap_icm ( hermon );
2753
+ err_map_icm:
2754
+	hermon_stop_firmware ( hermon );
2755
+ err_start_firmware:
2756
+	return rc;
2757
+}
2758
+
2759
+/**
2760
+ * Stop Hermon device
2761
+ *
2762
+ * @v hermon		Hermon device
2763
+ */
2764
+static void hermon_stop ( struct hermon *hermon ) {
2765
+	hermon_destroy_eq ( hermon );
2766
+	hermon_cmd_close_hca ( hermon );
2767
+	hermon_unmap_icm ( hermon );
2768
+	hermon_stop_firmware ( hermon );
2769
+	hermon_reset ( hermon );
2770
+}
2771
+
2772
+/**
2773
+ * Open Hermon device
2774
+ *
2775
+ * @v hermon		Hermon device
2776
+ * @ret rc		Return status code
2777
+ */
2778
+static int hermon_open ( struct hermon *hermon ) {
2779
+	int rc;
2780
+
2781
+	/* Start device if applicable */
2782
+	if ( hermon->open_count == 0 ) {
2783
+		if ( ( rc = hermon_start ( hermon, 0 ) ) != 0 )
2784
+			return rc;
2785
+	}
2786
+
2787
+	/* Increment open counter */
2788
+	hermon->open_count++;
2789
+
2790
+	return 0;
2791
+}
2792
+
2793
+/**
2794
+ * Close Hermon device
2795
+ *
2796
+ * @v hermon		Hermon device
2797
+ */
2798
+static void hermon_close ( struct hermon *hermon ) {
2799
+
2800
+	/* Decrement open counter */
2801
+	assert ( hermon->open_count != 0 );
2802
+	hermon->open_count--;
2803
+
2804
+	/* Stop device if applicable */
2805
+	if ( hermon->open_count == 0 )
2806
+		hermon_stop ( hermon );
2807
+}
2808
+
2689
 /***************************************************************************
2809
 /***************************************************************************
2690
  *
2810
  *
2691
  * Infiniband link-layer operations
2811
  * Infiniband link-layer operations
2699
  * @v ibdev		Infiniband device
2819
  * @v ibdev		Infiniband device
2700
  * @ret rc		Return status code
2820
  * @ret rc		Return status code
2701
  */
2821
  */
2702
-static int hermon_open ( struct ib_device *ibdev ) {
2822
+static int hermon_ib_open ( struct ib_device *ibdev ) {
2703
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2823
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2704
 	union hermonprm_set_port set_port;
2824
 	union hermonprm_set_port set_port;
2705
 	int rc;
2825
 	int rc;
2706
 
2826
 
2827
+	/* Open hardware */
2828
+	if ( ( rc = hermon_open ( hermon ) ) != 0 )
2829
+		goto err_open;
2830
+
2707
 	/* Set port parameters */
2831
 	/* Set port parameters */
2708
 	memset ( &set_port, 0, sizeof ( set_port ) );
2832
 	memset ( &set_port, 0, sizeof ( set_port ) );
2709
 	MLX_FILL_8 ( &set_port.ib, 0,
2833
 	MLX_FILL_8 ( &set_port.ib, 0,
2724
 					  &set_port ) ) != 0 ) {
2848
 					  &set_port ) ) != 0 ) {
2725
 		DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
2849
 		DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
2726
 		       hermon, ibdev->port, strerror ( rc ) );
2850
 		       hermon, ibdev->port, strerror ( rc ) );
2727
-		return rc;
2851
+		goto err_set_port;
2728
 	}
2852
 	}
2729
 
2853
 
2730
 	/* Initialise port */
2854
 	/* Initialise port */
2731
 	if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
2855
 	if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
2732
 		DBGC ( hermon, "Hermon %p port %d could not initialise port: "
2856
 		DBGC ( hermon, "Hermon %p port %d could not initialise port: "
2733
 		       "%s\n", hermon, ibdev->port, strerror ( rc ) );
2857
 		       "%s\n", hermon, ibdev->port, strerror ( rc ) );
2734
-		return rc;
2858
+		goto err_init_port;
2735
 	}
2859
 	}
2736
 
2860
 
2737
 	/* Update MAD parameters */
2861
 	/* Update MAD parameters */
2738
 	ib_smc_update ( ibdev, hermon_mad );
2862
 	ib_smc_update ( ibdev, hermon_mad );
2739
 
2863
 
2740
 	return 0;
2864
 	return 0;
2865
+
2866
+ err_init_port:
2867
+ err_set_port:
2868
+	hermon_close ( hermon );
2869
+ err_open:
2870
+	return rc;
2741
 }
2871
 }
2742
 
2872
 
2743
 /**
2873
 /**
2745
  *
2875
  *
2746
  * @v ibdev		Infiniband device
2876
  * @v ibdev		Infiniband device
2747
  */
2877
  */
2748
-static void hermon_close ( struct ib_device *ibdev ) {
2878
+static void hermon_ib_close ( struct ib_device *ibdev ) {
2749
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2879
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2750
 	int rc;
2880
 	int rc;
2751
 
2881
 
2882
+	/* Close port */
2752
 	if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
2883
 	if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
2753
 		DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
2884
 		DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
2754
 		       hermon, ibdev->port, strerror ( rc ) );
2885
 		       hermon, ibdev->port, strerror ( rc ) );
2755
 		/* Nothing we can do about this */
2886
 		/* Nothing we can do about this */
2756
 	}
2887
 	}
2888
+
2889
+	/* Close hardware */
2890
+	hermon_close ( hermon );
2757
 }
2891
 }
2758
 
2892
 
2759
 /**
2893
 /**
2883
 	.post_recv	= hermon_post_recv,
3017
 	.post_recv	= hermon_post_recv,
2884
 	.poll_cq	= hermon_poll_cq,
3018
 	.poll_cq	= hermon_poll_cq,
2885
 	.poll_eq	= hermon_poll_eq,
3019
 	.poll_eq	= hermon_poll_eq,
2886
-	.open		= hermon_open,
2887
-	.close		= hermon_close,
3020
+	.open		= hermon_ib_open,
3021
+	.close		= hermon_ib_close,
2888
 	.mcast_attach	= hermon_mcast_attach,
3022
 	.mcast_attach	= hermon_mcast_attach,
2889
 	.mcast_detach	= hermon_mcast_detach,
3023
 	.mcast_detach	= hermon_mcast_detach,
2890
 	.set_port_info	= hermon_inform_sma,
3024
 	.set_port_info	= hermon_inform_sma,
3073
 	union hermonprm_set_port set_port;
3207
 	union hermonprm_set_port set_port;
3074
 	int rc;
3208
 	int rc;
3075
 
3209
 
3210
+	/* Open hardware */
3211
+	if ( ( rc = hermon_open ( hermon ) ) != 0 )
3212
+		goto err_open;
3213
+
3076
 	/* Allocate completion queue */
3214
 	/* Allocate completion queue */
3077
 	port->eth_cq = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
3215
 	port->eth_cq = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
3078
 				      &hermon_eth_cq_op );
3216
 				      &hermon_eth_cq_op );
3167
  err_create_qp:
3305
  err_create_qp:
3168
 	ib_destroy_cq ( ibdev, port->eth_cq );
3306
 	ib_destroy_cq ( ibdev, port->eth_cq );
3169
  err_create_cq:
3307
  err_create_cq:
3308
+	hermon_close ( hermon );
3309
+ err_open:
3170
 	return rc;
3310
 	return rc;
3171
 }
3311
 }
3172
 
3312
 
3191
 	/* Tear down the queues */
3331
 	/* Tear down the queues */
3192
 	ib_destroy_qp ( ibdev, port->eth_qp );
3332
 	ib_destroy_qp ( ibdev, port->eth_qp );
3193
 	ib_destroy_cq ( ibdev, port->eth_cq );
3333
 	ib_destroy_cq ( ibdev, port->eth_cq );
3334
+
3335
+	/* Close hardware */
3336
+	hermon_close ( hermon );
3194
 }
3337
 }
3195
 
3338
 
3196
 /** Hermon Ethernet network device operations */
3339
 /** Hermon Ethernet network device operations */
3562
  */
3705
  */
3563
 static void hermon_free ( struct hermon *hermon ) {
3706
 static void hermon_free ( struct hermon *hermon ) {
3564
 
3707
 
3708
+	ufree ( hermon->icm );
3709
+	ufree ( hermon->firmware_area );
3565
 	free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
3710
 	free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
3566
 	free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
3711
 	free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
3567
 	free ( hermon );
3712
 	free ( hermon );
3571
  * Initialise Hermon PCI parameters
3716
  * Initialise Hermon PCI parameters
3572
  *
3717
  *
3573
  * @v hermon		Hermon device
3718
  * @v hermon		Hermon device
3574
- * @v pci		PCI device
3575
  */
3719
  */
3576
-static void hermon_pci_init ( struct hermon *hermon, struct pci_device *pci ) {
3720
+static void hermon_pci_init ( struct hermon *hermon ) {
3721
+	struct pci_device *pci = hermon->pci;
3577
 
3722
 
3578
 	/* Fix up PCI device */
3723
 	/* Fix up PCI device */
3579
 	adjust_pci_device ( pci );
3724
 	adjust_pci_device ( pci );
3597
 	struct ib_device *ibdev;
3742
 	struct ib_device *ibdev;
3598
 	struct net_device *netdev;
3743
 	struct net_device *netdev;
3599
 	struct hermon_port *port;
3744
 	struct hermon_port *port;
3600
-	struct hermonprm_init_hca init_hca;
3601
 	unsigned int i;
3745
 	unsigned int i;
3602
 	int rc;
3746
 	int rc;
3603
 
3747
 
3608
 		goto err_alloc;
3752
 		goto err_alloc;
3609
 	}
3753
 	}
3610
 	pci_set_drvdata ( pci, hermon );
3754
 	pci_set_drvdata ( pci, hermon );
3755
+	hermon->pci = pci;
3611
 
3756
 
3612
 	/* Initialise PCI parameters */
3757
 	/* Initialise PCI parameters */
3613
-	hermon_pci_init ( hermon, pci );
3758
+	hermon_pci_init ( hermon );
3614
 
3759
 
3615
 	/* Reset device */
3760
 	/* Reset device */
3616
-	hermon_reset ( hermon, pci );
3761
+	hermon_reset ( hermon );
3617
 
3762
 
3618
 	/* Start firmware */
3763
 	/* Start firmware */
3619
 	if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
3764
 	if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
3650
 		netdev->priv = &hermon->port[i];
3795
 		netdev->priv = &hermon->port[i];
3651
 	}
3796
 	}
3652
 
3797
 
3653
-	/* Allocate ICM */
3654
-	memset ( &init_hca, 0, sizeof ( init_hca ) );
3655
-	if ( ( rc = hermon_alloc_icm ( hermon, &init_hca ) ) != 0 )
3656
-		goto err_alloc_icm;
3657
-
3658
-	/* Initialise HCA */
3659
-	MLX_FILL_1 ( &init_hca, 0, version, 0x02 /* "Must be 0x02" */ );
3660
-	MLX_FILL_1 ( &init_hca, 5, udp, 1 );
3661
-	MLX_FILL_1 ( &init_hca, 74, uar_parameters.log_max_uars, 8 );
3662
-	if ( ( rc = hermon_cmd_init_hca ( hermon, &init_hca ) ) != 0 ) {
3663
-		DBGC ( hermon, "Hermon %p could not initialise HCA: %s\n",
3664
-		       hermon, strerror ( rc ) );
3665
-		goto err_init_hca;
3666
-	}
3667
-
3668
-	/* Set up memory protection */
3669
-	if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
3670
-		goto err_setup_mpt;
3671
-	for ( i = 0 ; i < hermon->cap.num_ports ; i++ )
3672
-		hermon->port[i].ibdev->rdma_key = hermon->lkey;
3673
-
3674
-	/* Set up event queue */
3675
-	if ( ( rc = hermon_create_eq ( hermon ) ) != 0 )
3676
-		goto err_create_eq;
3677
-
3678
-	/* Configure special QPs */
3679
-	if ( ( rc = hermon_configure_special_qps ( hermon ) ) != 0 )
3680
-		goto err_conf_special_qps;
3798
+	/* Start device */
3799
+	if ( ( rc = hermon_start ( hermon, 1 ) ) != 0 )
3800
+		goto err_start;
3681
 
3801
 
3682
 	/* Determine port types */
3802
 	/* Determine port types */
3683
 	for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
3803
 	for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
3693
 			goto err_register;
3813
 			goto err_register;
3694
 	}
3814
 	}
3695
 
3815
 
3816
+	/* Leave device quiescent until opened */
3817
+	if ( hermon->open_count == 0 )
3818
+		hermon_stop ( hermon );
3819
+
3696
 	return 0;
3820
 	return 0;
3697
 
3821
 
3698
 	i = hermon->cap.num_ports;
3822
 	i = hermon->cap.num_ports;
3702
 		port->type->unregister_dev ( hermon, port );
3826
 		port->type->unregister_dev ( hermon, port );
3703
 	}
3827
 	}
3704
  err_set_port_type:
3828
  err_set_port_type:
3705
- err_conf_special_qps:
3706
-	hermon_destroy_eq ( hermon );
3707
- err_create_eq:
3708
- err_setup_mpt:
3709
-	hermon_cmd_close_hca ( hermon );
3710
- err_init_hca:
3711
-	hermon_free_icm ( hermon );
3712
- err_alloc_icm:
3829
+	hermon_stop ( hermon );
3830
+ err_start:
3713
 	i = hermon->cap.num_ports;
3831
 	i = hermon->cap.num_ports;
3714
  err_alloc_netdev:
3832
  err_alloc_netdev:
3715
 	for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
3833
 	for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
3742
 		port = &hermon->port[i];
3860
 		port = &hermon->port[i];
3743
 		port->type->unregister_dev ( hermon, port );
3861
 		port->type->unregister_dev ( hermon, port );
3744
 	}
3862
 	}
3745
-	hermon_destroy_eq ( hermon );
3746
-	hermon_cmd_close_hca ( hermon );
3747
-	hermon_free_icm ( hermon );
3748
-	hermon_stop_firmware ( hermon );
3749
 	for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
3863
 	for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
3750
 		netdev_nullify ( hermon->port[i].netdev );
3864
 		netdev_nullify ( hermon->port[i].netdev );
3751
 		netdev_put ( hermon->port[i].netdev );
3865
 		netdev_put ( hermon->port[i].netdev );
3773
 		goto err_alloc;
3887
 		goto err_alloc;
3774
 	}
3888
 	}
3775
 	pci_set_drvdata ( pci, hermon );
3889
 	pci_set_drvdata ( pci, hermon );
3890
+	hermon->pci = pci;
3776
 
3891
 
3777
 	/* Initialise PCI parameters */
3892
 	/* Initialise PCI parameters */
3778
-	hermon_pci_init ( hermon, pci );
3893
+	hermon_pci_init ( hermon );
3779
 
3894
 
3780
 	/* Initialise BOFM device */
3895
 	/* Initialise BOFM device */
3781
 	bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );
3896
 	bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );

+ 23
- 2
src/drivers/infiniband/hermon.h View File

829
 
829
 
830
 /** A Hermon device */
830
 /** A Hermon device */
831
 struct hermon {
831
 struct hermon {
832
+	/** PCI device */
833
+	struct pci_device *pci;
832
 	/** PCI configuration registers */
834
 	/** PCI configuration registers */
833
 	void *config;
835
 	void *config;
834
 	/** PCI user Access Region */
836
 	/** PCI user Access Region */
841
 	/** Command output mailbox */
843
 	/** Command output mailbox */
842
 	void *mailbox_out;
844
 	void *mailbox_out;
843
 
845
 
844
-	/** Firmware area in external memory */
846
+	/** Device open request counter */
847
+	unsigned int open_count;
848
+
849
+	/** Firmware size */
850
+	size_t firmware_len;
851
+	/** Firmware area in external memory
852
+	 *
853
+	 * This is allocated when first needed, and freed only on
854
+	 * final teardown, in order to avoid memory map changes at
855
+	 * runtime.
856
+	 */
845
 	userptr_t firmware_area;
857
 	userptr_t firmware_area;
846
 	/** ICM map */
858
 	/** ICM map */
847
 	struct hermon_icm_map icm_map[HERMON_ICM_NUM_REGIONS];
859
 	struct hermon_icm_map icm_map[HERMON_ICM_NUM_REGIONS];
848
-	/** ICM area */
860
+	/** ICM size */
861
+	size_t icm_len;
862
+	/** ICM AUX size */
863
+	size_t icm_aux_len;
864
+	/** ICM area
865
+	 *
866
+	 * This is allocated when first needed, and freed only on
867
+	 * final teardown, in order to avoid memory map changes at
868
+	 * runtime.
869
+	 */
849
 	userptr_t icm;
870
 	userptr_t icm;
850
 
871
 
851
 	/** Event queue */
872
 	/** Event queue */

Loading…
Cancel
Save