aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/net/efi/nii.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
index 833462e..5d9aea8 100644
--- a/src/drivers/net/efi/nii.c
+++ b/src/drivers/net/efi/nii.c
@@ -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;