jme: Fix the race on the RX path against hardware for jumbo frames
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 12 Jun 2012 06:22:13 +0000 (14:22 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 12 Jun 2012 06:22:13 +0000 (14:22 +0800)
Hardware will not clear OWN bit except the first RX desc, so its
following RX desc's OWN bit should be cleared before set the OWN
bit on the first RX desc again, i.e. before the first RX desc get
reused.

sys/dev/netif/jme/if_jme.c

index 108f7f8..21f16ec 100644 (file)
@@ -2113,12 +2113,35 @@ jme_rxpkt(struct jme_rxdata *rdata)
 
        cons = rdata->jme_rx_cons;
        desc = &rdata->jme_rx_ring[cons];
+
        flags = le32toh(desc->flags);
        status = le32toh(desc->buflen);
        hash = le32toh(desc->addr_hi);
        hashinfo = le32toh(desc->addr_lo);
        nsegs = JME_RX_NSEGS(status);
 
+       if (nsegs > 1) {
+               /* Skip the first descriptor. */
+               JME_DESC_INC(cons, rdata->jme_rx_desc_cnt);
+
+               /*
+                * Clear the OWN bit of the following RX descriptors;
+                * hardware will not clear the OWN bit except the first
+                * RX descriptor.
+                *
+                * Since the first RX descriptor is setup, i.e. OWN bit
+                * on, before its followins RX descriptors, leaving the
+                * OWN bit on the following RX descriptors will trick
+                * the hardware into thinking that the following RX
+                * descriptors are ready to be used too.
+                */
+               for (count = 1; count < nsegs; count++,
+                    JME_DESC_INC(cons, rdata->jme_rx_desc_cnt))
+                       rdata->jme_rx_ring[cons].flags = 0;
+
+               cons = rdata->jme_rx_cons;
+       }
+
        JME_RSS_DPRINTF(rdata->jme_sc, 15, "ring%d, flags 0x%08x, "
                        "hash 0x%08x, hash info 0x%08x\n",
                        rdata->jme_rx_idx, flags, hash, hashinfo);