]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net/sonic: Improve receive descriptor status flag check
authorFinn Thain <fthain@telegraphics.com.au>
Wed, 22 Jan 2020 22:07:26 +0000 (09:07 +1100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 23 Jan 2020 20:24:37 +0000 (21:24 +0100)
After sonic_tx_timeout() calls sonic_init(), it can happen that
sonic_rx() will subsequently encounter a receive descriptor with no
flags set. Remove the comment that says that this can't happen.

When giving a receive descriptor to the SONIC, clear the descriptor
status field. That way, any rx descriptor with flags set can only be
a newly received packet.

Don't process a descriptor without the LPKT bit set. The buffer is
still in use by the SONIC.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/natsemi/sonic.c

index 2cee702f49b8654aeef41a4c0dd85beda4f922cf..9d2bddc4951b1474299ccab0d0f5e078432d8c52 100644 (file)
@@ -434,7 +434,6 @@ static int index_from_addr(struct sonic_local *lp, dma_addr_t addr,
 static void sonic_rx(struct net_device *dev)
 {
        struct sonic_local *lp = netdev_priv(dev);
-       int status;
        int entry = lp->cur_rx;
        int prev_entry = lp->eol_rx;
 
@@ -445,9 +444,10 @@ static void sonic_rx(struct net_device *dev)
                u16 bufadr_l;
                u16 bufadr_h;
                int pkt_len;
+               u16 status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
 
-               status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
-               if (status & SONIC_RCR_PRX) {
+               /* If the RD has LPKT set, the chip has finished with the RB */
+               if ((status & SONIC_RCR_PRX) && (status & SONIC_RCR_LPKT)) {
                        u32 addr = (sonic_rda_get(dev, entry,
                                                  SONIC_RD_PKTPTR_H) << 16) |
                                   sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L);
@@ -495,10 +495,6 @@ static void sonic_rx(struct net_device *dev)
                        bufadr_h = (unsigned long)new_laddr >> 16;
                        sonic_rra_put(dev, i, SONIC_RR_BUFADR_L, bufadr_l);
                        sonic_rra_put(dev, i, SONIC_RR_BUFADR_H, bufadr_h);
-               } else {
-                       /* This should only happen, if we enable accepting broken packets. */
-               }
-               if (status & SONIC_RCR_LPKT) {
                        /*
                         * this was the last packet out of the current receive buffer
                         * give the buffer back to the SONIC
@@ -511,12 +507,11 @@ static void sonic_rx(struct net_device *dev)
                                          __func__);
                                SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
                        }
-               } else
-                       printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
-                            dev->name);
+               }
                /*
                 * give back the descriptor
                 */
+               sonic_rda_put(dev, entry, SONIC_RD_STATUS, 0);
                sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
 
                prev_entry = entry;