summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/efi/snpnet.c
diff options
context:
space:
mode:
authorCurtis Larsen2014-08-05 20:27:10 +0200
committerMichael Brown2014-08-06 00:10:34 +0200
commit2ce1c70166e5bdcda6c17f184755b684fa1811c3 (patch)
tree0f70ea86cd222748357f130d3b47999f9b48b607 /src/drivers/net/efi/snpnet.c
parent[efi] Open device path protocol only at point of use (diff)
downloadipxe-2ce1c70166e5bdcda6c17f184755b684fa1811c3.tar.gz
ipxe-2ce1c70166e5bdcda6c17f184755b684fa1811c3.tar.xz
ipxe-2ce1c70166e5bdcda6c17f184755b684fa1811c3.zip
[efi] Try various possible SNP receive filters
The behavior observed in the Apple EFI (1.10) RecieveFilters() call is: - failure if any of the PROMISCUOUS or MULTICAST filters are included - success if only UNICAST is included, however the result is UNICAST|BROADCAST - success if only UNICAST and BROADCAST are included - if UNICAST, or UNICAST|BROADCAST are used, but the previous call tried (and failed) to set UNICAST|BROADCAST|MULTICAST, then the result is UNICAST|BROADCAST|MULTICAST Work around this apparently broken SNP implementation by trying RecieveFilterMask, then falling back to UNICAST|BROADCAST|MULTICAST, then UNICAST|BROADCAST, and finally UNICAST. Modified-by: Michael Brown <mcb30@ipxe.org> Tested-by: Curtis Larsen <larsen@dixie.edu> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/efi/snpnet.c')
-rw-r--r--src/drivers/net/efi/snpnet.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c
index 79b4946c..0348e7d1 100644
--- a/src/drivers/net/efi/snpnet.c
+++ b/src/drivers/net/efi/snpnet.c
@@ -284,6 +284,42 @@ static void snpnet_poll ( struct net_device *netdev ) {
}
/**
+ * Set receive filters
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int snpnet_rx_filters ( struct net_device *netdev ) {
+ struct snp_nic *snp = netdev->priv;
+ UINT32 filters[] = {
+ snp->snp->Mode->ReceiveFilterMask,
+ ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
+ ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
+ ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ),
+ };
+ unsigned int i;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Try possible receive filters in turn */
+ for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) {
+ efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i],
+ 0, TRUE, 0, NULL );
+ if ( efirc == 0 )
+ return 0;
+ rc = -EEFI ( efirc );
+ DBGC ( snp, "SNP %s could not set receive filters %#02x (have "
+ "%#02x): %s\n", netdev->name, filters[i],
+ snp->snp->Mode->ReceiveFilterSetting, strerror ( rc ) );
+ }
+
+ return rc;
+}
+
+/**
* Open network device
*
* @v netdev Network device
@@ -292,7 +328,6 @@ static void snpnet_poll ( struct net_device *netdev ) {
static int snpnet_open ( struct net_device *netdev ) {
struct snp_nic *snp = netdev->priv;
EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
- UINT32 filters;
EFI_STATUS efirc;
int rc;
@@ -322,16 +357,7 @@ static int snpnet_open ( struct net_device *netdev ) {
}
/* Set receive filters */
- filters = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
- EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
- EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
- EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS |
- EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST );
- if ( ( efirc = snp->snp->ReceiveFilters ( snp->snp, filters, 0, TRUE,
- 0, NULL ) ) != 0 ) {
- rc = -EEFI ( efirc );
- DBGC ( snp, "SNP %s could not set receive filters: %s\n",
- netdev->name, strerror ( rc ) );
+ if ( ( rc = snpnet_rx_filters ( netdev ) ) != 0 ) {
/* Ignore error */
}