Преглед на файлове

[efi] Default to releasing network devices for use via SNP

We currently treat network devices as available for use via the SNP
API only if RX queue processing has been frozen.  (This is similar in
spirit to the way that RX queue processing is frozen for the network
device currently exposed via the PXE API.)

The default state of a freshly created network device is for the RX
queue to not be frozen, and thus to be unavailable for use via SNP.
This causes problems when devices are added through code paths other
than _efidrv_start() (which explicitly releases devices for use via
SNP).

We don't actually need to freeze RX queue processing, since calls via
the SNP API will always use netdev_poll() rather than net_poll(), and
so will never trigger the RX queue processing code path anyway.

We can therefore simplify the code to use a single global flag to
indicate whether network devices are claimed for use by iPXE or
available for use via SNP.  Using a global flag allows the default
state for dynamically created network devices to behave sensibly.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown преди 9 години
родител
ревизия
dc18fd7648
променени са 5 файла, в които са добавени 53 реда и са изтрити 36 реда
  1. 0
    4
      src/arch/x86/prefix/efidrvprefix.c
  2. 5
    0
      src/arch/x86/prefix/efiprefix.c
  3. 17
    2
      src/include/ipxe/efi/efi_snp.h
  4. 4
    0
      src/interface/efi/efi_download.c
  5. 27
    30
      src/interface/efi/efi_snp.c

+ 0
- 4
src/arch/x86/prefix/efidrvprefix.c Целия файл

@@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
22 22
 #include <stdlib.h>
23 23
 #include <ipxe/init.h>
24 24
 #include <ipxe/efi/efi.h>
25
-#include <ipxe/efi/efi_snp.h>
26 25
 
27 26
 /**
28 27
  * EFI entry point
@@ -43,8 +42,5 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
43 42
 	initialise();
44 43
 	startup();
45 44
 
46
-	/* Release network devices for use via SNP */
47
-	efi_snp_release();
48
-
49 45
 	return 0;
50 46
 }

+ 5
- 0
src/arch/x86/prefix/efiprefix.c Целия файл

@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
24 24
 #include <ipxe/device.h>
25 25
 #include <ipxe/efi/efi.h>
26 26
 #include <ipxe/efi/efi_driver.h>
27
+#include <ipxe/efi/efi_snp.h>
27 28
 #include <ipxe/efi/efi_autoboot.h>
28 29
 
29 30
 /**
@@ -45,6 +46,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
45 46
 	/* Record autoboot device (if any) */
46 47
 	efi_set_autoboot();
47 48
 
49
+	/* Claim SNP devices for use by iPXE */
50
+	efi_snp_claim();
51
+
48 52
 	/* Call to main() */
49 53
 	if ( ( rc = main() ) != 0 ) {
50 54
 		efirc = EFIRC ( rc );
@@ -52,6 +56,7 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
52 56
 	}
53 57
 
54 58
  err_main:
59
+	efi_snp_release();
55 60
 	efi_loaded_image->Unload ( image_handle );
56 61
 	efi_driver_reconnect_all();
57 62
  err_init:

+ 17
- 2
src/include/ipxe/efi/efi_snp.h Целия файл

@@ -78,7 +78,22 @@ extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
78 78
 extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
79 79
 extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle );
80 80
 extern struct efi_snp_device * last_opened_snpdev ( void );
81
-extern void efi_snp_claim ( void );
82
-extern void efi_snp_release ( void );
81
+extern void efi_snp_set_claimed ( int claimed );
82
+
83
+/**
84
+ * Claim network devices for use by iPXE
85
+ *
86
+ */
87
+static inline void efi_snp_claim ( void ) {
88
+	efi_snp_set_claimed ( 1 );
89
+}
90
+
91
+/**
92
+ * Release network devices for use via SNP
93
+ *
94
+ */
95
+static inline void efi_snp_release ( void ) {
96
+	efi_snp_set_claimed ( 0 );
97
+}
83 98
 
84 99
 #endif /* _IPXE_EFI_SNP_H */

+ 4
- 0
src/interface/efi/efi_download.c Целия файл

