]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Default to releasing network devices for use via SNP
authorMichael Brown <mcb30@ipxe.org>
Wed, 30 Jul 2014 13:21:10 +0000 (14:21 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 30 Jul 2014 13:27:07 +0000 (14:27 +0100)
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>
src/arch/x86/prefix/efidrvprefix.c
src/arch/x86/prefix/efiprefix.c
src/include/ipxe/efi/efi_snp.h
src/interface/efi/efi_download.c
src/interface/efi/efi_snp.c

index 280e33535fd7d450ef33b8e43cfeaaae36815676..3daefd00add3904d9d7f4b27d2e5a43f694a5f07 100644 (file)
@@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <stdlib.h>
 #include <ipxe/init.h>
 #include <ipxe/efi/efi.h>
-#include <ipxe/efi/efi_snp.h>
 
 /**
  * EFI entry point
@@ -43,8 +42,5 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
        initialise();
        startup();
 
-       /* Release network devices for use via SNP */
-       efi_snp_release();
-
        return 0;
 }
index a0347680cc0691f4b58150ba193723ba254af645..b0bf99c651537f56f916798d8e30dd14ee236225 100644 (file)
@@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/device.h>
 #include <ipxe/efi/efi.h>
 #include <ipxe/efi/efi_driver.h>
+#include <ipxe/efi/efi_snp.h>
 #include <ipxe/efi/efi_autoboot.h>
 
 /**
@@ -45,6 +46,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
        /* Record autoboot device (if any) */
        efi_set_autoboot();
 
+       /* Claim SNP devices for use by iPXE */
+       efi_snp_claim();
+
        /* Call to main() */
        if ( ( rc = main() ) != 0 ) {
                efirc = EFIRC ( rc );
@@ -52,6 +56,7 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
        }
 
  err_main:
+       efi_snp_release();
        efi_loaded_image->Unload ( image_handle );
        efi_driver_reconnect_all();
  err_init:
index 06483cfbc4730cb931088d1a9aaab16e6abab3dc..87798ccc2238933d141213723241feee8355c963 100644 (file)
@@ -78,7 +78,22 @@ extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
 extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
 extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle );
 extern struct efi_snp_device * last_opened_snpdev ( void );
-extern void efi_snp_claim ( void );
-extern void efi_snp_release ( void );
+extern void efi_snp_set_claimed ( int claimed );
+
+/**
+ * Claim network devices for use by iPXE
+ *
+ */
+static inline void efi_snp_claim ( void ) {
+       efi_snp_set_claimed ( 1 );
+}
+
+/**
+ * Release network devices for use via SNP
+ *
+ */
+static inline void efi_snp_release ( void ) {
+       efi_snp_set_claimed ( 0 );
+}
 
 #endif /* _IPXE_EFI_SNP_H */
index 80279f7f9fe556c885442c0a5cde6636ab89a155..522276ace732372c087654bc062f843ad39dd64e 100644 (file)
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/iobuf.h>
 #include <ipxe/xfer.h>
 #include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_snp.h>
 #include <ipxe/efi/efi_download.h>
 
 /** iPXE download protocol GUID */
@@ -63,6 +64,8 @@ static void efi_download_close ( struct efi_download_file *file, int rc ) {
        file->finish_callback ( file->context, EFIRC ( rc ) );
 
        intf_shutdown ( &file->xfer, rc );
+
+       efi_snp_release();
 }
 
 /**
@@ -147,6 +150,7 @@ efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused,
                return EFIRC ( rc );
        }
 
+       efi_snp_claim();
        file->pos = 0;
        file->data_callback = DataCallback;
        file->finish_callback = FinishCallback;
index fd3aad4cbb01f3e1b92318b6689d540bc60acb66..a301f3b48cf634df94040ebcabf77832e2df9f04 100644 (file)
@@ -67,6 +67,9 @@ static EFI_GUID efi_load_file_protocol_guid
 /** List of SNP devices */
 static LIST_HEAD ( efi_snp_devices );
 
+/** Network devices are currently claimed for use by iPXE */
+static int efi_snp_claimed;
+
 /**
  * Set EFI SNP mode state
  *
@@ -83,7 +86,7 @@ static void efi_snp_set_state ( struct efi_snp_device *snpdev ) {
        } else if ( ! netdev_is_open ( netdev ) ) {
                /* Network device not opened; report as Started */
                mode->State = EfiSimpleNetworkStarted;
-       } else if ( ! netdev_rx_frozen ( netdev ) ) {
+       } else if ( efi_snp_claimed ) {
                /* Network device opened but claimed for use by iPXE; report
                 * as Started to inhibit receive polling.
                 */
@@ -162,7 +165,7 @@ efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
        DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        snpdev->started = 1;
@@ -184,7 +187,7 @@ efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
        DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        snpdev->started = 0;
@@ -212,7 +215,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
                ( ( unsigned long ) extra_tx_bufsize ) );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
@@ -242,7 +245,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
                snpdev, ( ext_verify ? "with" : "without" ) );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        netdev_close ( snpdev->netdev );
@@ -272,7 +275,7 @@ efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
        DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        netdev_close ( snpdev->netdev );
@@ -309,7 +312,7 @@ efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
        }
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* 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,
                ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Set the MAC address */
@@ -372,7 +375,7 @@ efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
                ( reset ? " reset" : "" ) );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Gather statistics */
@@ -424,7 +427,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
        DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Try to hash the address */
@@ -461,7 +464,7 @@ efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
                DBGC2_HDA ( snpdev, offset, data, len );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        return EFI_UNSUPPORTED;
@@ -484,7 +487,7 @@ efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
        DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Poll the network device */
@@ -583,7 +586,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
        DBGC2 ( snpdev, "\n" );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Sanity checks */
@@ -695,7 +698,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
                ( ( unsigned long ) *len ) );
 
        /* Fail if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return EFI_NOT_READY;
 
        /* Poll the network device */
@@ -759,7 +762,7 @@ static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
                return;
 
        /* Do nothing if net device is currently claimed for use by iPXE */
-       if ( ! netdev_rx_frozen ( snpdev->netdev ) )
+       if ( efi_snp_claimed )
                return;
 
        /* Poll the network device */
@@ -1184,23 +1187,17 @@ struct efi_snp_device * last_opened_snpdev ( void ) {
 }
 
 /**
- * Claim network devices for use by iPXE
+ * Set SNP claimed/released state
  *
+ * @v claimed          Network devices are claimed for use by iPXE
  */
-void efi_snp_claim ( void ) {
-       struct net_device *netdev;
-
-       for_each_netdev ( netdev )
-               netdev_rx_unfreeze ( netdev );
-}
+void efi_snp_set_claimed ( int claimed ) {
+       struct efi_snp_device *snpdev;
 
-/**
- * Release network devices for use via SNP
- *
- */
-void efi_snp_release ( void ) {
-       struct net_device *netdev;
+       /* Claim SNP devices */
+       efi_snp_claimed = claimed;
 
-       for_each_netdev ( netdev )
-               netdev_rx_freeze ( netdev );
+       /* Update SNP mode state for each interface */
+       list_for_each_entry ( snpdev, &efi_snp_devices, list )
+               efi_snp_set_state ( snpdev );
 }