diff options
| author | Yuval Mintz <yuvalmin@broadcom.com> | 2014-01-07 05:07:41 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-01-09 21:46:06 -0500 |
| commit | 9a2620c877454bb4b5c19f73d4d1d7b375da3632 (patch) | |
| tree | a7c905f03ae7947d017e3362ea3ff83db822d8ef | |
| parent | a04c0e2c0d4f284503fc1249bb4d2d7064c0bd0c (diff) | |
bnx2x: prevent WARN during driver unload
Starting with commit 80c33dd "net: add might_sleep() call to napi_disable"
bnx2x fails the might_sleep tests causing a stack trace to appear whenever
the driver is unloaded, as local_bh_disable() is being called before
napi_disable().
This changes the locking schematics related to CONFIG_NET_RX_BUSY_POLL,
preventing the need for calling local_bh_disable() and thus eliminating
the issue.
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 44 | ||||
| -rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 |
2 files changed, 38 insertions, 18 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 2d5fce4c9751..ec6119089b82 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
| @@ -520,10 +520,12 @@ struct bnx2x_fastpath { | |||
| 520 | #define BNX2X_FP_STATE_IDLE 0 | 520 | #define BNX2X_FP_STATE_IDLE 0 |
| 521 | #define BNX2X_FP_STATE_NAPI (1 << 0) /* NAPI owns this FP */ | 521 | #define BNX2X_FP_STATE_NAPI (1 << 0) /* NAPI owns this FP */ |
| 522 | #define BNX2X_FP_STATE_POLL (1 << 1) /* poll owns this FP */ | 522 | #define BNX2X_FP_STATE_POLL (1 << 1) /* poll owns this FP */ |
| 523 | #define BNX2X_FP_STATE_NAPI_YIELD (1 << 2) /* NAPI yielded this FP */ | 523 | #define BNX2X_FP_STATE_DISABLED (1 << 2) |
| 524 | #define BNX2X_FP_STATE_POLL_YIELD (1 << 3) /* poll yielded this FP */ | 524 | #define BNX2X_FP_STATE_NAPI_YIELD (1 << 3) /* NAPI yielded this FP */ |
| 525 | #define BNX2X_FP_STATE_POLL_YIELD (1 << 4) /* poll yielded this FP */ | ||
| 526 | #define BNX2X_FP_OWNED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL) | ||
| 525 | #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD) | 527 | #define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD) |
| 526 | #define BNX2X_FP_LOCKED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL) | 528 | #define BNX2X_FP_LOCKED (BNX2X_FP_OWNED | BNX2X_FP_STATE_DISABLED) |
| 527 | #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD) | 529 | #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD) |
| 528 | /* protect state */ | 530 | /* protect state */ |
| 529 | spinlock_t lock; | 531 | spinlock_t lock; |
| @@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) | |||
| 613 | { | 615 | { |
| 614 | bool rc = true; | 616 | bool rc = true; |
| 615 | 617 | ||
| 616 | spin_lock(&fp->lock); | 618 | spin_lock_bh(&fp->lock); |
| 617 | if (fp->state & BNX2X_FP_LOCKED) { | 619 | if (fp->state & BNX2X_FP_LOCKED) { |
| 618 | WARN_ON(fp->state & BNX2X_FP_STATE_NAPI); | 620 | WARN_ON(fp->state & BNX2X_FP_STATE_NAPI); |
| 619 | fp->state |= BNX2X_FP_STATE_NAPI_YIELD; | 621 | fp->state |= BNX2X_FP_STATE_NAPI_YIELD; |
| @@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) | |||
| 622 | /* we don't care if someone yielded */ | 624 | /* we don't care if someone yielded */ |
| 623 | fp->state = BNX2X_FP_STATE_NAPI; | 625 | fp->state = BNX2X_FP_STATE_NAPI; |
| 624 | } | 626 | } |
| 625 | spin_unlock(&fp->lock); | 627 | spin_unlock_bh(&fp->lock); |
| 626 | return rc; | 628 | return rc; |
| 627 | } | 629 | } |
| 628 | 630 | ||
| @@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp) | |||
| 631 | { | 633 | { |
| 632 | bool rc = false; | 634 | bool rc = false; |
| 633 | 635 | ||
| 634 | spin_lock(&fp->lock); | 636 | spin_lock_bh(&fp->lock); |
| 635 | WARN_ON(fp->state & | 637 | WARN_ON(fp->state & |
| 636 | (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD)); | 638 | (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD)); |
| 637 | 639 | ||
| 638 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) | 640 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) |
| 639 | rc = true; | 641 | rc = true; |
| 640 | fp->state = BNX2X_FP_STATE_IDLE; | 642 | |
| 641 | spin_unlock(&fp->lock); | 643 | /* state ==> idle, unless currently disabled */ |
| 644 | fp->state &= BNX2X_FP_STATE_DISABLED; | ||
| 645 | spin_unlock_bh(&fp->lock); | ||
| 642 | return rc; | 646 | return rc; |
| 643 | } | 647 | } |
| 644 | 648 | ||
| @@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) | |||
| 669 | 673 | ||
| 670 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) | 674 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) |
| 671 | rc = true; | 675 | rc = true; |
| 672 | fp->state = BNX2X_FP_STATE_IDLE; | 676 | |
| 677 | /* state ==> idle, unless currently disabled */ | ||
| 678 | fp->state &= BNX2X_FP_STATE_DISABLED; | ||
| 673 | spin_unlock_bh(&fp->lock); | 679 | spin_unlock_bh(&fp->lock); |
| 674 | return rc; | 680 | return rc; |
| 675 | } | 681 | } |
| @@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) | |||
| 677 | /* true if a socket is polling, even if it did not get the lock */ | 683 | /* true if a socket is polling, even if it did not get the lock */ |
| 678 | static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp) | 684 | static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp) |
| 679 | { | 685 | { |
| 680 | WARN_ON(!(fp->state & BNX2X_FP_LOCKED)); | 686 | WARN_ON(!(fp->state & BNX2X_FP_OWNED)); |
| 681 | return fp->state & BNX2X_FP_USER_PEND; | 687 | return fp->state & BNX2X_FP_USER_PEND; |
| 682 | } | 688 | } |
| 689 | |||
| 690 | /* false if fp is currently owned */ | ||
| 691 | static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp) | ||
| 692 | { | ||
| 693 | int rc = true; | ||
| 694 | |||
| 695 | spin_lock_bh(&fp->lock); | ||
| 696 | if (fp->state & BNX2X_FP_OWNED) | ||
| 697 | rc = false; | ||
| 698 | fp->state |= BNX2X_FP_STATE_DISABLED; | ||
| 699 | spin_unlock_bh(&fp->lock); | ||
| 700 | |||
| 701 | return rc; | ||
| 702 | } | ||
| 683 | #else | 703 | #else |
| 684 | static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp) | 704 | static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp) |
| 685 | { | 705 | { |
| @@ -709,6 +729,10 @@ static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp) | |||
| 709 | { | 729 | { |
| 710 | return false; | 730 | return false; |
| 711 | } | 731 | } |
| 732 | static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp) | ||
| 733 | { | ||
| 734 | return true; | ||
| 735 | } | ||
| 712 | #endif /* CONFIG_NET_RX_BUSY_POLL */ | 736 | #endif /* CONFIG_NET_RX_BUSY_POLL */ |
| 713 | 737 | ||
| 714 | /* Use 2500 as a mini-jumbo MTU for FCoE */ | 738 | /* Use 2500 as a mini-jumbo MTU for FCoE */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ec96130533cc..c6745d7def5c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
| @@ -1790,26 +1790,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp) | |||
| 1790 | { | 1790 | { |
| 1791 | int i; | 1791 | int i; |
| 1792 | 1792 | ||
| 1793 | local_bh_disable(); | ||
| 1794 | for_each_rx_queue_cnic(bp, i) { | 1793 | for_each_rx_queue_cnic(bp, i) { |
| 1795 | napi_disable(&bnx2x_fp(bp, i, napi)); | 1794 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 1796 | while (!bnx2x_fp_lock_napi(&bp->fp[i])) | 1795 | while (!bnx2x_fp_ll_disable(&bp->fp[i])) |
| 1797 | mdelay(1); | 1796 | usleep_range(1000, 2000); |
| 1798 | } | 1797 | } |
| 1799 | local_bh_enable(); | ||
| 1800 | } | 1798 | } |
| 1801 | 1799 | ||
| 1802 | static void bnx2x_napi_disable(struct bnx2x *bp) | 1800 | static void bnx2x_napi_disable(struct bnx2x *bp) |
| 1803 | { | 1801 | { |
| 1804 | int i; | 1802 | int i; |
| 1805 | 1803 | ||
| 1806 | local_bh_disable(); | ||
| 1807 | for_each_eth_queue(bp, i) { | 1804 | for_each_eth_queue(bp, i) { |
| 1808 | napi_disable(&bnx2x_fp(bp, i, napi)); | 1805 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 1809 | while (!bnx2x_fp_lock_napi(&bp->fp[i])) | 1806 | while (!bnx2x_fp_ll_disable(&bp->fp[i])) |
| 1810 | mdelay(1); | 1807 | usleep_range(1000, 2000); |
| 1811 | } | 1808 | } |
| 1812 | local_bh_enable(); | ||
| 1813 | } | 1809 | } |
| 1814 | 1810 | ||
| 1815 | void bnx2x_netif_start(struct bnx2x *bp) | 1811 | void bnx2x_netif_start(struct bnx2x *bp) |
