summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/efi
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/net/efi')
-rw-r--r--src/drivers/net/efi/nii.c59
-rw-r--r--src/drivers/net/efi/snp.c66
-rw-r--r--src/drivers/net/efi/snponly.c2
3 files changed, 85 insertions, 42 deletions
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
index 833462e77..be5bce4b4 100644
--- a/src/drivers/net/efi/nii.c
+++ b/src/drivers/net/efi/nii.c
@@ -222,7 +222,7 @@ static int nii_pci_open ( struct nii_nic *nii ) {
/* Locate PCI I/O protocol */
if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
- &pci_device ) ) != 0 ) {
+ &pci_device, 0 ) ) != 0 ) {
DBGC ( nii, "NII %s could not locate PCI I/O protocol: %s\n",
nii->dev.name, strerror ( rc ) );
goto err_locate;
@@ -921,18 +921,17 @@ static int nii_set_station_address ( struct nii_nic *nii,
* Set receive filters
*
* @v nii NII NIC
+ * @v flags Flags
* @ret rc Return status code
*/
-static int nii_set_rx_filters ( struct nii_nic *nii ) {
+static int nii_set_rx_filters ( struct nii_nic *nii, unsigned int flags ) {
uint32_t implementation = nii->undi->Implementation;
- unsigned int flags;
unsigned int op;
int stat;
int rc;
/* Construct receive filter set */
- flags = ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
- PXE_OPFLAGS_RECEIVE_FILTER_UNICAST );
+ flags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
if ( implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED )
flags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED )
@@ -944,8 +943,12 @@ static int nii_set_rx_filters ( struct nii_nic *nii ) {
op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags );
if ( ( stat = nii_issue ( nii, op ) ) < 0 ) {
rc = -EIO_STAT ( stat );
- DBGC ( nii, "NII %s could not set receive filters %#04x: %s\n",
- nii->dev.name, flags, strerror ( rc ) );
+ DBGC ( nii, "NII %s could not %s%sable receive filters "
+ "%#04x: %s\n", nii->dev.name,
+ ( ( flags & PXE_OPFLAGS_RECEIVE_FILTER_ENABLE ) ?
+ "en" : "" ),
+ ( ( flags & PXE_OPFLAGS_RECEIVE_FILTER_DISABLE ) ?
+ "dis" : "" ), flags, strerror ( rc ) );
return rc;
}
@@ -953,6 +956,28 @@ static int nii_set_rx_filters ( struct nii_nic *nii ) {
}
/**
+ * Enable receive filters
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_enable_rx_filters ( struct nii_nic *nii ) {
+
+ return nii_set_rx_filters ( nii, PXE_OPFLAGS_RECEIVE_FILTER_ENABLE );
+}
+
+/**
+ * Disable receive filters
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_disable_rx_filters ( struct nii_nic *nii ) {
+
+ return nii_set_rx_filters ( nii, PXE_OPFLAGS_RECEIVE_FILTER_DISABLE );
+}
+
+/**
* Transmit packet
*
* @v netdev Network device
@@ -1175,13 +1200,25 @@ static int nii_open ( struct net_device *netdev ) {
/* Treat as non-fatal */
}
- /* Set receive filters */
- if ( ( rc = nii_set_rx_filters ( nii ) ) != 0 )
- goto err_set_rx_filters;
+ /* Disable receive filters
+ *
+ * We have no reason to disable receive filters here (or
+ * anywhere), but some NII drivers have a bug which prevents
+ * packets from being received unless we attempt to disable
+ * the receive filters.
+ *
+ * Ignore any failures, since we genuinely don't care if the
+ * NII driver cannot disable the filters.
+ */
+ nii_disable_rx_filters ( nii );
+
+ /* Enable receive filters */
+ if ( ( rc = nii_enable_rx_filters ( nii ) ) != 0 )
+ goto err_enable_rx_filters;
return 0;
- err_set_rx_filters:
+ err_enable_rx_filters:
nii_shutdown ( nii );
err_initialise:
return rc;
diff --git a/src/drivers/net/efi/snp.c b/src/drivers/net/efi/snp.c
index fbd606902..1920cdbc5 100644
--- a/src/drivers/net/efi/snp.c
+++ b/src/drivers/net/efi/snp.c
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_snp.h>
+#include <ipxe/efi/efi_utils.h>
#include "snpnet.h"
#include "nii.h"
@@ -40,31 +41,46 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Check to see if driver supports a device
*
* @v device EFI device handle
+ * @v protocol Protocol GUID
* @ret rc Return status code
*/
-static int snp_supported ( EFI_HANDLE device ) {
+static int snp_nii_supported ( EFI_HANDLE device, EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE parent;
EFI_STATUS efirc;
+ int rc;
/* Check that this is not a device we are providing ourselves */
if ( find_snpdev ( device ) != NULL ) {
- DBGCP ( device, "SNP %s is provided by this binary\n",
+ DBGCP ( device, "HANDLE %s is provided by this binary\n",
efi_handle_name ( device ) );
return -ENOTTY;
}
- /* Test for presence of simple network protocol */
- if ( ( efirc = bs->OpenProtocol ( device,
- &efi_simple_network_protocol_guid,
+ /* Test for presence of protocol */
+ if ( ( efirc = bs->OpenProtocol ( device, protocol,
NULL, efi_image_handle, device,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
- DBGCP ( device, "SNP %s is not an SNP device\n",
- efi_handle_name ( device ) );
+ DBGCP ( device, "HANDLE %s is not a %s device\n",
+ efi_handle_name ( device ),
+ efi_guid_ntoa ( protocol ) );
return -EEFI ( efirc );
}
- DBGC ( device, "SNP %s is an SNP device\n",
- efi_handle_name ( device ) );
+ /* Check that there are no instances of this protocol further
+ * up this device path.
+ */
+ if ( ( rc = efi_locate_device ( device, protocol,
+ &parent, 1 ) ) == 0 ) {
+ DBGC2 ( device, "HANDLE %s has %s-supporting parent ",
+ efi_handle_name ( device ),
+ efi_guid_ntoa ( protocol ) );
+ DBGC2 ( device, "%s\n", efi_handle_name ( parent ) );
+ return -ENOTTY;
+ }
+
+ DBGC ( device, "HANDLE %s is a %s device\n",
+ efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
return 0;
}
@@ -74,30 +90,20 @@ static int snp_supported ( EFI_HANDLE device ) {
* @v device EFI device handle
* @ret rc Return status code
*/
-static int nii_supported ( EFI_HANDLE device ) {
- EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
- EFI_STATUS efirc;
+static int snp_supported ( EFI_HANDLE device ) {
- /* Check that this is not a device we are providing ourselves */
- if ( find_snpdev ( device ) != NULL ) {
- DBGCP ( device, "NII %s is provided by this binary\n",
- efi_handle_name ( device ) );
- return -ENOTTY;
- }
+ return snp_nii_supported ( device, &efi_simple_network_protocol_guid );
+}
- /* Test for presence of NII protocol */
- if ( ( efirc = bs->OpenProtocol ( device,
- &efi_nii31_protocol_guid,
- NULL, efi_image_handle, device,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
- DBGCP ( device, "NII %s is not an NII device\n",
- efi_handle_name ( device ) );
- return -EEFI ( efirc );
- }
- DBGC ( device, "NII %s is an NII device\n",
- efi_handle_name ( device ) );
+/**
+ * Check to see if driver supports a device
+ *
+ * @v device EFI device handle
+ * @ret rc Return status code
+ */
+static int nii_supported ( EFI_HANDLE device ) {
- return 0;
+ return snp_nii_supported ( device, &efi_nii31_protocol_guid );
}
/** EFI SNP driver */
diff --git a/src/drivers/net/efi/snponly.c b/src/drivers/net/efi/snponly.c
index cb7ea1bbc..674e0a050 100644
--- a/src/drivers/net/efi/snponly.c
+++ b/src/drivers/net/efi/snponly.c
@@ -80,7 +80,7 @@ static int chained_locate ( struct chained_protocol *chained ) {
/* Locate handle supporting this protocol */
if ( ( rc = efi_locate_device ( device, chained->protocol,
- &parent ) ) != 0 ) {
+ &parent, 0 ) ) != 0 ) {
DBGC ( device, "CHAINED %s does not support %s: %s\n",
efi_handle_name ( device ),
efi_guid_ntoa ( chained->protocol ), strerror ( rc ) );