@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
26 26
 #include <ipxe/iobuf.h>
27 27
 #include <ipxe/xfer.h>
28 28
 #include <ipxe/efi/efi.h>
29
+#include <ipxe/efi/efi_snp.h>
29 30
 #include <ipxe/efi/efi_download.h>
30 31
 
31 32
 /** iPXE download protocol GUID */
@@ -63,6 +64,8 @@ static void efi_download_close ( struct efi_download_file *file, int rc ) {
63 64
 	file->finish_callback ( file->context, EFIRC ( rc ) );
64 65
 
65 66
 	intf_shutdown ( &file->xfer, rc );
67
+
68
+	efi_snp_release();
66 69
 }
67 70
 
68 71
 /**
@@ -147,6 +150,7 @@ efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
147 150
 		return EFIRC ( rc );
148 151
 	}
149 152
 
153
+	efi_snp_claim();
150 154
 	file->pos = 0;
151 155
 	file->data_callback = DataCallback;
152 156
 	file->finish_callback = FinishCallback;

+ 27
- 30
src/interface/efi/efi_snp.c Целия файл

@@ -67,6 +67,9 @@ static EFI_GUID efi_load_file_protocol_guid
67 67
 /** List of SNP devices */
68 68
 static LIST_HEAD ( efi_snp_devices );
69 69
 
70
+/** Network devices are currently claimed for use by iPXE */
71
+static int efi_snp_claimed;
72
+
70 73
 /**
71 74
  * Set EFI SNP mode state
72 75
  *
@@ -83,7 +86,7 @@ static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
83 86
 	} else if ( ! netdev_is_open ( netdev ) ) {
84 87
 		/* Network device not opened; report as Started */
85 88
 		mode->State = EfiSimpleNetworkStarted;
86
-	} else if ( ! netdev_rx_frozen ( netdev ) ) {
89
+	} else if ( efi_snp_claimed ) {
87 90
 		/* Network device opened but claimed for use by iPXE; report
88 91
 		 * as Started to inhibit receive polling.
89 92
 		 */
@@ -162,7 +165,7 @@ efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
162 165
 	DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
163 166
 
164 167
 	/* Fail if net device is currently claimed for use by iPXE */
165
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
168
+	if ( efi_snp_claimed )
166 169
 		return EFI_NOT_READY;
167 170
 
168 171
 	snpdev->started = 1;
@@ -184,7 +187,7 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
184 187
 	DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
185 188
 
186 189
 	/* Fail if net device is currently claimed for use by iPXE */
187
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
190
+	if ( efi_snp_claimed )
188 191
 		return EFI_NOT_READY;
189 192
 
190 193
 	snpdev->started = 0;
@@ -212,7 +215,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
212 215
 		( ( unsigned long ) extra_tx_bufsize ) );
213 216
 
214 217
 	/* Fail if net device is currently claimed for use by iPXE */
215
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
218
+	if ( efi_snp_claimed )
216 219
 		return EFI_NOT_READY;
217 220
 
218 221
 	if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
@@ -242,7 +245,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
242 245
 		snpdev, ( ext_verify ? "with" : "without" ) );
243 246
 
244 247
 	/* Fail if net device is currently claimed for use by iPXE */
245
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
248
+	if ( efi_snp_claimed )
246 249
 		return EFI_NOT_READY;
247 250
 
248 251
 	netdev_close ( snpdev->netdev );
@@ -272,7 +275,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
272 275
 	DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
273 276
 
274 277
 	/* Fail if net device is currently claimed for use by iPXE */
275
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
278
+	if ( efi_snp_claimed )
276 279
 		return EFI_NOT_READY;
277 280
 
278 281
 	netdev_close ( snpdev->netdev );
@@ -309,7 +312,7 @@ efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
309 312
 	}
310 313
 
311 314
 	/* Fail if net device is currently claimed for use by iPXE */
312
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
315
+	if ( efi_snp_claimed )
313 316
 		return EFI_NOT_READY;
314 317
 
315 318
 	/* Lie through our teeth, otherwise MNP refuses to accept us */
