diff options
author | Michael Brown <mcb30@ipxe.org> | 2014-07-30 14:21:10 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2014-07-30 14:27:07 +0100 |
commit | dc18fd76488476c8bd5b70ba228576d328280670 (patch) | |
tree | 367cbb53850d4379742d465ced0a08918abe5fbd | |
parent | 793a806611f5a7b3a404afb27c837a3da381952e (diff) | |
download | ipxe-dc18fd76488476c8bd5b70ba228576d328280670.tar.gz |
[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>
-rw-r--r-- | src/arch/x86/prefix/efidrvprefix.c | 4 | ||||
-rw-r--r-- | src/arch/x86/prefix/efiprefix.c | 5 | ||||
-rw-r--r-- | src/include/ipxe/efi/efi_snp.h | 19 | ||||
-rw-r--r-- | src/interface/efi/efi_download.c | 4 | ||||
-rw-r--r-- | src/interface/efi/efi_snp.c | 57 |
5 files changed, 53 insertions, 36 deletions
diff --git a/src/arch/x86/prefix/efidrvprefix.c b/src/arch/x86/prefix/efidrvprefix.c index 280e3353..3daefd00 100644 --- a/src/arch/x86/prefix/efidrvprefix.c +++ b/src/arch/x86/prefix/efidrvprefix.c @@ -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; } diff --git a/src/arch/x86/prefix/efiprefix.c b/src/arch/x86/prefix/efiprefix.c index a0347680..b0bf99c6 100644 --- a/src/arch/x86/prefix/efiprefix.c +++ b/src/arch/x86/prefix/efiprefix.c @@ -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: diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h index 06483cfb..87798ccc 100644 --- a/src/include/ipxe/efi/efi_snp.h +++ b/src/include/ipxe/efi/efi_snp.h @@ -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 */ diff --git a/src/interface/efi/efi_download.c b/src/interface/efi/efi_download.c index 80279f7f..522276ac 100644 --- a/src/interface/efi/efi_download.c +++ b/src/interface/efi/efi_download.c @@ -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; diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index fd3aad4c..a301f3b4 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -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 ); } |