]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From 58f4c4cfce5c4715b79621f0a635925c55f855d5 Mon Sep 17 00:00:00 2001 |
2 | From: Eilon Greenstein <eilong@broadcom.com> | |
3 | Date: Wed, 14 Jan 2009 21:23:36 -0800 | |
4 | Subject: bnx2x: Missing memory barriers | |
5 | Acked-by: Karsten Keil <kkeil@novell.com> | |
6 | Reference: bnc#472500 | |
7 | ||
8 | While working on IA64, it became clear that the following memory | |
9 | barriers are missing | |
10 | ||
11 | Signed-off-by: Eilon Greenstein <eilong@broadcom.com> | |
12 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
13 | --- | |
14 | drivers/net/bnx2x_main.c | 28 ++++++++++++++++++++++++++-- | |
15 | 1 files changed, 26 insertions(+), 2 deletions(-) | |
16 | ||
17 | Index: linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c | |
18 | =================================================================== | |
19 | --- linux-2.6.27-bnx2x_2.orig/drivers/net/bnx2x_main.c | |
20 | +++ linux-2.6.27-bnx2x_2/drivers/net/bnx2x_main.c | |
21 | @@ -1358,11 +1358,23 @@ static inline void bnx2x_update_rx_prod( | |
22 | rx_prods.cqe_prod = rx_comp_prod; | |
23 | rx_prods.sge_prod = rx_sge_prod; | |
24 | ||
25 | + /* | |
26 | + * Make sure that the BD and SGE data is updated before updating the | |
27 | + * producers since FW might read the BD/SGE right after the producer | |
28 | + * is updated. | |
29 | + * This is only applicable for weak-ordered memory model archs such | |
30 | + * as IA-64. The following barrier is also mandatory since FW will | |
31 | + * assumes BDs must have buffers. | |
32 | + */ | |
33 | + wmb(); | |
34 | + | |
35 | for (i = 0; i < sizeof(struct tstorm_eth_rx_producers)/4; i++) | |
36 | REG_WR(bp, BAR_TSTRORM_INTMEM + | |
37 | TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)) + i*4, | |
38 | ((u32 *)&rx_prods)[i]); | |
39 | ||
40 | + mmiowb(); /* keep prod updates ordered */ | |
41 | + | |
42 | DP(NETIF_MSG_RX_STATUS, | |
43 | "Wrote: bd_prod %u cqe_prod %u sge_prod %u\n", | |
44 | bd_prod, rx_comp_prod, rx_sge_prod); | |
45 | @@ -1584,7 +1596,6 @@ next_cqe: | |
46 | /* Update producers */ | |
47 | bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod, | |
48 | fp->rx_sge_prod); | |
49 | - mmiowb(); /* keep prod updates ordered */ | |
50 | ||
51 | fp->rx_pkt += rx_pkt; | |
52 | fp->rx_calls++; | |
53 | @@ -8732,6 +8743,8 @@ static int bnx2x_run_loopback(struct bnx | |
54 | tx_bd->general_data = ((UNICAST_ADDRESS << | |
55 | ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1); | |
56 | ||
57 | + wmb(); | |
58 | + | |
59 | fp->hw_tx_prods->bds_prod = | |
60 | cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + 1); | |
61 | mb(); /* FW restriction: must not reorder writing nbd and packets */ | |
62 | @@ -8784,7 +8797,6 @@ test_loopback_rx_exit: | |
63 | /* Update producers */ | |
64 | bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, | |
65 | fp->rx_sge_prod); | |
66 | - mmiowb(); /* keep prod updates ordered */ | |
67 | ||
68 | test_loopback_exit: | |
69 | bp->link_params.loopback_mode = LOOPBACK_NONE; | |
70 | @@ -9711,6 +9723,15 @@ static int bnx2x_start_xmit(struct sk_bu | |
71 | ||
72 | DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); | |
73 | ||
74 | + /* | |
75 | + * Make sure that the BD data is updated before updating the producer | |
76 | + * since FW might read the BD right after the producer is updated. | |
77 | + * This is only applicable for weak-ordered memory model archs such | |
78 | + * as IA-64. The following barrier is also mandatory since FW will | |
79 | + * assumes packets must have BDs. | |
80 | + */ | |
81 | + wmb(); | |
82 | + | |
83 | fp->hw_tx_prods->bds_prod = | |
84 | cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd); | |
85 | mb(); /* FW restriction: must not reorder writing nbd and packets */ | |
86 | @@ -9724,6 +9745,9 @@ static int bnx2x_start_xmit(struct sk_bu | |
87 | dev->trans_start = jiffies; | |
88 | ||
89 | if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { | |
90 | + /* We want bnx2x_tx_int to "see" the updated tx_bd_prod | |
91 | + if we put Tx into XOFF state. */ | |
92 | + smp_mb(); | |
93 | netif_stop_queue(dev); | |
94 | bp->eth_stats.driver_xoff++; | |
95 | if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) |