|
@@ -4552,6 +4552,12 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi,
|
|
|
pci_unmap_addr(src_map, mapping));
|
|
|
dest_desc->addr_hi = src_desc->addr_hi;
|
|
|
dest_desc->addr_lo = src_desc->addr_lo;
|
|
|
+
|
|
|
+ /* Ensure that the update to the skb happens after the physical
|
|
|
+ * addresses have been transferred to the new BD location.
|
|
|
+ */
|
|
|
+ smp_wmb();
|
|
|
+
|
|
|
src_map->skb = NULL;
|
|
|
}
|
|
|
|
|
@@ -4816,6 +4822,22 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp,
|
|
|
si = spr->rx_std_cons_idx;
|
|
|
di = dpr->rx_std_prod_idx;
|
|
|
|
|
|
+ for (i = di; i < di + cpycnt; i++) {
|
|
|
+ if (dpr->rx_std_buffers[i].skb) {
|
|
|
+ cpycnt = i - di;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cpycnt)
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* Ensure that updates to the rx_std_buffers ring and the
|
|
|
+ * shadowed hardware producer ring from tg3_recycle_skb() are
|
|
|
+ * ordered correctly WRT the skb check above.
|
|
|
+ */
|
|
|
+ smp_rmb();
|
|
|
+
|
|
|
memcpy(&dpr->rx_std_buffers[di],
|
|
|
&spr->rx_std_buffers[si],
|
|
|
cpycnt * sizeof(struct ring_info));
|
|
@@ -4856,6 +4878,22 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp,
|
|
|
si = spr->rx_jmb_cons_idx;
|
|
|
di = dpr->rx_jmb_prod_idx;
|
|
|
|
|
|
+ for (i = di; i < di + cpycnt; i++) {
|
|
|
+ if (dpr->rx_jmb_buffers[i].skb) {
|
|
|
+ cpycnt = i - di;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cpycnt)
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* Ensure that updates to the rx_jmb_buffers ring and the
|
|
|
+ * shadowed hardware producer ring from tg3_recycle_skb() are
|
|
|
+ * ordered correctly WRT the skb check above.
|
|
|
+ */
|
|
|
+ smp_rmb();
|
|
|
+
|
|
|
memcpy(&dpr->rx_jmb_buffers[di],
|
|
|
&spr->rx_jmb_buffers[si],
|
|
|
cpycnt * sizeof(struct ring_info));
|