aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c1339
1 files changed, 806 insertions, 533 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 367b6d46270..5ebde67d429 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -47,6 +47,7 @@
#include <linux/prefetch.h>
#include <linux/cache.h>
#include <linux/zlib.h>
+#include <linux/log2.h>
#include "bnx2.h"
#include "bnx2_fw.h"
@@ -56,8 +57,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.7.5"
-#define DRV_MODULE_RELDATE "April 29, 2008"
+#define DRV_MODULE_VERSION "1.7.9"
+#define DRV_MODULE_RELDATE "July 18, 2008"
#define RUN_AT(x) (jiffies + (x))
@@ -68,7 +69,7 @@ static char version[] __devinitdata =
"Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708 Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -87,6 +88,7 @@ typedef enum {
BCM5708S,
BCM5709,
BCM5709S,
+ BCM5716,
} board_t;
/* indexed by board_t, above */
@@ -102,9 +104,10 @@ static struct {
{ "Broadcom NetXtreme II BCM5708 1000Base-SX" },
{ "Broadcom NetXtreme II BCM5709 1000Base-T" },
{ "Broadcom NetXtreme II BCM5709 1000Base-SX" },
+ { "Broadcom NetXtreme II BCM5716 1000Base-T" },
};
-static struct pci_device_id bnx2_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
@@ -123,6 +126,8 @@ static struct pci_device_id bnx2_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
+ { PCI_VENDOR_ID_BROADCOM, 0x163b,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 },
{ 0, }
};
@@ -226,7 +231,7 @@ static struct flash_spec flash_5709 = {
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
-static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_napi *bnapi)
+static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
{
u32 diff;
@@ -235,7 +240,7 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_napi *bnapi)
/* The ring uses 256 indices for 255 entries, one of them
* needs to be skipped.
*/
- diff = bp->tx_prod - bnapi->tx_cons;
+ diff = txr->tx_prod - txr->tx_cons;
if (unlikely(diff >= TX_DESC_CNT)) {
diff &= 0xffff;
if (diff == TX_DESC_CNT)
@@ -289,7 +294,6 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
REG_WR(bp, BNX2_CTX_CTX_CTRL,
offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
for (i = 0; i < 5; i++) {
- u32 val;
val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
break;
@@ -488,7 +492,7 @@ bnx2_netif_start(struct bnx2 *bp)
{
if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) {
- netif_wake_queue(bp->dev);
+ netif_tx_wake_all_queues(bp->dev);
bnx2_napi_enable(bp);
bnx2_enable_int(bp);
}
@@ -496,99 +500,162 @@ bnx2_netif_start(struct bnx2 *bp)
}
static void
-bnx2_free_mem(struct bnx2 *bp)
+bnx2_free_tx_mem(struct bnx2 *bp)
{
int i;
- for (i = 0; i < bp->ctx_pages; i++) {
- if (bp->ctx_blk[i]) {
- pci_free_consistent(bp->pdev, BCM_PAGE_SIZE,
- bp->ctx_blk[i],
- bp->ctx_blk_mapping[i]);
- bp->ctx_blk[i] = NULL;
+ for (i = 0; i < bp->num_tx_rings; i++) {
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+ struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+
+ if (txr->tx_desc_ring) {
+ pci_free_consistent(bp->pdev, TXBD_RING_SIZE,
+ txr->tx_desc_ring,
+ txr->tx_desc_mapping);
+ txr->tx_desc_ring = NULL;
}
+ kfree(txr->tx_buf_ring);
+ txr->tx_buf_ring = NULL;
}
- if (bp->status_blk) {
- pci_free_consistent(bp->pdev, bp->status_stats_size,
- bp->status_blk, bp->status_blk_mapping);
- bp->status_blk = NULL;
- bp->stats_blk = NULL;
+}
+
+static void
+bnx2_free_rx_mem(struct bnx2 *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->num_rx_rings; i++) {
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+ struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
+ int j;
+
+ for (j = 0; j < bp->rx_max_ring; j++) {
+ if (rxr->rx_desc_ring[j])
+ pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
+ rxr->rx_desc_ring[j],
+ rxr->rx_desc_mapping[j]);
+ rxr->rx_desc_ring[j] = NULL;
+ }
+ if (rxr->rx_buf_ring)
+ vfree(rxr->rx_buf_ring);
+ rxr->rx_buf_ring = NULL;
+
+ for (j = 0; j < bp->rx_max_pg_ring; j++) {
+ if (rxr->rx_pg_desc_ring[j])
+ pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
+ rxr->rx_pg_desc_ring[i],
+ rxr->rx_pg_desc_mapping[i]);
+ rxr->rx_pg_desc_ring[i] = NULL;
+ }
+ if (rxr->rx_pg_ring)
+ vfree(rxr->rx_pg_ring);
+ rxr->rx_pg_ring = NULL;
}
- if (bp->tx_desc_ring) {
- pci_free_consistent(bp->pdev, TXBD_RING_SIZE,
- bp->tx_desc_ring, bp->tx_desc_mapping);
- bp->tx_desc_ring = NULL;
- }
- kfree(bp->tx_buf_ring);
- bp->tx_buf_ring = NULL;
- for (i = 0; i < bp->rx_max_ring; i++) {
- if (bp->rx_desc_ring[i])
- pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
- bp->rx_desc_ring[i],
- bp->rx_desc_mapping[i]);
- bp->rx_desc_ring[i] = NULL;
- }
- vfree(bp->rx_buf_ring);
- bp->rx_buf_ring = NULL;
- for (i = 0; i < bp->rx_max_pg_ring; i++) {
- if (bp->rx_pg_desc_ring[i])
- pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
- bp->rx_pg_desc_ring[i],
- bp->rx_pg_desc_mapping[i]);
- bp->rx_pg_desc_ring[i] = NULL;
- }
- if (bp->rx_pg_ring)
- vfree(bp->rx_pg_ring);
- bp->rx_pg_ring = NULL;
}
static int
-bnx2_alloc_mem(struct bnx2 *bp)
+bnx2_alloc_tx_mem(struct bnx2 *bp)
{
- int i, status_blk_size;
+ int i;
- bp->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
- if (bp->tx_buf_ring == NULL)
- return -ENOMEM;
+ for (i = 0; i < bp->num_tx_rings; i++) {
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+ struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
- bp->tx_desc_ring = pci_alloc_consistent(bp->pdev, TXBD_RING_SIZE,
- &bp->tx_desc_mapping);
- if (bp->tx_desc_ring == NULL)
- goto alloc_mem_err;
+ txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
+ if (txr->tx_buf_ring == NULL)
+ return -ENOMEM;
- bp->rx_buf_ring = vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
- if (bp->rx_buf_ring == NULL)
- goto alloc_mem_err;
+ txr->tx_desc_ring =
+ pci_alloc_consistent(bp->pdev, TXBD_RING_SIZE,
+ &txr->tx_desc_mapping);
+ if (txr->tx_desc_ring == NULL)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int
+bnx2_alloc_rx_mem(struct bnx2 *bp)
+{
+ int i;
+
+ for (i = 0; i < bp->num_rx_rings; i++) {
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+ struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
+ int j;
- memset(bp->rx_buf_ring, 0, SW_RXBD_RING_SIZE * bp->rx_max_ring);
+ rxr->rx_buf_ring =
+ vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
+ if (rxr->rx_buf_ring == NULL)
+ return -ENOMEM;
- for (i = 0; i < bp->rx_max_ring; i++) {
- bp->rx_desc_ring[i] =
- pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
- &bp->rx_desc_mapping[i]);
- if (bp->rx_desc_ring[i] == NULL)
- goto alloc_mem_err;
+ memset(rxr->rx_buf_ring, 0,
+ SW_RXBD_RING_SIZE * bp->rx_max_ring);
- }
+ for (j = 0; j < bp->rx_max_ring; j++) {
+ rxr->rx_desc_ring[j] =
+ pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
+ &rxr->rx_desc_mapping[j]);
+ if (rxr->rx_desc_ring[j] == NULL)
+ return -ENOMEM;
- if (bp->rx_pg_ring_size) {
- bp->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
- bp->rx_max_pg_ring);
- if (bp->rx_pg_ring == NULL)
- goto alloc_mem_err;
+ }
+
+ if (bp->rx_pg_ring_size) {
+ rxr->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
+ bp->rx_max_pg_ring);
+ if (rxr->rx_pg_ring == NULL)
+ return -ENOMEM;
+
+ memset(rxr->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
+ bp->rx_max_pg_ring);
+ }
+
+ for (j = 0; j < bp->rx_max_pg_ring; j++) {
+ rxr->rx_pg_desc_ring[j] =
+ pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
+ &rxr->rx_pg_desc_mapping[j]);
+ if (rxr->rx_pg_desc_ring[j] == NULL)
+ return -ENOMEM;
- memset(bp->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
- bp->rx_max_pg_ring);
+ }
}
+ return 0;
+}
- for (i = 0; i < bp->rx_max_pg_ring; i++) {
- bp->rx_pg_desc_ring[i] =
- pci_alloc_consistent(bp->pdev, RXBD_RING_SIZE,
- &bp->rx_pg_desc_mapping[i]);
- if (bp->rx_pg_desc_ring[i] == NULL)
- goto alloc_mem_err;
+static void
+bnx2_free_mem(struct bnx2 *bp)
+{
+ int i;
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+
+ bnx2_free_tx_mem(bp);
+ bnx2_free_rx_mem(bp);
+ for (i = 0; i < bp->ctx_pages; i++) {
+ if (bp->ctx_blk[i]) {
+ pci_free_consistent(bp->pdev, BCM_PAGE_SIZE,
+ bp->ctx_blk[i],
+ bp->ctx_blk_mapping[i]);
+ bp->ctx_blk[i] = NULL;
+ }
}
+ if (bnapi->status_blk.msi) {
+ pci_free_consistent(bp->pdev, bp->status_stats_size,
+ bnapi->status_blk.msi,
+ bp->status_blk_mapping);
+ bnapi->status_blk.msi = NULL;
+ bp->stats_blk = NULL;
+ }
+}
+
+static int
+bnx2_alloc_mem(struct bnx2 *bp)
+{
+ int i, status_blk_size, err;
+ struct bnx2_napi *bnapi;
+ void *status_blk;
/* Combine status and statistics blocks into one allocation. */
status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
@@ -598,27 +665,37 @@ bnx2_alloc_mem(struct bnx2 *bp)
bp->status_stats_size = status_blk_size +
sizeof(struct statistics_block);
- bp->status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size,
- &bp->status_blk_mapping);
- if (bp->status_blk == NULL)
+ status_blk = pci_alloc_consistent(bp->pdev, bp->status_stats_size,
+ &bp->status_blk_mapping);
+ if (status_blk == NULL)
goto alloc_mem_err;
- memset(bp->status_blk, 0, bp->status_stats_size);
+ memset(status_blk, 0, bp->status_stats_size);
- bp->bnx2_napi[0].status_blk = bp->status_blk;
+ bnapi = &bp->bnx2_napi[0];
+ bnapi->status_blk.msi = status_blk;
+ bnapi->hw_tx_cons_ptr =
+ &bnapi->status_blk.msi->status_tx_quick_consumer_index0;
+ bnapi->hw_rx_cons_ptr =
+ &bnapi->status_blk.msi->status_rx_quick_consumer_index0;
if (bp->flags & BNX2_FLAG_MSIX_CAP) {
for (i = 1; i < BNX2_MAX_MSIX_VEC; i++) {
- struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+ struct status_block_msix *sblk;
- bnapi->status_blk_msix = (void *)
- ((unsigned long) bp->status_blk +
- BNX2_SBLK_MSIX_ALIGN_SIZE * i);
+ bnapi = &bp->bnx2_napi[i];
+
+ sblk = (void *) (status_blk +
+ BNX2_SBLK_MSIX_ALIGN_SIZE * i);
+ bnapi->status_blk.msix = sblk;
+ bnapi->hw_tx_cons_ptr =
+ &sblk->status_tx_quick_consumer_index;
+ bnapi->hw_rx_cons_ptr =
+ &sblk->status_rx_quick_consumer_index;
bnapi->int_num = i << 24;
}
}
- bp->stats_blk = (void *) ((unsigned long) bp->status_blk +
- status_blk_size);
+ bp->stats_blk = status_blk + status_blk_size;
bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
@@ -634,6 +711,15 @@ bnx2_alloc_mem(struct bnx2 *bp)
goto alloc_mem_err;
}
}
+
+ err = bnx2_alloc_rx_mem(bp);
+ if (err)
+ goto alloc_mem_err;
+
+ err = bnx2_alloc_tx_mem(bp);
+ if (err)
+ goto alloc_mem_err;
+
return 0;
alloc_mem_err:
@@ -993,9 +1079,9 @@ bnx2_copper_linkup(struct bnx2 *bp)
}
static void
-bnx2_init_rx_context0(struct bnx2 *bp)
+bnx2_init_rx_context(struct bnx2 *bp, u32 cid)
{
- u32 val, rx_cid_addr = GET_CID_ADDR(RX_CID);
+ u32 val, rx_cid_addr = GET_CID_ADDR(cid);
val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
@@ -1028,6 +1114,19 @@ bnx2_init_rx_context0(struct bnx2 *bp)
bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_CTX_TYPE, val);
}
+static void
+bnx2_init_all_rx_contexts(struct bnx2 *bp)
+{
+ int i;
+ u32 cid;
+
+ for (i = 0, cid = RX_CID; i < bp->num_rx_rings; i++, cid++) {
+ if (i == 1)
+ cid = RX_RSS_CID;
+ bnx2_init_rx_context(bp, cid);
+ }
+}
+
static int
bnx2_set_mac_link(struct bnx2 *bp)
{
@@ -1093,7 +1192,7 @@ bnx2_set_mac_link(struct bnx2 *bp)
REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
if (CHIP_NUM(bp) == CHIP_NUM_5709)
- bnx2_init_rx_context0(bp);
+ bnx2_init_all_rx_contexts(bp);
return 0;
}
@@ -1392,7 +1491,7 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp)
return adv;
}
-static int bnx2_fw_sync(struct bnx2 *, u32, int);
+static int bnx2_fw_sync(struct bnx2 *, u32, int, int);
static int
bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
@@ -1445,7 +1544,7 @@ bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
bnx2_shmem_wr(bp, BNX2_DRV_MB_ARG0, speed_arg);
spin_unlock_bh(&bp->phy_lock);
- bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0);
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 1, 0);
spin_lock_bh(&bp->phy_lock);
return 0;
@@ -1875,7 +1974,7 @@ bnx2_setup_phy(struct bnx2 *bp, u8 port)
}
static int
-bnx2_init_5709s_phy(struct bnx2 *bp)
+bnx2_init_5709s_phy(struct bnx2 *bp, int reset_phy)
{
u32 val;
@@ -1890,7 +1989,8 @@ bnx2_init_5709s_phy(struct bnx2 *bp)
bnx2_write_phy(bp, MII_BNX2_AER_AER, MII_BNX2_AER_AER_AN_MMD);
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
- bnx2_reset_phy(bp);
+ if (reset_phy)
+ bnx2_reset_phy(bp);
bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_SERDES_DIG);
@@ -1924,11 +2024,12 @@ bnx2_init_5709s_phy(struct bnx2 *bp)
}
static int
-bnx2_init_5708s_phy(struct bnx2 *bp)
+bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
{
u32 val;
- bnx2_reset_phy(bp);
+ if (reset_phy)
+ bnx2_reset_phy(bp);
bp->mii_up1 = BCM5708S_UP1;
@@ -1981,9 +2082,10 @@ bnx2_init_5708s_phy(struct bnx2 *bp)
}
static int
-bnx2_init_5706s_phy(struct bnx2 *bp)
+bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
{
- bnx2_reset_phy(bp);
+ if (reset_phy)
+ bnx2_reset_phy(bp);
bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
@@ -2018,11 +2120,12 @@ bnx2_init_5706s_phy(struct bnx2 *bp)
}
static int
-bnx2_init_copper_phy(struct bnx2 *bp)
+bnx2_init_copper_phy(struct bnx2 *bp, int reset_phy)
{
u32 val;
- bnx2_reset_phy(bp);
+ if (reset_phy)
+ bnx2_reset_phy(bp);
if (bp->phy_flags & BNX2_PHY_FLAG_CRC_FIX) {
bnx2_write_phy(bp, 0x18, 0x0c00);
@@ -2070,7 +2173,7 @@ bnx2_init_copper_phy(struct bnx2 *bp)
static int
-bnx2_init_phy(struct bnx2 *bp)
+bnx2_init_phy(struct bnx2 *bp, int reset_phy)
{
u32 val;
int rc = 0;
@@ -2096,14 +2199,14 @@ bnx2_init_phy(struct bnx2 *bp)
if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
if (CHIP_NUM(bp) == CHIP_NUM_5706)
- rc = bnx2_init_5706s_phy(bp);
+ rc = bnx2_init_5706s_phy(bp, reset_phy);
else if (CHIP_NUM(bp) == CHIP_NUM_5708)
- rc = bnx2_init_5708s_phy(bp);
+ rc = bnx2_init_5708s_phy(bp, reset_phy);
else if (CHIP_NUM(bp) == CHIP_NUM_5709)
- rc = bnx2_init_5709s_phy(bp);
+ rc = bnx2_init_5709s_phy(bp, reset_phy);
}
else {
- rc = bnx2_init_copper_phy(bp);
+ rc = bnx2_init_copper_phy(bp, reset_phy);
}
setup_phy:
@@ -2159,7 +2262,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
}
static int
-bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
{
int i;
u32 val;
@@ -2169,6 +2272,9 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
+ if (!ack)
+ return 0;
+
/* wait for an acknowledgement. */
for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
msleep(10);
@@ -2345,28 +2451,27 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
}
static void
-bnx2_set_mac_addr(struct bnx2 *bp)
+bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
{
u32 val;
- u8 *mac_addr = bp->dev->dev_addr;
val = (mac_addr[0] << 8) | mac_addr[1];
- REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val);
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
(mac_addr[4] << 8) | mac_addr[5];
- REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val);
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
}
static inline int
-bnx2_alloc_rx_page(struct bnx2 *bp, u16 index)
+bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
{
dma_addr_t mapping;
- struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
+ struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
struct rx_bd *rxbd =
- &bp->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
+ &rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
struct page *page = alloc_page(GFP_ATOMIC);
if (!page)
@@ -2381,9 +2486,9 @@ bnx2_alloc_rx_page(struct bnx2 *bp, u16 index)
}
static void
-bnx2_free_rx_page(struct bnx2 *bp, u16 index)
+bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
{
- struct sw_pg *rx_pg = &bp->rx_pg_ring[index];
+ struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
struct page *page = rx_pg->page;
if (!page)
@@ -2397,12 +2502,12 @@ bnx2_free_rx_page(struct bnx2 *bp, u16 index)
}
static inline int
-bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, u16 index)
+bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
{
struct sk_buff *skb;
- struct sw_bd *rx_buf = &bp->rx_buf_ring[index];
+ struct sw_bd *rx_buf = &rxr->rx_buf_ring[index];
dma_addr_t mapping;
- struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
+ struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
unsigned long align;
skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
@@ -2422,7 +2527,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, u16 index)
rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
- bnapi->rx_prod_bseq += bp->rx_buf_use_size;
+ rxr->rx_prod_bseq += bp->rx_buf_use_size;
return 0;
}
@@ -2430,7 +2535,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, u16 index)
static int
bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
{
- struct status_block *sblk = bnapi->status_blk;
+ struct status_block *sblk = bnapi->status_blk.msi;
u32 new_link_state, old_link_state;
int is_set = 1;
@@ -2466,11 +2571,9 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
{
u16 cons;
- if (bnapi->int_num == 0)
- cons = bnapi->status_blk->status_tx_quick_consumer_index0;
- else
- cons = bnapi->status_blk_msix->status_tx_quick_consumer_index;
-
+ /* Tell compiler that status block fields can change. */
+ barrier();
+ cons = *bnapi->hw_tx_cons_ptr;
if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
cons++;
return cons;
@@ -2479,11 +2582,16 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
static int
bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
{
+ struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
u16 hw_cons, sw_cons, sw_ring_cons;
- int tx_pkt = 0;
+ int tx_pkt = 0, index;
+ struct netdev_queue *txq;
+
+ index = (bnapi - bp->bnx2_napi);
+ txq = netdev_get_tx_queue(bp->dev, index);
hw_cons = bnx2_get_hw_tx_cons(bnapi);
- sw_cons = bnapi->tx_cons;
+ sw_cons = txr->tx_cons;
while (sw_cons != hw_cons) {
struct sw_bd *tx_buf;
@@ -2492,7 +2600,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
sw_ring_cons = TX_RING_IDX(sw_cons);
- tx_buf = &bp->tx_buf_ring[sw_ring_cons];
+ tx_buf = &txr->tx_buf_ring[sw_ring_cons];
skb = tx_buf->skb;
/* partial BD completions possible with TSO packets */
@@ -2522,7 +2630,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
pci_unmap_page(bp->pdev,
pci_unmap_addr(
- &bp->tx_buf_ring[TX_RING_IDX(sw_cons)],
+ &txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
mapping),
skb_shinfo(skb)->frags[i].size,
PCI_DMA_TODEVICE);
@@ -2538,44 +2646,46 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
hw_cons = bnx2_get_hw_tx_cons(bnapi);
}
- bnapi->hw_tx_cons = hw_cons;
- bnapi->tx_cons = sw_cons;
+ txr->hw_tx_cons = hw_cons;
+ txr->tx_cons = sw_cons;
+
/* Need to make the tx_cons update visible to bnx2_start_xmit()
- * before checking for netif_queue_stopped(). Without the
+ * before checking for netif_tx_queue_stopped(). Without the
* memory barrier, there is a small possibility that bnx2_start_xmit()
* will miss it and cause the queue to be stopped forever.
*/
smp_mb();
- if (unlikely(netif_queue_stopped(bp->dev)) &&
- (bnx2_tx_avail(bp, bnapi) > bp->tx_wake_thresh)) {
- netif_tx_lock(bp->dev);
- if ((netif_queue_stopped(bp->dev)) &&
- (bnx2_tx_avail(bp, bnapi) > bp->tx_wake_thresh))
- netif_wake_queue(bp->dev);
- netif_tx_unlock(bp->dev);
+ if (unlikely(netif_tx_queue_stopped(txq)) &&
+ (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
+ __netif_tx_lock(txq, smp_processor_id());
+ if ((netif_tx_queue_stopped(txq)) &&
+ (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh))
+ netif_tx_wake_queue(txq);
+ __netif_tx_unlock(txq);
}
+
return tx_pkt;
}
static void
-bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_napi *bnapi,
+bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
struct sk_buff *skb, int count)
{
struct sw_pg *cons_rx_pg, *prod_rx_pg;
struct rx_bd *cons_bd, *prod_bd;
dma_addr_t mapping;
int i;
- u16 hw_prod = bnapi->rx_pg_prod, prod;
- u16 cons = bnapi->rx_pg_cons;
+ u16 hw_prod = rxr->rx_pg_prod, prod;
+ u16 cons = rxr->rx_pg_cons;
for (i = 0; i < count; i++) {
prod = RX_PG_RING_IDX(hw_prod);
- prod_rx_pg = &bp->rx_pg_ring[prod];
- cons_rx_pg = &bp->rx_pg_ring[cons];
- cons_bd = &bp->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
- prod_bd = &bp->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ prod_rx_pg = &rxr->rx_pg_ring[prod];
+ cons_rx_pg = &rxr->rx_pg_ring[cons];
+ cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
+ prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
if (i == 0 && skb) {
struct page *page;
@@ -2604,25 +2714,25 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_napi *bnapi,
cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
hw_prod = NEXT_RX_BD(hw_prod);
}
- bnapi->rx_pg_prod = hw_prod;
- bnapi->rx_pg_cons = cons;
+ rxr->rx_pg_prod = hw_prod;
+ rxr->rx_pg_cons = cons;
}
static inline void
-bnx2_reuse_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
- u16 cons, u16 prod)
+bnx2_reuse_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
+ struct sk_buff *skb, u16 cons, u16 prod)
{
struct sw_bd *cons_rx_buf, *prod_rx_buf;
struct rx_bd *cons_bd, *prod_bd;
- cons_rx_buf = &bp->rx_buf_ring[cons];
- prod_rx_buf = &bp->rx_buf_ring[prod];
+ cons_rx_buf = &rxr->rx_buf_ring[cons];
+ prod_rx_buf = &rxr->rx_buf_ring[prod];
pci_dma_sync_single_for_device(bp->pdev,
pci_unmap_addr(cons_rx_buf, mapping),
- bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
+ BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
- bnapi->rx_prod_bseq += bp->rx_buf_use_size;
+ rxr->rx_prod_bseq += bp->rx_buf_use_size;
prod_rx_buf->skb = skb;
@@ -2632,33 +2742,33 @@ bnx2_reuse_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
pci_unmap_addr_set(prod_rx_buf, mapping,
pci_unmap_addr(cons_rx_buf, mapping));
- cons_bd = &bp->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
- prod_bd = &bp->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+ cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
+ prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
}
static int
-bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
+bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
unsigned int len, unsigned int hdr_len, dma_addr_t dma_addr,
u32 ring_idx)
{
int err;
u16 prod = ring_idx & 0xffff;
- err = bnx2_alloc_rx_skb(bp, bnapi, prod);
+ err = bnx2_alloc_rx_skb(bp, rxr, prod);
if (unlikely(err)) {
- bnx2_reuse_rx_skb(bp, bnapi, skb, (u16) (ring_idx >> 16), prod);
+ bnx2_reuse_rx_skb(bp, rxr, skb, (u16) (ring_idx >> 16), prod);
if (hdr_len) {
unsigned int raw_len = len + 4;
int pages = PAGE_ALIGN(raw_len - hdr_len) >> PAGE_SHIFT;
- bnx2_reuse_rx_skb_pages(bp, bnapi, NULL, pages);
+ bnx2_reuse_rx_skb_pages(bp, rxr, NULL, pages);
}
return err;
}
- skb_reserve(skb, bp->rx_offset);
+ skb_reserve(skb, BNX2_RX_OFFSET);
pci_unmap_single(bp->pdev, dma_addr, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
@@ -2668,8 +2778,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
} else {
unsigned int i, frag_len, frag_size, pages;
struct sw_pg *rx_pg;
- u16 pg_cons = bnapi->rx_pg_cons;
- u16 pg_prod = bnapi->rx_pg_prod;
+ u16 pg_cons = rxr->rx_pg_cons;
+ u16 pg_prod = rxr->rx_pg_prod;
frag_size = len + 4 - hdr_len;
pages = PAGE_ALIGN(frag_size) >> PAGE_SHIFT;
@@ -2680,9 +2790,9 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
if (unlikely(frag_len <= 4)) {
unsigned int tail = 4 - frag_len;
- bnapi->rx_pg_cons = pg_cons;
- bnapi->rx_pg_prod = pg_prod;
- bnx2_reuse_rx_skb_pages(bp, bnapi, NULL,
+ rxr->rx_pg_cons = pg_cons;
+ rxr->rx_pg_prod = pg_prod;
+ bnx2_reuse_rx_skb_pages(bp, rxr, NULL,
pages - i);
skb->len -= tail;
if (i == 0) {
@@ -2696,7 +2806,7 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
}
return 0;
}
- rx_pg = &bp->rx_pg_ring[pg_cons];
+ rx_pg = &rxr->rx_pg_ring[pg_cons];
pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping),
PAGE_SIZE, PCI_DMA_FROMDEVICE);
@@ -2707,11 +2817,12 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len);
rx_pg->page = NULL;
- err = bnx2_alloc_rx_page(bp, RX_PG_RING_IDX(pg_prod));
+ err = bnx2_alloc_rx_page(bp, rxr,
+ RX_PG_RING_IDX(pg_prod));
if (unlikely(err)) {
- bnapi->rx_pg_cons = pg_cons;
- bnapi->rx_pg_prod = pg_prod;
- bnx2_reuse_rx_skb_pages(bp, bnapi, skb,
+ rxr->rx_pg_cons = pg_cons;
+ rxr->rx_pg_prod = pg_prod;
+ bnx2_reuse_rx_skb_pages(bp, rxr, skb,
pages - i);
return err;
}
@@ -2724,8 +2835,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
pg_prod = NEXT_RX_BD(pg_prod);
pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
}
- bnapi->rx_pg_prod = pg_prod;
- bnapi->rx_pg_cons = pg_cons;
+ rxr->rx_pg_prod = pg_prod;
+ rxr->rx_pg_cons = pg_cons;
}
return 0;
}
@@ -2733,8 +2844,11 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_napi *bnapi, struct sk_buff *skb,
static inline u16
bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
{
- u16 cons = bnapi->status_blk->status_rx_quick_consumer_index0;
+ u16 cons;
+ /* Tell compiler that status block fields can change. */
+ barrier();
+ cons = *bnapi->hw_rx_cons_ptr;
if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
cons++;
return cons;
@@ -2743,13 +2857,14 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
static int
bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
{
+ struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
struct l2_fhdr *rx_hdr;
int rx_pkt = 0, pg_ring_used = 0;
hw_cons = bnx2_get_hw_rx_cons(bnapi);
- sw_cons = bnapi->rx_cons;
- sw_prod = bnapi->rx_prod;
+ sw_cons = rxr->rx_cons;
+ sw_prod = rxr->rx_prod;
/* Memory barrier necessary as speculative reads of the rx
* buffer can be ahead of the index in the status block
@@ -2765,7 +2880,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
sw_ring_cons = RX_RING_IDX(sw_cons);
sw_ring_prod = RX_RING_IDX(sw_prod);
- rx_buf = &bp->rx_buf_ring[sw_ring_cons];
+ rx_buf = &rxr->rx_buf_ring[sw_ring_cons];
skb = rx_buf->skb;
rx_buf->skb = NULL;
@@ -2773,7 +2888,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
dma_addr = pci_unmap_addr(rx_buf, mapping);
pci_dma_sync_single_for_cpu(bp->pdev, dma_addr,
- bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
+ BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
+ PCI_DMA_FROMDEVICE);
rx_hdr = (struct l2_fhdr *) skb->data;
len = rx_hdr->l2_fhdr_pkt_len;
@@ -2785,7 +2901,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
L2_FHDR_ERRORS_TOO_SHORT |
L2_FHDR_ERRORS_GIANT_FRAME)) {
- bnx2_reuse_rx_skb(bp, bnapi, skb, sw_ring_cons,
+ bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
sw_ring_prod);
goto next_rx;
}
@@ -2805,22 +2921,23 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
new_skb = netdev_alloc_skb(bp->dev, len + 2);
if (new_skb == NULL) {
- bnx2_reuse_rx_skb(bp, bnapi, skb, sw_ring_cons,
+ bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons,
sw_ring_prod);
goto next_rx;
}
/* aligned copy */
- skb_copy_from_linear_data_offset(skb, bp->rx_offset - 2,
+ skb_copy_from_linear_data_offset(skb,
+ BNX2_RX_OFFSET - 2,
new_skb->data, len + 2);
skb_reserve(new_skb, 2);
skb_put(new_skb, len);
- bnx2_reuse_rx_skb(bp, bnapi, skb,
+ bnx2_reuse_rx_skb(bp, rxr, skb,
sw_ring_cons, sw_ring_prod);
skb = new_skb;
- } else if (unlikely(bnx2_rx_skb(bp, bnapi, skb, len, hdr_len,
+ } else if (unlikely(bnx2_rx_skb(bp, rxr, skb, len, hdr_len,
dma_addr, (sw_ring_cons << 16) | sw_ring_prod)))
goto next_rx;
@@ -2869,16 +2986,15 @@ next_rx:
rmb();
}
}
- bnapi->rx_cons = sw_cons;
- bnapi->rx_prod = sw_prod;
+ rxr->rx_cons = sw_cons;
+ rxr->rx_prod = sw_prod;
if (pg_ring_used)
- REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_PG_BDIDX,
- bnapi->rx_pg_prod);
+ REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
- REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, sw_prod);
+ REG_WR16(bp, rxr->rx_bidx_addr, sw_prod);
- REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bnapi->rx_prod_bseq);
+ REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
mmiowb();
@@ -2892,11 +3008,11 @@ next_rx:
static irqreturn_t
bnx2_msi(int irq, void *dev_instance)
{
- struct net_device *dev = dev_instance;
- struct bnx2 *bp = netdev_priv(dev);
- struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+ struct bnx2_napi *bnapi = dev_instance;
+ struct bnx2 *bp = bnapi->bp;
+ struct net_device *dev = bp->dev;
- prefetch(bnapi->status_blk);
+ prefetch(bnapi->status_blk.msi);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
@@ -2913,11 +3029,11 @@ bnx2_msi(int irq, void *dev_instance)
static irqreturn_t
bnx2_msi_1shot(int irq, void *dev_instance)
{
- struct net_device *dev = dev_instance;
- struct bnx2 *bp = netdev_priv(dev);
- struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+ struct bnx2_napi *bnapi = dev_instance;
+ struct bnx2 *bp = bnapi->bp;
+ struct net_device *dev = bp->dev;
- prefetch(bnapi->status_blk);
+ prefetch(bnapi->status_blk.msi);
/* Return here if interrupt is disabled. */
if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -2931,10 +3047,10 @@ bnx2_msi_1shot(int irq, void *dev_instance)
static irqreturn_t
bnx2_interrupt(int irq, void *dev_instance)
{
- struct net_device *dev = dev_instance;
- struct bnx2 *bp = netdev_priv(dev);
- struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
- struct status_block *sblk = bnapi->status_blk;
+ struct bnx2_napi *bnapi = dev_instance;
+ struct bnx2 *bp = bnapi->bp;
+ struct net_device *dev = bp->dev;
+ struct status_block *sblk = bnapi->status_blk.msi;
/* When using INTx, it is possible for the interrupt to arrive
* at the CPU before the status block posted prior to the
@@ -2968,21 +3084,16 @@ bnx2_interrupt(int irq, void *dev_instance)
return IRQ_HANDLED;
}
-static irqreturn_t
-bnx2_tx_msix(int irq, void *dev_instance)
+static inline int
+bnx2_has_fast_work(struct bnx2_napi *bnapi)
{
- struct net_device *dev = dev_instance;
- struct bnx2 *bp = netdev_priv(dev);
- struct bnx2_napi *bnapi = &bp->bnx2_napi[BNX2_TX_VEC];
-
- prefetch(bnapi->status_blk_msix);
+ struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+ struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
- /* Return here if interrupt is disabled. */
- if (unlikely(atomic_read(&bp->intr_sem) != 0))
- return IRQ_HANDLED;
-
- netif_rx_schedule(dev, &bnapi->napi);
- return IRQ_HANDLED;
+ if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) ||
+ (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
+ return 1;
+ return 0;
}
#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \
@@ -2991,10 +3102,9 @@ bnx2_tx_msix(int irq, void *dev_instance)
static inline int
bnx2_has_work(struct bnx2_napi *bnapi)
{
- struct status_block *sblk = bnapi->status_blk;
+ struct status_block *sblk = bnapi->status_blk.msi;
- if ((bnx2_get_hw_rx_cons(bnapi) != bnapi->rx_cons) ||
- (bnx2_get_hw_tx_cons(bnapi) != bnapi->hw_tx_cons))
+ if (bnx2_has_fast_work(bnapi))
return 1;
if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
@@ -3004,33 +3114,9 @@ bnx2_has_work(struct bnx2_napi *bnapi)
return 0;
}
-static int bnx2_tx_poll(struct napi_struct *napi, int budget)
-{
- struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
- struct bnx2 *bp = bnapi->bp;
- int work_done = 0;
- struct status_block_msix *sblk = bnapi->status_blk_msix;
-
- do {
- work_done += bnx2_tx_int(bp, bnapi, budget - work_done);
- if (unlikely(work_done >= budget))
- return work_done;
-
- bnapi->last_status_idx = sblk->status_idx;
- rmb();
- } while (bnx2_get_hw_tx_cons(bnapi) != bnapi->hw_tx_cons);
-
- netif_rx_complete(bp->dev, napi);
- REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
- BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
- bnapi->