Ver código fonte

[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 13 anos atrás
pai
commit
6dd4ac77e5
2 arquivos alterados com 217 adições e 81 exclusões
  1. 194
    79
      src/drivers/infiniband/hermon.c
  2. 23
    2
      src/drivers/infiniband/hermon.h

+ 194
- 79
src/drivers/infiniband/hermon.c Ver arquivo

@@ -2136,7 +2136,7 @@ static int hermon_map_vpm ( struct hermon *hermon,
2136 2136
 static int hermon_start_firmware ( struct hermon *hermon ) {
2137 2137
 	struct hermonprm_query_fw fw;
2138 2138
 	unsigned int fw_pages;
2139
-	size_t fw_size;
2139
+	size_t fw_len;
2140 2140
 	physaddr_t fw_base;
2141 2141
 	int rc;
2142 2142
 
@@ -2154,17 +2154,22 @@ static int hermon_start_firmware ( struct hermon *hermon ) {
2154 2154
 	       hermon, fw_pages, ( fw_pages * 4 ) );
2155 2155
 
2156 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 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 2168
 	fw_base = user_to_phys ( hermon->firmware_area, 0 );
2164 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 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 2173
 		DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
2169 2174
 		       hermon, strerror ( rc ) );
2170 2175
 		goto err_map_fa;
@@ -2183,8 +2188,6 @@ static int hermon_start_firmware ( struct hermon *hermon ) {
2183 2188
  err_run_fw:
2184 2189
  err_map_fa:
2185 2190
 	hermon_cmd_unmap_fa ( hermon );
2186
-	ufree ( hermon->firmware_area );
2187
-	hermon->firmware_area = UNULL;
2188 2191
  err_alloc_fa:
2189 2192
  err_query_fw:
2190 2193
 	return rc;
@@ -2202,10 +2205,9 @@ static void hermon_stop_firmware ( struct hermon *hermon ) {
2202 2205
 		DBGC ( hermon, "Hermon %p FATAL could not stop firmware: %s\n",
2203 2206
 		       hermon, strerror ( rc ) );
2204 2207
 		/* Leak memory and return; at least we avoid corruption */
2208
+		hermon->firmware_area = UNULL;
2205 2209
 		return;
2206 2210
 	}
2207
-	ufree ( hermon->firmware_area );
2208
-	hermon->firmware_area = UNULL;
2209 2211
 }
2210 2212
 
2211 2213
 /***************************************************************************
@@ -2285,14 +2287,14 @@ static uint64_t icm_align ( uint64_t icm_offset, size_t len ) {
2285 2287
 }
2286 2288
 
2287 2289
 /**
2288
- * Allocate ICM
2290
+ * Map ICM (allocating if necessary)
2289 2291
  *
2290 2292
  * @v hermon		Hermon device
2291 2293
  * @v init_hca		INIT_HCA structure to fill in
2292 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 2298
 	struct hermonprm_scalar_parameter icm_size;
2297 2299
 	struct hermonprm_scalar_parameter icm_aux_size;
2298 2300
 	uint64_t icm_offset = 0;
@@ -2519,10 +2521,17 @@ static int hermon_alloc_icm ( struct hermon *hermon,
2519 2521
 	/* Allocate ICM data and auxiliary area */
2520 2522
 	DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
2521 2523
 	       hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
2522
-	hermon->icm = umalloc ( icm_aux_len + icm_len );
2523 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 2536
 	icm_phys = user_to_phys ( hermon->icm, 0 );
2528 2537
 
@@ -2559,19 +2568,17 @@ static int hermon_alloc_icm ( struct hermon *hermon,
2559 2568
 	assert ( i == 0 ); /* We don't handle partial failure at present */
2560 2569
  err_map_icm_aux:
2561 2570
 	hermon_cmd_unmap_icm_aux ( hermon );
2562
-	ufree ( hermon->icm );
2563
-	hermon->icm = UNULL;
2564 2571
  err_alloc:
2565 2572
  err_set_icm_size:
2566 2573
 	return rc;
2567 2574
 }
2568 2575
 
2569 2576
 /**
2570
- * Free ICM
2577
+ * Unmap ICM
2571 2578
  *
2572 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 2582
 	struct hermonprm_scalar_parameter unmap_icm;
2576 2583
 	int i;
2577 2584
 
@@ -2587,13 +2594,11 @@ static void hermon_free_icm ( struct hermon *hermon ) {
2587 2594
 				       &unmap_icm );
2588 2595
 	}
2589 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,19 +2607,22 @@ static void hermon_free_icm ( struct hermon *hermon ) {
2602 2607
  * Reset device
2603 2608
  *
2604 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 2613
 	struct pci_config_backup backup;
2610 2614
 	static const uint8_t backup_exclude[] =
2611 2615
 		PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
2612 2616
 
2617
+	/* Perform device reset and preserve PCI configuration */
2613 2618
 	pci_backup ( pci, &backup, backup_exclude );
2614 2619
 	writel ( HERMON_RESET_MAGIC,
2615 2620
 		 ( hermon->config + HERMON_RESET_OFFSET ) );
2616 2621
 	mdelay ( HERMON_RESET_WAIT_TIME_MS );
2617 2622
 	pci_restore ( pci, &backup, backup_exclude );
2623
+
2624
+	/* Reset command interface toggle */
2625
+	hermon->toggle = 0;
2618 2626
 }
2619 2627
 
2620 2628
 /**
@@ -2686,6 +2694,118 @@ static int hermon_configure_special_qps ( struct hermon *hermon ) {
2686 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 2811
  * Infiniband link-layer operations
@@ -2699,11 +2819,15 @@ static int hermon_configure_special_qps ( struct hermon *hermon ) {
2699 2819
  * @v ibdev		Infiniband device
2700 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 2823
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2704 2824
 	union hermonprm_set_port set_port;
2705 2825
 	int rc;
2706 2826
 
2827
+	/* Open hardware */
2828
+	if ( ( rc = hermon_open ( hermon ) ) != 0 )
2829
+		goto err_open;
2830
+
2707 2831
 	/* Set port parameters */
2708 2832
 	memset ( &set_port, 0, sizeof ( set_port ) );
2709 2833
 	MLX_FILL_8 ( &set_port.ib, 0,
@@ -2724,20 +2848,26 @@ static int hermon_open ( struct ib_device *ibdev ) {
2724 2848
 					  &set_port ) ) != 0 ) {
2725 2849
 		DBGC ( hermon, "Hermon %p port %d could not set port: %s\n",
2726 2850
 		       hermon, ibdev->port, strerror ( rc ) );
2727
-		return rc;
2851
+		goto err_set_port;
2728 2852
 	}