@@ -335,7 +338,7 @@ efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
335 338
 		( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
336 339
 
337 340
 	/* Fail if net device is currently claimed for use by iPXE */
338
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
341
+	if ( efi_snp_claimed )
339 342
 		return EFI_NOT_READY;
340 343
 
341 344
 	/* Set the MAC address */
@@ -372,7 +375,7 @@ efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
372 375
 		( reset ? " reset" : "" ) );
373 376
 
374 377
 	/* Fail if net device is currently claimed for use by iPXE */
375
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
378
+	if ( efi_snp_claimed )
376 379
 		return EFI_NOT_READY;
377 380
 
378 381
 	/* Gather statistics */
@@ -424,7 +427,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
424 427
 	DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
425 428
 
426 429
 	/* Fail if net device is currently claimed for use by iPXE */
427
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
430
+	if ( efi_snp_claimed )
428 431
 		return EFI_NOT_READY;
429 432
 
430 433
 	/* Try to hash the address */
@@ -461,7 +464,7 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
461 464
 		DBGC2_HDA ( snpdev, offset, data, len );
462 465
 
463 466
 	/* Fail if net device is currently claimed for use by iPXE */
464
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
467
+	if ( efi_snp_claimed )
465 468
 		return EFI_NOT_READY;
466 469
 
467 470
 	return EFI_UNSUPPORTED;
@@ -484,7 +487,7 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
484 487
 	DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
485 488
 
486 489
 	/* Fail if net device is currently claimed for use by iPXE */
487
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
490
+	if ( efi_snp_claimed )
488 491
 		return EFI_NOT_READY;
489 492
 
490 493
 	/* Poll the network device */
@@ -583,7 +586,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
583 586
 	DBGC2 ( snpdev, "\n" );
584 587
 
585 588
 	/* Fail if net device is currently claimed for use by iPXE */
586
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
589
+	if ( efi_snp_claimed )
587 590
 		return EFI_NOT_READY;
588 591
 
589 592
 	/* Sanity checks */
@@ -695,7 +698,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
695 698
 		( ( unsigned long ) *len ) );
696 699
 
697 700
 	/* Fail if net device is currently claimed for use by iPXE */
698
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
701
+	if ( efi_snp_claimed )
699 702
 		return EFI_NOT_READY;
700 703
 
701 704
 	/* Poll the network device */
@@ -759,7 +762,7 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
759 762
 		return;
760 763
 
761 764
 	/* Do nothing if net device is currently claimed for use by iPXE */
762
-	if ( ! netdev_rx_frozen ( snpdev->netdev ) )
765
+	if ( efi_snp_claimed )
763 766
 		return;
764 767
 
765 768
 	/* Poll the network device */
@@ -1184,23 +1187,17 @@ struct efi_snp_device * last_opened_snpdev ( void ) {
1184 1187
 }
1185 1188
 
1186 1189
 /**
1187
- * Claim network devices for use by iPXE
1190
+ * Set SNP claimed/released state
1188 1191
  *
1192
+ * @v claimed		Network devices are claimed for use by iPXE
1189 1193
  */
1190
-void efi_snp_claim ( void ) {
1191
-	struct net_device *netdev;
1192
-
1193
-	for_each_netdev ( netdev )
1194
-		netdev_rx_unfreeze ( netdev );
1195
-}
1194
+void efi_snp_set_claimed ( int claimed ) {
1195
+	struct efi_snp_device *snpdev;
1196 1196
 
1197
-/**
1198
- * Release network devices for use via SNP
1199
- *
1200
- */
1201
-void efi_snp_release ( void ) {
1202
-	struct net_device *netdev;
1197
+	/* Claim SNP devices */
1198
+	efi_snp_claimed = claimed;
1203 1199
 
1204
-	for_each_netdev ( netdev )
1205
-		netdev_rx_freeze ( netdev );
1200
+	/* Update SNP mode state for each interface */
1201
+	list_for_each_entry ( snpdev, &efi_snp_devices, list )
1202
+		efi_snp_set_state ( snpdev );
1206 1203
 }

Loading…
Отказ
Запис