]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[rndis] Clear receive filter when closing the device
authorMichael Brown <mcb30@ipxe.org>
Sat, 20 Dec 2014 12:06:35 +0000 (12:06 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sat, 20 Dec 2014 12:06:35 +0000 (12:06 +0000)
On Windows Server 2012 R2, closing and reopening the device will
sometimes result in a non-functional RX datapath.  The root cause is
unknown.  Clearing the receive filter before closing the device seems
to fix the problem.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/rndis.c

index 62a26ad585219eac279cc67c34d8432e880e9630..e21dd195dfc893790f1c65f1764bab2762ff303e 100644 (file)
@@ -828,6 +828,28 @@ void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ) {
        netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
 }
 
+/**
+ * Set receive filter
+ *
+ * @v rndis            RNDIS device
+ * @v filter           Receive filter
+ * @ret rc             Return status code
+ */
+static int rndis_filter ( struct rndis_device *rndis, unsigned int filter ) {
+       uint32_t value = cpu_to_le32 ( filter );
+       int rc;
+
+       /* Set receive filter */
+       if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
+                               &value, sizeof ( value ) ) ) != 0 ) {
+               DBGC ( rndis, "RNDIS %s could not set receive filter to %#08x: "
+                      "%s\n", rndis->name, filter, strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}
+
 /**
  * Open network device
  *
@@ -836,7 +858,6 @@ void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ) {
  */
 static int rndis_open ( struct net_device *netdev ) {
        struct rndis_device *rndis = netdev->priv;
-       uint32_t filter;
        int rc;
 
        /* Open RNDIS device */
@@ -851,17 +872,12 @@ static int rndis_open ( struct net_device *netdev ) {
                goto err_initialise;
 
        /* Set receive filter */
-       filter = cpu_to_le32 ( RNDIS_FILTER_UNICAST |
-                              RNDIS_FILTER_MULTICAST |
-                              RNDIS_FILTER_ALL_MULTICAST |
-                              RNDIS_FILTER_BROADCAST |
-                              RNDIS_FILTER_PROMISCUOUS );
-       if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
-                               &filter, sizeof ( filter ) ) ) != 0 ) {
-               DBGC ( rndis, "RNDIS %s could not set receive filter: %s\n",
-                      rndis->name, strerror ( rc ) );
+       if ( ( rc = rndis_filter ( rndis, ( RNDIS_FILTER_UNICAST |
+                                           RNDIS_FILTER_MULTICAST |
+                                           RNDIS_FILTER_ALL_MULTICAST |
+                                           RNDIS_FILTER_BROADCAST |
+                                           RNDIS_FILTER_PROMISCUOUS ) ) ) != 0)
                goto err_set_filter;
-       }
 
        /* Update link status */
        if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
@@ -887,6 +903,9 @@ static int rndis_open ( struct net_device *netdev ) {
 static void rndis_close ( struct net_device *netdev ) {
        struct rndis_device *rndis = netdev->priv;
 
+       /* Clear receive filter */
+       rndis_filter ( rndis, 0 );
+
        /* Halt RNDIS device */
        rndis_halt ( rndis );