2729 2853
 
2730 2854
 	/* Initialise port */
2731 2855
 	if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port ) ) != 0 ) {
2732 2856
 		DBGC ( hermon, "Hermon %p port %d could not initialise port: "
2733 2857
 		       "%s\n", hermon, ibdev->port, strerror ( rc ) );
2734
-		return rc;
2858
+		goto err_init_port;
2735 2859
 	}
2736 2860
 
2737 2861
 	/* Update MAD parameters */
2738 2862
 	ib_smc_update ( ibdev, hermon_mad );
2739 2863
 
2740 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,15 +2875,19 @@ static int hermon_open ( struct ib_device *ibdev ) {
2745 2875
  *
2746 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 2879
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
2750 2880
 	int rc;
2751 2881
 
2882
+	/* Close port */
2752 2883
 	if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
2753 2884
 		DBGC ( hermon, "Hermon %p port %d could not close port: %s\n",
2754 2885
 		       hermon, ibdev->port, strerror ( rc ) );
2755 2886
 		/* Nothing we can do about this */
2756 2887
 	}
2888
+
2889
+	/* Close hardware */
2890
+	hermon_close ( hermon );
2757 2891
 }
2758 2892
 
2759 2893
 /**
@@ -2883,8 +3017,8 @@ static struct ib_device_operations hermon_ib_operations = {
2883 3017
 	.post_recv	= hermon_post_recv,
2884 3018
 	.poll_cq	= hermon_poll_cq,
2885 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 3022
 	.mcast_attach	= hermon_mcast_attach,
2889 3023
 	.mcast_detach	= hermon_mcast_detach,
2890 3024
 	.set_port_info	= hermon_inform_sma,
@@ -3073,6 +3207,10 @@ static int hermon_eth_open ( struct net_device *netdev ) {
3073 3207
 	union hermonprm_set_port set_port;
3074 3208
 	int rc;
3075 3209
 
3210
+	/* Open hardware */
3211
+	if ( ( rc = hermon_open ( hermon ) ) != 0 )
3212
+		goto err_open;
3213
+
3076 3214
 	/* Allocate completion queue */
3077 3215
 	port->eth_cq = ib_create_cq ( ibdev, HERMON_ETH_NUM_CQES,
3078 3216
 				      &hermon_eth_cq_op );
@@ -3167,6 +3305,8 @@ static int hermon_eth_open ( struct net_device *netdev ) {
3167 3305
  err_create_qp:
3168 3306
 	ib_destroy_cq ( ibdev, port->eth_cq );
3169 3307
  err_create_cq:
3308
+	hermon_close ( hermon );
3309
+ err_open:
3170 3310
 	return rc;
3171 3311
 }
3172 3312
 
