]> git.proxmox.com Git - mirror_ubuntu-bionic-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)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 6 Mar 2020 07:13:20 +0000 (02:13 -0500)
BugLink: https://bugs.launchpad.net/bugs/1864261
commit 94b166349503957079ef5e7d6f667f157aea014a upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/ethernet/natsemi/sonic.c

index d5648bc655e36dcc927aad841c2da4909c4b0f79..676366d17bec5760976ec7c9f1c8f4b26e370f5c 100644 (file)
@@ -426,7 +426,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;
 
@@ -437,9 +436,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);
@@ -487,10 +487,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
@@ -503,12 +499,11 @@ static void sonic_rx(struct net_device *dev)
                                        printk("%s: rx buffer exhausted\n", dev->name);
                                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;