diff options
author | Divy Le Ray <divy@chelsio.com> | 2010-02-01 05:29:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-03 21:37:10 -0500 |
commit | 2e02644abc4b3574533b027782820b5a6dfe1920 (patch) | |
tree | 8d290370b0147c459970ddf789fe4f6410dbce6e /drivers/net/cxgb3 | |
parent | ace2a4d0fbf868c00625a8fd91c44ad9fabe7012 (diff) |
cxgb3: add memory barriers
Add memory barriers to fix crashes observed on newest PowerPC platforms.
The HW and driver state of the receive rings were getting out of sync.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r-- | drivers/net/cxgb3/sge.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index bdbd14727e4b..4cf9b7962afa 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -480,6 +480,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) | |||
480 | { | 480 | { |
481 | if (q->pend_cred >= q->credits / 4) { | 481 | if (q->pend_cred >= q->credits / 4) { |
482 | q->pend_cred = 0; | 482 | q->pend_cred = 0; |
483 | wmb(); | ||
483 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); | 484 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); |
484 | } | 485 | } |
485 | } | 486 | } |
@@ -2282,11 +2283,14 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, | |||
2282 | while (likely(budget_left && is_new_response(r, q))) { | 2283 | while (likely(budget_left && is_new_response(r, q))) { |
2283 | int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; | 2284 | int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; |
2284 | struct sk_buff *skb = NULL; | 2285 | struct sk_buff *skb = NULL; |
2285 | u32 len, flags = ntohl(r->flags); | 2286 | u32 len, flags; |
2286 | __be32 rss_hi = *(const __be32 *)r, | 2287 | __be32 rss_hi, rss_lo; |
2287 | rss_lo = r->rss_hdr.rss_hash_val; | ||
2288 | 2288 | ||
2289 | rmb(); | ||
2289 | eth = r->rss_hdr.opcode == CPL_RX_PKT; | 2290 | eth = r->rss_hdr.opcode == CPL_RX_PKT; |
2291 | rss_hi = *(const __be32 *)r; | ||
2292 | rss_lo = r->rss_hdr.rss_hash_val; | ||
2293 | flags = ntohl(r->flags); | ||
2290 | 2294 | ||
2291 | if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) { | 2295 | if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) { |
2292 | skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC); | 2296 | skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC); |
@@ -2497,7 +2501,10 @@ static int process_pure_responses(struct adapter *adap, struct sge_qset *qs, | |||
2497 | refill_rspq(adap, q, q->credits); | 2501 | refill_rspq(adap, q, q->credits); |
2498 | q->credits = 0; | 2502 | q->credits = 0; |
2499 | } | 2503 | } |
2500 | } while (is_new_response(r, q) && is_pure_response(r)); | 2504 | if (!is_new_response(r, q)) |
2505 | break; | ||
2506 | rmb(); | ||
2507 | } while (is_pure_response(r)); | ||
2501 | 2508 | ||
2502 | if (sleeping) | 2509 | if (sleeping) |
2503 | check_ring_db(adap, qs, sleeping); | 2510 | check_ring_db(adap, qs, sleeping); |
@@ -2531,6 +2538,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) | |||
2531 | 2538 | ||
2532 | if (!is_new_response(r, q)) | 2539 | if (!is_new_response(r, q)) |
2533 | return -1; | 2540 | return -1; |
2541 | rmb(); | ||
2534 | if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) { | 2542 | if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) { |
2535 | t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | | 2543 | t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | |
2536 | V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx)); | 2544 | V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx)); |