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.
Unified · Split
| @@ -520,10 +520,12 @@ struct bnx2x_fastpath { · 519 unmodified lines | ||
| 520 | 520 | #define BNX2X_FP_STATE_IDLE 0 |
| 521 | 521 | #define BNX2X_FP_STATE_NAPI (1 << 0) /* NAPI owns this FP */ |
| 522 | 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 */ | |
| 524 | −#define BNX2X_FP_STATE_POLL_YIELD (1 << 3) /* poll yielded this FP */ | |
| 523 | +#define BNX2X_FP_STATE_DISABLED (1 << 2) | |
| 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 | 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 | 529 | #define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD) |
| 528 | 530 | /* protect state */ |
| 529 | 531 | spinlock_t lock; |
| @@ -613,7 +615,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) · 83 unmodified lines | ||
| 613 | 615 | { |
| 614 | 616 | bool rc = true; |
| 615 | 617 | |
| 616 | − spin_lock(&fp->lock); | |
| 618 | + spin_lock_bh(&fp->lock); | |
| 617 | 619 | if (fp->state & BNX2X_FP_LOCKED) { |
| 618 | 620 | WARN_ON(fp->state & BNX2X_FP_STATE_NAPI); |
| 619 | 621 | fp->state |= BNX2X_FP_STATE_NAPI_YIELD; |
| @@ -622,7 +624,7 @@ static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) · 2 unmodified lines | ||
| 622 | 624 | /* we don't care if someone yielded */ |
| 623 | 625 | fp->state = BNX2X_FP_STATE_NAPI; |
| 624 | 626 | } |
| 625 | − spin_unlock(&fp->lock); | |
| 627 | + spin_unlock_bh(&fp->lock); | |
| 626 | 628 | return rc; |
| 627 | 629 | } |
| 628 | 630 | |
| @@ -631,14 +633,16 @@ static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp) · 2 unmodified lines | ||
| 631 | 633 | { |
| 632 | 634 | bool rc = false; |
| 633 | 635 | |
| 634 | − spin_lock(&fp->lock); | |
| 636 | + spin_lock_bh(&fp->lock); | |
| 635 | 637 | WARN_ON(fp->state & |
| 636 | 638 | (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD)); |
| 637 | 639 | |
| 638 | 640 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) |
| 639 | 641 | rc = true; |
| 640 | − fp->state = BNX2X_FP_STATE_IDLE; | |
| 641 | − spin_unlock(&fp->lock); | |
| 642 | + | |
| 643 | + /* state ==> idle, unless currently disabled */ | |
| 644 | + fp->state &= BNX2X_FP_STATE_DISABLED; | |
| 645 | + spin_unlock_bh(&fp->lock); | |
| 642 | 646 | return rc; |
| 643 | 647 | } |
| 644 | 648 | |
| @@ -669,7 +673,9 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) · 24 unmodified lines | ||
| 669 | 673 | |
| 670 | 674 | if (fp->state & BNX2X_FP_STATE_POLL_YIELD) |
| 671 | 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 | 679 | spin_unlock_bh(&fp->lock); |
| 674 | 680 | return rc; |
| 675 | 681 | } |
| @@ -677,9 +683,23 @@ static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) · 1 unmodified line | ||
| 677 | 683 | /* true if a socket is polling, even if it did not get the lock */ |
| 678 | 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 | 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 | 703 | #else |
| 684 | 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) · 23 unmodified lines | ||
| 709 | 729 | { |
| 710 | 730 | return false; |
| 711 | 731 | } |
| 732 | +static inline bool bnx2x_fp_ll_disable(struct bnx2x_fastpath *fp) | |
| 733 | +{ | |
| 734 | + return true; | |
| 735 | +} | |
| 712 | 736 | #endif /* CONFIG_NET_RX_BUSY_POLL */ |
| 713 | 737 | |
| 714 | 738 | /* Use 2500 as a mini-jumbo MTU for FCoE */ |
| @@ -1790,26 +1790,22 @@ static void bnx2x_napi_disable_cnic(struct bnx2x *bp) · 1789 unmodified lines | ||
| 1790 | 1790 | { |
| 1791 | 1791 | int i; |
| 1792 | 1792 | |
| 1793 | − local_bh_disable(); | |
| 1794 | 1793 | for_each_rx_queue_cnic(bp, i) { |
| 1795 | 1794 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 1796 | − while (!bnx2x_fp_lock_napi(&bp->fp[i])) | |
| 1797 | − mdelay(1); | |
| 1795 | + while (!bnx2x_fp_ll_disable(&bp->fp[i])) | |
| 1796 | + usleep_range(1000, 2000); | |
| 1798 | 1797 | } |
| 1799 | − local_bh_enable(); | |
| 1800 | 1798 | } |
| 1801 | 1799 | |
| 1802 | 1800 | static void bnx2x_napi_disable(struct bnx2x *bp) |
| 1803 | 1801 | { |
| 1804 | 1802 | int i; |
| 1805 | 1803 | |
| 1806 | − local_bh_disable(); | |
| 1807 | 1804 | for_each_eth_queue(bp, i) { |
| 1808 | 1805 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 1809 | − while (!bnx2x_fp_lock_napi(&bp->fp[i])) | |
| 1810 | − mdelay(1); | |
| 1806 | + while (!bnx2x_fp_ll_disable(&bp->fp[i])) | |
| 1807 | + usleep_range(1000, 2000); | |
| 1811 | 1808 | } |
| 1812 | − local_bh_enable(); | |
| 1813 | 1809 | } |
| 1814 | 1810 | |
| 1815 | 1811 | void bnx2x_netif_start(struct bnx2x *bp) |