@@ -3191,6 +3331,9 @@ static void hermon_eth_close ( struct net_device *netdev ) {
3191 3331
 	/* Tear down the queues */
3192 3332
 	ib_destroy_qp ( ibdev, port->eth_qp );
3193 3333
 	ib_destroy_cq ( ibdev, port->eth_cq );
3334
+
3335
+	/* Close hardware */
3336
+	hermon_close ( hermon );
3194 3337
 }
3195 3338
 
3196 3339
 /** Hermon Ethernet network device operations */
@@ -3562,6 +3705,8 @@ static struct hermon * hermon_alloc ( void ) {
3562 3705
  */
3563 3706
 static void hermon_free ( struct hermon *hermon ) {
3564 3707
 
3708
+	ufree ( hermon->icm );
3709
+	ufree ( hermon->firmware_area );
3565 3710
 	free_dma ( hermon->mailbox_out, HERMON_MBOX_SIZE );
3566 3711
 	free_dma ( hermon->mailbox_in, HERMON_MBOX_SIZE );
3567 3712
 	free ( hermon );
@@ -3571,9 +3716,9 @@ static void hermon_free ( struct hermon *hermon ) {
3571 3716
  * Initialise Hermon PCI parameters
3572 3717
  *
3573 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 3723
 	/* Fix up PCI device */
3579 3724
 	adjust_pci_device ( pci );
@@ -3597,7 +3742,6 @@ static int hermon_probe ( struct pci_device *pci ) {
3597 3742
 	struct ib_device *ibdev;
3598 3743
 	struct net_device *netdev;
3599 3744
 	struct hermon_port *port;
3600
-	struct hermonprm_init_hca init_hca;
3601 3745
 	unsigned int i;
3602 3746
 	int rc;
3603 3747
 
@@ -3608,12 +3752,13 @@ static int hermon_probe ( struct pci_device *pci ) {
3608 3752
 		goto err_alloc;
3609 3753
 	}
3610 3754
 	pci_set_drvdata ( pci, hermon );
3755
+	hermon->pci = pci;
3611 3756
 
3612 3757
 	/* Initialise PCI parameters */
3613
-	hermon_pci_init ( hermon, pci );
3758
+	hermon_pci_init ( hermon );
3614 3759
 
3615 3760
 	/* Reset device */
3616
-	hermon_reset ( hermon, pci );
3761
+	hermon_reset ( hermon );
3617 3762
 
3618 3763
 	/* Start firmware */
3619 3764
 	if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
@@ -3650,34 +3795,9 @@ static int hermon_probe ( struct pci_device *pci ) {
3650 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 3802
 	/* Determine port types */
3683 3803
 	for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) {
@@ -3693,6 +3813,10 @@ static int hermon_probe ( struct pci_device *pci ) {
3693 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 3820
 	return 0;
3697 3821
 
3698 3822
 	i = hermon->cap.num_ports;
@@ -3702,14 +3826,8 @@ static int hermon_probe ( struct pci_device *pci ) {
3702 3826
 		port->type->unregister_dev ( hermon, port );
3703 3827
 	}
3704 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 3831
 	i = hermon->cap.num_ports;
3714 3832
  err_alloc_netdev:
3715 3833
 	for ( i-- ; ( signed int ) i >= 0 ; i-- ) {
@@ -3742,10 +3860,6 @@ static void hermon_remove ( struct pci_device *pci ) {
3742 3860
 		port = &hermon->port[i];
3743 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 3863
 	for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) {
3750 3864
 		netdev_nullify ( hermon->port[i].netdev );
3751 3865
 		netdev_put ( hermon->port[i].netdev );
@@ -3773,9 +3887,10 @@ static int hermon_bofm_probe ( struct pci_device *pci ) {
3773 3887
 		goto err_alloc;
3774 3888
 	}
3775 3889
 	pci_set_drvdata ( pci, hermon );
3890
+	hermon->pci = pci;
3776 3891
 
3777 3892
 	/* Initialise PCI parameters */
3778
-	hermon_pci_init ( hermon, pci );
3893
+	hermon_pci_init ( hermon );
3779 3894
 
3780 3895
 	/* Initialise BOFM device */
3781 3896
 	bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations );

+ 23
- 2
src/drivers/infiniband/hermon.h Ver arquivo

@@ -829,6 +829,8 @@ struct hermon_port {
829 829
 
830 830
 /** A Hermon device */
831 831
 struct hermon {
832
+	/** PCI device */
833
+	struct pci_device *pci;
832 834
 	/** PCI configuration registers */
833 835
 	void *config;
834 836
 	/** PCI user Access Region */
@@ -841,11 +843,30 @@ struct hermon {
841 843
 	/** Command output mailbox */
842 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 857
 	userptr_t firmware_area;
846 858
 	/** ICM map */
847 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 870
 	userptr_t icm;
850 871
 
851 872
 	/** Event queue */

Carregando…
Cancelar
Salvar