Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bnx2x: tx_has_work should not wait for FW

The current tx_has_work waited until all packets sent by the driver
are marked as completed by the FW. This is too greedy and it causes
the bnx2x_poll to spin in vain. The driver should only check that all
packets FW already completed are freed - only in unload flow the
driver should make sure that transmit queue is empty

Signed-off-by: Vladislav Zolotarov <vladz@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladislav Zolotarov and committed by
David S. Miller
e8b5fc51 32ec8033

+12 -5
+12 -5
drivers/net/bnx2x_main.c
··· 57 57 #include "bnx2x.h" 58 58 #include "bnx2x_init.h" 59 59 60 - #define DRV_MODULE_VERSION "1.45.25" 61 - #define DRV_MODULE_RELDATE "2009/01/22" 60 + #define DRV_MODULE_VERSION "1.45.26" 61 + #define DRV_MODULE_RELDATE "2009/01/26" 62 62 #define BNX2X_BC_VER 0x040200 63 63 64 64 /* Time in jiffies before concluding the transmitter is hung */ ··· 740 740 /* Tell compiler that status block fields can change */ 741 741 barrier(); 742 742 tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb); 743 - return ((fp->tx_pkt_prod != tx_cons_sb) || 744 - (fp->tx_pkt_prod != fp->tx_pkt_cons)); 743 + return (fp->tx_pkt_cons != tx_cons_sb); 744 + } 745 + 746 + static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp) 747 + { 748 + /* Tell compiler that consumer and producer can change */ 749 + barrier(); 750 + return (fp->tx_pkt_prod != fp->tx_pkt_cons); 751 + 745 752 } 746 753 747 754 /* free skb in the packet ring at pos idx ··· 6736 6729 6737 6730 cnt = 1000; 6738 6731 smp_rmb(); 6739 - while (bnx2x_has_tx_work(fp)) { 6732 + while (bnx2x_has_tx_work_unload(fp)) { 6740 6733 6741 6734 bnx2x_tx_int(fp, 1000); 6742 6735 if (!cnt) {