netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] bnx2: Enable multi rx rings.
@ 2008-06-19  0:25 Michael Chan
  2008-06-19  0:25 ` [PATCH 1/8] bnx2: Put tx ring variables in a separate struct Michael Chan
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli

Please review these bnx2 patches to enable multiple rx rings for
net-next.  Thanks.



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/8] bnx2: Put tx ring variables in a separate struct.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:39   ` David Miller
  2008-06-19  0:25 ` [PATCH 2/8] bnx2: Put rx " Michael Chan
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

In preparation for multi-ring support, tx ring variables are now put
in a separate bnx2_tx_ring_info struct.  Multi tx ring will not be
enabled until it is fully supported by the stack.  Only 1 tx ring
will be used at the moment.

The functions to allocate/free tx memory and to initialize tx rings
are now modified to handle multiple rings.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |  294 ++++++++++++++++++++++++++++++++--------------------
 drivers/net/bnx2.h |   34 +++---
 2 files changed, 199 insertions(+), 129 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 2c52d2c..61f2b4f 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -226,7 +226,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 +235,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)
@@ -496,10 +496,54 @@ bnx2_netif_start(struct bnx2 *bp)
 }
 
 static void
+bnx2_free_tx_mem(struct bnx2 *bp)
+{
+	int i;
+
+	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;
+	}
+}
+
+static int
+bnx2_alloc_tx_mem(struct bnx2 *bp)
+{
+	int i;
+
+	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;
+
+		txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
+		if (txr->tx_buf_ring == NULL)
+			return -ENOMEM;
+
+		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 void
 bnx2_free_mem(struct bnx2 *bp)
 {
 	int i;
 
+	bnx2_free_tx_mem(bp);
+
 	for (i = 0; i < bp->ctx_pages; i++) {
 		if (bp->ctx_blk[i]) {
 			pci_free_consistent(bp->pdev, BCM_PAGE_SIZE,
@@ -514,13 +558,6 @@ bnx2_free_mem(struct bnx2 *bp)
 		bp->status_blk = NULL;
 		bp->stats_blk = 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,
@@ -545,16 +582,7 @@ bnx2_free_mem(struct bnx2 *bp)
 static int
 bnx2_alloc_mem(struct bnx2 *bp)
 {
-	int i, status_blk_size;
-
-	bp->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL);
-	if (bp->tx_buf_ring == NULL)
-		return -ENOMEM;
-
-	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;
+	int i, status_blk_size, err;
 
 	bp->rx_buf_ring = vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
 	if (bp->rx_buf_ring == NULL)
@@ -634,6 +662,11 @@ bnx2_alloc_mem(struct bnx2 *bp)
 				goto alloc_mem_err;
 		}
 	}
+
+	err = bnx2_alloc_tx_mem(bp);
+	if (err)
+		goto alloc_mem_err;
+
 	return 0;
 
 alloc_mem_err:
@@ -2483,11 +2516,12 @@ 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;
 
 	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;
@@ -2496,7 +2530,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 */
@@ -2526,7 +2560,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);
@@ -2542,8 +2576,8 @@ 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
 	 * memory barrier, there is a small possibility that bnx2_start_xmit()
@@ -2552,10 +2586,10 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 	smp_mb();
 
 	if (unlikely(netif_queue_stopped(bp->dev)) &&
-		     (bnx2_tx_avail(bp, bnapi) > bp->tx_wake_thresh)) {
+		     (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
 		netif_tx_lock(bp->dev);
 		if ((netif_queue_stopped(bp->dev)) &&
-		    (bnx2_tx_avail(bp, bnapi) > bp->tx_wake_thresh))
+		    (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh))
 			netif_wake_queue(bp->dev);
 		netif_tx_unlock(bp->dev);
 	}
@@ -2997,10 +3031,11 @@ bnx2_tx_msix(int irq, void *dev_instance)
 static inline int
 bnx2_has_work(struct bnx2_napi *bnapi)
 {
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 	struct status_block *sblk = bnapi->status_blk;
 
 	if ((bnx2_get_hw_rx_cons(bnapi) != bnapi->rx_cons) ||
-	    (bnx2_get_hw_tx_cons(bnapi) != bnapi->hw_tx_cons))
+	    (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
 		return 1;
 
 	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
@@ -3014,6 +3049,7 @@ 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;
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 	int work_done = 0;
 	struct status_block_msix *sblk = bnapi->status_blk_msix;
 
@@ -3024,7 +3060,7 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
 
 		bnapi->last_status_idx = sblk->status_idx;
 		rmb();
-	} while (bnx2_get_hw_tx_cons(bnapi) != bnapi->hw_tx_cons);
+	} while (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons);
 
 	netif_rx_complete(bp->dev, napi);
 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
@@ -3036,6 +3072,7 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
 static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 			  int work_done, int budget)
 {
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 	struct status_block *sblk = bnapi->status_blk;
 	u32 status_attn_bits = sblk->status_attn_bits;
 	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
@@ -3053,7 +3090,7 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 		REG_RD(bp, BNX2_HC_COMMAND);
 	}
 
-	if (bnx2_get_hw_tx_cons(bnapi) != bnapi->hw_tx_cons)
+	if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
 		bnx2_tx_int(bp, bnapi, 0);
 
 	if (bnx2_get_hw_rx_cons(bnapi) != bnapi->rx_cons)
@@ -4494,13 +4531,15 @@ static void
 bnx2_clear_ring_states(struct bnx2 *bp)
 {
 	struct bnx2_napi *bnapi;
+	struct bnx2_tx_ring_info *txr;
 	int i;
 
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
 		bnapi = &bp->bnx2_napi[i];
+		txr = &bnapi->tx_ring;
 
-		bnapi->tx_cons = 0;
-		bnapi->hw_tx_cons = 0;
+		txr->tx_cons = 0;
+		txr->hw_tx_cons = 0;
 		bnapi->rx_prod_bseq = 0;
 		bnapi->rx_prod = 0;
 		bnapi->rx_cons = 0;
@@ -4510,7 +4549,7 @@ bnx2_clear_ring_states(struct bnx2 *bp)
 }
 
 static void
-bnx2_init_tx_context(struct bnx2 *bp, u32 cid)
+bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
 {
 	u32 val, offset0, offset1, offset2, offset3;
 	u32 cid_addr = GET_CID_ADDR(cid);
@@ -4532,43 +4571,43 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid)
 	val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
 	bnx2_ctx_wr(bp, cid_addr, offset1, val);
 
-	val = (u64) bp->tx_desc_mapping >> 32;
+	val = (u64) txr->tx_desc_mapping >> 32;
 	bnx2_ctx_wr(bp, cid_addr, offset2, val);
 
-	val = (u64) bp->tx_desc_mapping & 0xffffffff;
+	val = (u64) txr->tx_desc_mapping & 0xffffffff;
 	bnx2_ctx_wr(bp, cid_addr, offset3, val);
 }
 
 static void
-bnx2_init_tx_ring(struct bnx2 *bp)
+bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
 {
 	struct tx_bd *txbd;
 	u32 cid = TX_CID;
 	struct bnx2_napi *bnapi;
+	struct bnx2_tx_ring_info *txr;
 
-	bp->tx_vec = 0;
-	if (bp->flags & BNX2_FLAG_USING_MSIX) {
-		cid = TX_TSS_CID;
-		bp->tx_vec = BNX2_TX_VEC;
-		REG_WR(bp, BNX2_TSCH_TSS_CFG, BNX2_TX_INT_NUM |
-		       (TX_TSS_CID << 7));
-	}
-	bnapi = &bp->bnx2_napi[bp->tx_vec];
+	bnapi = &bp->bnx2_napi[ring_num];
+	txr = &bnapi->tx_ring;
+
+	if (ring_num == 0)
+		cid = TX_CID;
+	else
+		cid = TX_TSS_CID + ring_num - 1;
 
 	bp->tx_wake_thresh = bp->tx_ring_size / 2;
 
-	txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
+	txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT];
 
-	txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
-	txbd->tx_bd_haddr_lo = (u64) bp->tx_desc_mapping & 0xffffffff;
+	txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32;
+	txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff;
 
-	bp->tx_prod = 0;
-	bp->tx_prod_bseq = 0;
+	txr->tx_prod = 0;
+	txr->tx_prod_bseq = 0;
 
-	bp->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX;
-	bp->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ;
+	txr->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX;
+	txr->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ;
 
-	bnx2_init_tx_context(bp, cid);
+	bnx2_init_tx_context(bp, cid, txr);
 }
 
 static void
@@ -4665,6 +4704,24 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 	REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bnapi->rx_prod_bseq);
 }
 
+static void
+bnx2_init_all_rings(struct bnx2 *bp)
+{
+	int i;
+
+	bnx2_clear_ring_states(bp);
+
+	REG_WR(bp, BNX2_TSCH_TSS_CFG, 0);
+	for (i = 0; i < bp->num_tx_rings; i++)
+		bnx2_init_tx_ring(bp, i);
+
+	if (bp->num_tx_rings > 1)
+		REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
+		       (TX_TSS_CID << 7));
+
+	bnx2_init_rx_ring(bp);
+}
+
 static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
 {
 	u32 max, num_rings = 1;
@@ -4728,36 +4785,42 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
 {
 	int i;
 
-	if (bp->tx_buf_ring == NULL)
-		return;
-
-	for (i = 0; i < TX_DESC_CNT; ) {
-		struct sw_bd *tx_buf = &bp->tx_buf_ring[i];
-		struct sk_buff *skb = tx_buf->skb;
-		int j, last;
+	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;
+		int j;
 
-		if (skb == NULL) {
-			i++;
+		if (txr->tx_buf_ring == NULL)
 			continue;
-		}
 
-		pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping),
+		for (j = 0; j < TX_DESC_CNT; ) {
+			struct sw_bd *tx_buf = &txr->tx_buf_ring[j];
+			struct sk_buff *skb = tx_buf->skb;
+			int k, last;
+
+			if (skb == NULL) {
+				j++;
+				continue;
+			}
+
+			pci_unmap_single(bp->pdev,
+					 pci_unmap_addr(tx_buf, mapping),
 			skb_headlen(skb), PCI_DMA_TODEVICE);
 
-		tx_buf->skb = NULL;
+			tx_buf->skb = NULL;
 
-		last = skb_shinfo(skb)->nr_frags;
-		for (j = 0; j < last; j++) {
-			tx_buf = &bp->tx_buf_ring[i + j + 1];
-			pci_unmap_page(bp->pdev,
-				pci_unmap_addr(tx_buf, mapping),
-				skb_shinfo(skb)->frags[j].size,
-				PCI_DMA_TODEVICE);
+			last = skb_shinfo(skb)->nr_frags;
+			for (k = 0; k < last; k++) {
+				tx_buf = &txr->tx_buf_ring[j + k + 1];
+				pci_unmap_page(bp->pdev,
+					pci_unmap_addr(tx_buf, mapping),
+					skb_shinfo(skb)->frags[j].size,
+					PCI_DMA_TODEVICE);
+			}
+			dev_kfree_skb(skb);
+			j += k + 1;
 		}
-		dev_kfree_skb(skb);
-		i += j + 1;
 	}
-
 }
 
 static void
@@ -4806,9 +4869,7 @@ bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
 	if ((rc = bnx2_init_chip(bp)) != 0)
 		return rc;
 
-	bnx2_clear_ring_states(bp);
-	bnx2_init_tx_ring(bp);
-	bnx2_init_rx_ring(bp);
+	bnx2_init_all_rings(bp);
 	return 0;
 }
 
@@ -5081,11 +5142,11 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	struct l2_fhdr *rx_hdr;
 	int ret = -ENODEV;
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 
 	tx_napi = bnapi;
-	if (bp->flags & BNX2_FLAG_USING_MSIX)
-		tx_napi = &bp->bnx2_napi[BNX2_TX_VEC];
 
+	txr = &tx_napi->tx_ring;
 	if (loopback_mode == BNX2_MAC_LOOPBACK) {
 		bp->loopback = MAC_LOOPBACK;
 		bnx2_set_mac_loopback(bp);
@@ -5123,7 +5184,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 
 	num_pkts = 0;
 
-	txbd = &bp->tx_desc_ring[TX_RING_IDX(bp->tx_prod)];
+	txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)];
 
 	txbd->tx_bd_haddr_hi = (u64) map >> 32;
 	txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
@@ -5131,11 +5192,11 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
 
 	num_pkts++;
-	bp->tx_prod = NEXT_TX_BD(bp->tx_prod);
-	bp->tx_prod_bseq += pkt_size;
+	txr->tx_prod = NEXT_TX_BD(txr->tx_prod);
+	txr->tx_prod_bseq += pkt_size;
 
-	REG_WR16(bp, bp->tx_bidx_addr, bp->tx_prod);
-	REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq);
+	REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
+	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
 
 	udelay(100);
 
@@ -5149,7 +5210,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
 	dev_kfree_skb(skb);
 
-	if (bnx2_get_hw_tx_cons(tx_napi) != bp->tx_prod)
+	if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod)
 		goto loopback_test_done;
 
 	rx_idx = bnx2_get_hw_rx_cons(bnapi);
@@ -5527,20 +5588,18 @@ bnx2_enable_msix(struct bnx2 *bp)
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
 		msix_ent[i].entry = i;
 		msix_ent[i].vector = 0;
+
+		strcpy(bp->irq_tbl[i].name, bp->dev->name);
+		if (i == 0)
+			bp->irq_tbl[i].handler = bnx2_msi_1shot;
+		else
+			bp->irq_tbl[i].handler = bnx2_tx_msix;
 	}
 
 	rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC);
 	if (rc != 0)
 		return;
 
-	bp->irq_tbl[BNX2_BASE_VEC].handler = bnx2_msi_1shot;
-	bp->irq_tbl[BNX2_TX_VEC].handler = bnx2_tx_msix;
-
-	strcpy(bp->irq_tbl[BNX2_BASE_VEC].name, bp->dev->name);
-	strcat(bp->irq_tbl[BNX2_BASE_VEC].name, "-base");
-	strcpy(bp->irq_tbl[BNX2_TX_VEC].name, bp->dev->name);
-	strcat(bp->irq_tbl[BNX2_TX_VEC].name, "-tx");
-
 	bp->irq_nvecs = BNX2_MAX_MSIX_VEC;
 	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
@@ -5571,6 +5630,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 			bp->irq_tbl[0].vector = bp->pdev->irq;
 		}
 	}
+	bp->num_tx_rings = 1;
 }
 
 /* Called with rtnl_lock */
@@ -5585,12 +5645,15 @@ bnx2_open(struct net_device *dev)
 	bnx2_set_power_state(bp, PCI_D0);
 	bnx2_disable_int(bp);
 
+	bnx2_setup_int_mode(bp, disable_msi);
+	bnx2_napi_enable(bp);
 	rc = bnx2_alloc_mem(bp);
-	if (rc)
+	if (rc) {
+		bnx2_napi_disable(bp);
+		bnx2_free_mem(bp);
 		return rc;
+	}
 
-	bnx2_setup_int_mode(bp, disable_msi);
-	bnx2_napi_enable(bp);
 	rc = bnx2_request_irq(bp);
 
 	if (rc) {
@@ -5711,9 +5774,10 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	u32 len, vlan_tag_flags, last_frag, mss;
 	u16 prod, ring_prod;
 	int i;
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[bp->tx_vec];
+	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 
-	if (unlikely(bnx2_tx_avail(bp, bnapi) <
+	if (unlikely(bnx2_tx_avail(bp, txr) <
 	    (skb_shinfo(skb)->nr_frags + 1))) {
 		netif_stop_queue(dev);
 		printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
@@ -5722,7 +5786,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_BUSY;
 	}
 	len = skb_headlen(skb);
-	prod = bp->tx_prod;
+	prod = txr->tx_prod;
 	ring_prod = TX_RING_IDX(prod);
 
 	vlan_tag_flags = 0;
@@ -5784,11 +5848,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
-	tx_buf = &bp->tx_buf_ring[ring_prod];
+	tx_buf = &txr->tx_buf_ring[ring_prod];
 	tx_buf->skb = skb;
 	pci_unmap_addr_set(tx_buf, mapping, mapping);
 
-	txbd = &bp->tx_desc_ring[ring_prod];
+	txbd = &txr->tx_desc_ring[ring_prod];
 
 	txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
 	txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
@@ -5802,12 +5866,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		prod = NEXT_TX_BD(prod);
 		ring_prod = TX_RING_IDX(prod);
-		txbd = &bp->tx_desc_ring[ring_prod];
+		txbd = &txr->tx_desc_ring[ring_prod];
 
 		len = frag->size;
 		mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset,
 			len, PCI_DMA_TODEVICE);
-		pci_unmap_addr_set(&bp->tx_buf_ring[ring_prod],
+		pci_unmap_addr_set(&txr->tx_buf_ring[ring_prod],
 				mapping, mapping);
 
 		txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
@@ -5819,19 +5883,19 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
 
 	prod = NEXT_TX_BD(prod);
-	bp->tx_prod_bseq += skb->len;
+	txr->tx_prod_bseq += skb->len;
 
-	REG_WR16(bp, bp->tx_bidx_addr, prod);
-	REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq);
+	REG_WR16(bp, txr->tx_bidx_addr, prod);
+	REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
 
 	mmiowb();
 
-	bp->tx_prod = prod;
+	txr->tx_prod = prod;
 	dev->trans_start = jiffies;
 
-	if (unlikely(bnx2_tx_avail(bp, bnapi) <= MAX_SKB_FRAGS)) {
+	if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) {
 		netif_stop_queue(dev);
-		if (bnx2_tx_avail(bp, bnapi) > bp->tx_wake_thresh)
+		if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh)
 			netif_wake_queue(dev);
 	}
 
@@ -7390,15 +7454,19 @@ static void __devinit
 bnx2_init_napi(struct bnx2 *bp)
 {
 	int i;
-	struct bnx2_napi *bnapi;
 
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
-		bnapi = &bp->bnx2_napi[i];
+		struct bnx2_napi *bnapi = &bp->bnx2_napi[i];
+		int (*poll)(struct napi_struct *, int);
+
+		if (i == 0)
+			poll = bnx2_poll;
+		else
+			poll = bnx2_tx_poll;
+
+		netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64);
 		bnapi->bp = bp;
 	}
-	netif_napi_add(bp->dev, &bp->bnx2_napi[0].napi, bnx2_poll, 64);
-	netif_napi_add(bp->dev, &bp->bnx2_napi[BNX2_TX_VEC].napi, bnx2_tx_poll,
-		       64);
 }
 
 static int __devinit
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index be7ccb5..e4f0fb4 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6569,6 +6569,21 @@ struct bnx2_irq {
 	char		name[16];
 };
 
+struct bnx2_tx_ring_info {
+	u32			tx_prod_bseq;
+	u16			tx_prod;
+	u32			tx_bidx_addr;
+	u32			tx_bseq_addr;
+
+	struct tx_bd		*tx_desc_ring;
+	struct sw_bd		*tx_buf_ring;
+
+	u16			tx_cons;
+	u16			hw_tx_cons;
+
+	dma_addr_t		tx_desc_mapping;
+};
+
 struct bnx2_napi {
 	struct napi_struct	napi		____cacheline_aligned;
 	struct bnx2		*bp;
@@ -6577,9 +6592,6 @@ struct bnx2_napi {
 	u32 			last_status_idx;
 	u32			int_num;
 
-	u16			tx_cons;
-	u16			hw_tx_cons;
-
 	u32			rx_prod_bseq;
 	u16			rx_prod;
 	u16			rx_cons;
@@ -6587,6 +6599,7 @@ struct bnx2_napi {
 	u16			rx_pg_prod;
 	u16			rx_pg_cons;
 
+	struct bnx2_tx_ring_info	tx_ring;
 };
 
 struct bnx2 {
@@ -6614,14 +6627,6 @@ struct bnx2 {
 					 BNX2_FLAG_USING_MSIX)
 #define BNX2_FLAG_JUMBO_BROKEN		0x00000800
 
-	/* Put tx producer and consumer fields in separate cache lines. */
-
-	u32		tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
-	u16		tx_prod;
-	u8		tx_vec;
-	u32		tx_bidx_addr;
-	u32		tx_bseq_addr;
-
 	struct bnx2_napi	bnx2_napi[BNX2_MAX_MSIX_VEC];
 
 #ifdef BCM_VLAN
@@ -6643,8 +6648,6 @@ struct bnx2 {
 	struct rx_bd		*rx_pg_desc_ring[MAX_RX_PG_RINGS];
 
 	/* TX constants */
-	struct tx_bd	*tx_desc_ring;
-	struct sw_bd	*tx_buf_ring;
 	int		tx_ring_size;
 	u32		tx_wake_thresh;
 
@@ -6722,9 +6725,6 @@ struct bnx2 {
 	u16			fw_wr_seq;
 	u16			fw_drv_pulse_wr_seq;
 
-	dma_addr_t		tx_desc_mapping;
-
-
 	int			rx_max_ring;
 	int			rx_ring_size;
 	dma_addr_t		rx_desc_mapping[MAX_RX_RINGS];
@@ -6812,6 +6812,8 @@ struct bnx2 {
 
 	struct bnx2_irq		irq_tbl[BNX2_MAX_MSIX_VEC];
 	int			irq_nvecs;
+
+	u8			num_tx_rings;
 };
 
 #define REG_RD(bp, offset)					\
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/8] bnx2: Put rx ring variables in a separate struct.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
  2008-06-19  0:25 ` [PATCH 1/8] bnx2: Put tx ring variables in a separate struct Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:39   ` David Miller
  2008-06-19  0:25 ` [PATCH 3/8] bnx2: Optimize fast-path tx and rx work Michael Chan
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

In preparation for multi-ring support, rx ring variables are now put
in a separate bnx2_rx_ring_info struct.  With MSI-X, we can support
multiple rx rings.

The functions to allocate/free rx memory and to initialize rx rings
are now modified to handle multiple rings.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |  390 +++++++++++++++++++++++++++++++---------------------
 drivers/net/bnx2.h |   38 ++++--
 2 files changed, 259 insertions(+), 169 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 61f2b4f..4360528 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -515,6 +515,40 @@ bnx2_free_tx_mem(struct bnx2 *bp)
 	}
 }
 
+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;
+	}
+}
+
 static int
 bnx2_alloc_tx_mem(struct bnx2 *bp)
 {
@@ -537,12 +571,62 @@ bnx2_alloc_tx_mem(struct bnx2 *bp)
 	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;
+
+		rxr->rx_buf_ring =
+			vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
+		if (rxr->rx_buf_ring == NULL)
+			return -ENOMEM;
+
+		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) {
+			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;
+
+		}
+	}
+	return 0;
+}
+
 static void
 bnx2_free_mem(struct bnx2 *bp)
 {
 	int i;
 
 	bnx2_free_tx_mem(bp);
+	bnx2_free_rx_mem(bp);
 
 	for (i = 0; i < bp->ctx_pages; i++) {
 		if (bp->ctx_blk[i]) {
@@ -558,25 +642,6 @@ bnx2_free_mem(struct bnx2 *bp)
 		bp->status_blk = NULL;
 		bp->stats_blk = 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
@@ -584,40 +649,6 @@ bnx2_alloc_mem(struct bnx2 *bp)
 {
 	int i, status_blk_size, err;
 
-	bp->rx_buf_ring = vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
-	if (bp->rx_buf_ring == NULL)
-		goto alloc_mem_err;
-
-	memset(bp->rx_buf_ring, 0, SW_RXBD_RING_SIZE * bp->rx_max_ring);
-
-	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;
-
-	}
-
-	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;
-
-		memset(bp->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
-		       bp->rx_max_pg_ring);
-	}
-
-	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;
-
-	}
-
 	/* Combine status and statistics blocks into one allocation. */
 	status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
 	if (bp->flags & BNX2_FLAG_MSIX_CAP)
@@ -663,6 +694,10 @@ bnx2_alloc_mem(struct bnx2 *bp)
 		}
 	}
 
+	err = bnx2_alloc_rx_mem(bp);
+	if (err)
+		goto alloc_mem_err;
+
 	err = bnx2_alloc_tx_mem(bp);
 	if (err)
 		goto alloc_mem_err;
@@ -1026,9 +1061,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;
@@ -1061,6 +1096,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)
 {
@@ -1126,7 +1174,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;
 }
@@ -2398,12 +2446,12 @@ bnx2_set_mac_addr(struct bnx2 *bp)
 }
 
 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)
@@ -2418,9 +2466,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)
@@ -2434,12 +2482,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);
@@ -2459,7 +2507,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;
 }
@@ -2597,23 +2645,23 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 }
 
 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;
@@ -2642,25 +2690,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),
 		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;
 
@@ -2670,28 +2718,28 @@ 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;
 	}
@@ -2706,8 +2754,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;
@@ -2718,9 +2766,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) {
@@ -2734,7 +2782,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);
@@ -2745,11 +2793,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;
 			}
@@ -2762,8 +2811,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;
 }
@@ -2771,7 +2820,12 @@ 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;
+
+	if (bnapi->int_num == 0)
+		cons = bnapi->status_blk->status_rx_quick_consumer_index0;
+	else
+		cons = bnapi->status_blk_msix->status_rx_quick_consumer_index;
 
 	if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
 		cons++;
@@ -2781,13 +2835,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
@@ -2803,7 +2858,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;
@@ -2824,7 +2879,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;
 		}
@@ -2844,7 +2899,7 @@ 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;
 			}
@@ -2856,11 +2911,11 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 			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;
 
@@ -2909,16 +2964,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();
 
@@ -3032,9 +3086,10 @@ static inline int
 bnx2_has_work(struct bnx2_napi *bnapi)
 {
 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
 	struct status_block *sblk = bnapi->status_blk;
 
-	if ((bnx2_get_hw_rx_cons(bnapi) != bnapi->rx_cons) ||
+	if ((bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons) ||
 	    (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons))
 		return 1;
 
@@ -3073,6 +3128,7 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 			  int work_done, int budget)
 {
 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
 	struct status_block *sblk = bnapi->status_blk;
 	u32 status_attn_bits = sblk->status_attn_bits;
 	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
@@ -3093,7 +3149,7 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 	if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
 		bnx2_tx_int(bp, bnapi, 0);
 
-	if (bnx2_get_hw_rx_cons(bnapi) != bnapi->rx_cons)
+	if (bnx2_get_hw_rx_cons(bnapi) != rxr->rx_cons)
 		work_done += bnx2_rx_int(bp, bnapi, budget - work_done);
 
 	return work_done;
@@ -4532,19 +4588,21 @@ bnx2_clear_ring_states(struct bnx2 *bp)
 {
 	struct bnx2_napi *bnapi;
 	struct bnx2_tx_ring_info *txr;
+	struct bnx2_rx_ring_info *rxr;
 	int i;
 
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
 		bnapi = &bp->bnx2_napi[i];
 		txr = &bnapi->tx_ring;
+		rxr = &bnapi->rx_ring;
 
 		txr->tx_cons = 0;
 		txr->hw_tx_cons = 0;
-		bnapi->rx_prod_bseq = 0;
-		bnapi->rx_prod = 0;
-		bnapi->rx_cons = 0;
-		bnapi->rx_pg_prod = 0;
-		bnapi->rx_pg_cons = 0;
+		rxr->rx_prod_bseq = 0;
+		rxr->rx_prod = 0;
+		rxr->rx_cons = 0;
+		rxr->rx_pg_prod = 0;
+		rxr->rx_pg_cons = 0;
 	}
 }
 
@@ -4635,17 +4693,25 @@ bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
 }
 
 static void
-bnx2_init_rx_ring(struct bnx2 *bp)
+bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
 {
 	int i;
 	u16 prod, ring_prod;
-	u32 val, rx_cid_addr = GET_CID_ADDR(RX_CID);
-	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+	u32 cid, rx_cid_addr, val;
+	struct bnx2_napi *bnapi = &bp->bnx2_napi[ring_num];
+	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
+
+	if (ring_num == 0)
+		cid = RX_CID;
+	else
+		cid = RX_RSS_CID + ring_num - 1;
 
-	bnx2_init_rxbd_rings(bp->rx_desc_ring, bp->rx_desc_mapping,
+	rx_cid_addr = GET_CID_ADDR(cid);
+
+	bnx2_init_rxbd_rings(rxr->rx_desc_ring, rxr->rx_desc_mapping,
 			     bp->rx_buf_use_size, bp->rx_max_ring);
 
-	bnx2_init_rx_context0(bp);
+	bnx2_init_rx_context(bp, cid);
 
 	if (CHIP_NUM(bp) == CHIP_NUM_5709) {
 		val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
@@ -4654,54 +4720,56 @@ bnx2_init_rx_ring(struct bnx2 *bp)
 
 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
 	if (bp->rx_pg_ring_size) {
-		bnx2_init_rxbd_rings(bp->rx_pg_desc_ring,
-				     bp->rx_pg_desc_mapping,
+		bnx2_init_rxbd_rings(rxr->rx_pg_desc_ring,
+				     rxr->rx_pg_desc_mapping,
 				     PAGE_SIZE, bp->rx_max_pg_ring);
 		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
 		       BNX2_L2CTX_RBDC_JUMBO_KEY);
 
-		val = (u64) bp->rx_pg_desc_mapping[0] >> 32;
+		val = (u64) rxr->rx_pg_desc_mapping[0] >> 32;
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
 
-		val = (u64) bp->rx_pg_desc_mapping[0] & 0xffffffff;
+		val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff;
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
 
 		if (CHIP_NUM(bp) == CHIP_NUM_5709)
 			REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
 	}
 
-	val = (u64) bp->rx_desc_mapping[0] >> 32;
+	val = (u64) rxr->rx_desc_mapping[0] >> 32;
 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
 
-	val = (u64) bp->rx_desc_mapping[0] & 0xffffffff;
+	val = (u64) rxr->rx_desc_mapping[0] & 0xffffffff;
 	bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
 
-	ring_prod = prod = bnapi->rx_pg_prod;
+	ring_prod = prod = rxr->rx_pg_prod;
 	for (i = 0; i < bp->rx_pg_ring_size; i++) {
-		if (bnx2_alloc_rx_page(bp, ring_prod) < 0)
+		if (bnx2_alloc_rx_page(bp, rxr, ring_prod) < 0)
 			break;
 		prod = NEXT_RX_BD(prod);
 		ring_prod = RX_PG_RING_IDX(prod);
 	}
-	bnapi->rx_pg_prod = prod;
+	rxr->rx_pg_prod = prod;
 
-	ring_prod = prod = bnapi->rx_prod;
+	ring_prod = prod = rxr->rx_prod;
 	for (i = 0; i < bp->rx_ring_size; i++) {
-		if (bnx2_alloc_rx_skb(bp, bnapi, ring_prod) < 0) {
+		if (bnx2_alloc_rx_skb(bp, rxr, ring_prod) < 0)
 			break;
-		}
 		prod = NEXT_RX_BD(prod);
 		ring_prod = RX_RING_IDX(prod);
 	}
-	bnapi->rx_prod = prod;
+	rxr->rx_prod = prod;
+
+	rxr->rx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BDIDX;
+	rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ;
+	rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX;
 
-	REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_PG_BDIDX,
-		 bnapi->rx_pg_prod);
-	REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod);
+	REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
+	REG_WR16(bp, rxr->rx_bidx_addr, 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);
 }
 
 static void
@@ -4719,7 +4787,8 @@ bnx2_init_all_rings(struct bnx2 *bp)
 		REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
 		       (TX_TSS_CID << 7));
 
-	bnx2_init_rx_ring(bp);
+	for (i = 0; i < bp->num_rx_rings; i++)
+		bnx2_init_rx_ring(bp, i);
 }
 
 static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
@@ -4828,25 +4897,33 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
 {
 	int i;
 
-	if (bp->rx_buf_ring == NULL)
-		return;
+	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 (i = 0; i < bp->rx_max_ring_idx; i++) {
-		struct sw_bd *rx_buf = &bp->rx_buf_ring[i];
-		struct sk_buff *skb = rx_buf->skb;
+		if (rxr->rx_buf_ring == NULL)
+			return;
 
-		if (skb == NULL)
-			continue;
+		for (j = 0; j < bp->rx_max_ring_idx; j++) {
+			struct sw_bd *rx_buf = &rxr->rx_buf_ring[j];
+			struct sk_buff *skb = rx_buf->skb;
 
-		pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping),
-			bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+			if (skb == NULL)
+				continue;
 
-		rx_buf->skb = NULL;
+			pci_unmap_single(bp->pdev,
+					 pci_unmap_addr(rx_buf, mapping),
+					 bp->rx_buf_use_size,
+					 PCI_DMA_FROMDEVICE);
 
-		dev_kfree_skb(skb);
+			rx_buf->skb = NULL;
+
+			dev_kfree_skb(skb);
+		}
+		for (j = 0; j < bp->rx_max_pg_ring_idx; j++)
+			bnx2_free_rx_page(bp, rxr, j);
 	}
-	for (i = 0; i < bp->rx_max_pg_ring_idx; i++)
-		bnx2_free_rx_page(bp, i);
 }
 
 static void
@@ -5143,10 +5220,12 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 	int ret = -ENODEV;
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
 
 	tx_napi = bnapi;
 
 	txr = &tx_napi->tx_ring;
+	rxr = &bnapi->rx_ring;
 	if (loopback_mode == BNX2_MAC_LOOPBACK) {
 		bp->loopback = MAC_LOOPBACK;
 		bnx2_set_mac_loopback(bp);
@@ -5218,7 +5297,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
 		goto loopback_test_done;
 	}
 
-	rx_buf = &bp->rx_buf_ring[rx_start_idx];
+	rx_buf = &rxr->rx_buf_ring[rx_start_idx];
 	rx_skb = rx_buf->skb;
 
 	rx_hdr = (struct l2_fhdr *) rx_skb->data;
@@ -5631,6 +5710,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 		}
 	}
 	bp->num_tx_rings = 1;
+	bp->num_rx_rings = 1;
 }
 
 /* Called with rtnl_lock */
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index e4f0fb4..1c5ce80 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6479,6 +6479,7 @@ struct l2_fhdr {
 #define TX_CID		16
 #define TX_TSS_CID	32
 #define RX_CID		0
+#define RX_RSS_CID	4
 
 #define MB_TX_CID_ADDR	MB_GET_CID_ADDR(TX_CID)
 #define MB_RX_CID_ADDR	MB_GET_CID_ADDR(RX_CID)
@@ -6584,6 +6585,27 @@ struct bnx2_tx_ring_info {
 	dma_addr_t		tx_desc_mapping;
 };
 
+struct bnx2_rx_ring_info {
+	u32			rx_prod_bseq;
+	u16			rx_prod;
+	u16			rx_cons;
+
+	u32			rx_bidx_addr;
+	u32			rx_bseq_addr;
+	u32			rx_pg_bidx_addr;
+
+	u16			rx_pg_prod;
+	u16			rx_pg_cons;
+
+	struct sw_bd		*rx_buf_ring;
+	struct rx_bd		*rx_desc_ring[MAX_RX_RINGS];
+	struct sw_pg		*rx_pg_ring;
+	struct rx_bd		*rx_pg_desc_ring[MAX_RX_PG_RINGS];
+
+	dma_addr_t		rx_desc_mapping[MAX_RX_RINGS];
+	dma_addr_t		rx_pg_desc_mapping[MAX_RX_PG_RINGS];
+};
+
 struct bnx2_napi {
 	struct napi_struct	napi		____cacheline_aligned;
 	struct bnx2		*bp;
@@ -6592,13 +6614,7 @@ struct bnx2_napi {
 	u32 			last_status_idx;
 	u32			int_num;
 
-	u32			rx_prod_bseq;
-	u16			rx_prod;
-	u16			rx_cons;
-
-	u16			rx_pg_prod;
-	u16			rx_pg_cons;
-
+	struct bnx2_rx_ring_info	rx_ring;
 	struct bnx2_tx_ring_info	tx_ring;
 };
 
@@ -6642,11 +6658,6 @@ struct bnx2 {
 
 	u32			rx_csum;
 
-	struct sw_bd		*rx_buf_ring;
-	struct rx_bd		*rx_desc_ring[MAX_RX_RINGS];
-	struct sw_pg		*rx_pg_ring;
-	struct rx_bd		*rx_pg_desc_ring[MAX_RX_PG_RINGS];
-
 	/* TX constants */
 	int		tx_ring_size;
 	u32		tx_wake_thresh;
@@ -6727,11 +6738,9 @@ struct bnx2 {
 
 	int			rx_max_ring;
 	int			rx_ring_size;
-	dma_addr_t		rx_desc_mapping[MAX_RX_RINGS];
 
 	int			rx_max_pg_ring;
 	int			rx_pg_ring_size;
-	dma_addr_t		rx_pg_desc_mapping[MAX_RX_PG_RINGS];
 
 	u16			tx_quick_cons_trip;
 	u16			tx_quick_cons_trip_int;
@@ -6814,6 +6823,7 @@ struct bnx2 {
 	int			irq_nvecs;
 
 	u8			num_tx_rings;
+	u8			num_rx_rings;
 };
 
 #define REG_RD(bp, offset)					\
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/8] bnx2: Optimize fast-path tx and rx work.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
  2008-06-19  0:25 ` [PATCH 1/8] bnx2: Put tx ring variables in a separate struct Michael Chan
  2008-06-19  0:25 ` [PATCH 2/8] bnx2: Put rx " Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:41   ` David Miller
  2008-06-19  0:25 ` [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors Michael Chan
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

Add hw_tx_cons_ptr and hw_rx_cons_ptr to speed up the retreival of
the tx and rx consumer index, since the MSI-X and default status
blocks have different structures.

Combine status_blk and status_blk_msix into a union.  We'll only use
one type of status block for each vector.

Separate the code to detect more rx and tx work from the code to
detect link related work.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |  107 ++++++++++++++++++++++++++++++++--------------------
 drivers/net/bnx2.h |    9 +++-
 2 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 4360528..cc70bdb 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -624,6 +624,7 @@ 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);
@@ -636,10 +637,11 @@ bnx2_free_mem(struct bnx2 *bp)
 			bp->ctx_blk[i] = NULL;
 		}
 	}
-	if (bp->status_blk) {
+	if (bnapi->status_blk.msi) {
 		pci_free_consistent(bp->pdev, bp->status_stats_size,
-				    bp->status_blk, bp->status_blk_mapping);
-		bp->status_blk = NULL;
+				    bnapi->status_blk.msi,
+				    bp->status_blk_mapping);
+		bnapi->status_blk.msi = NULL;
 		bp->stats_blk = NULL;
 	}
 }
@@ -648,6 +650,8 @@ 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));
@@ -657,27 +661,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 = &bp->bnx2_napi[i];
 
-			bnapi->status_blk_msix = (void *)
-				((unsigned long) bp->status_blk +
-				 BNX2_SBLK_MSIX_ALIGN_SIZE * 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;
 
@@ -2515,7 +2529,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, 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;
 
@@ -2551,11 +2565,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;
@@ -2822,11 +2834,9 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
 {
 	u16 cons;
 
-	if (bnapi->int_num == 0)
-		cons = bnapi->status_blk->status_rx_quick_consumer_index0;
-	else
-		cons = bnapi->status_blk_msix->status_rx_quick_consumer_index;
-
+	/* 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;
@@ -2990,7 +3000,7 @@ bnx2_msi(int irq, void *dev_instance)
 	struct bnx2 *bp = netdev_priv(dev);
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
 
-	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);
@@ -3011,7 +3021,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
 	struct bnx2 *bp = netdev_priv(dev);
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
 
-	prefetch(bnapi->status_blk);
+	prefetch(bnapi->status_blk.msi);
 
 	/* Return here if interrupt is disabled. */
 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3028,7 +3038,7 @@ 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 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
@@ -3069,7 +3079,7 @@ bnx2_tx_msix(int irq, void *dev_instance)
 	struct bnx2 *bp = netdev_priv(dev);
 	struct bnx2_napi *bnapi = &bp->bnx2_napi[BNX2_TX_VEC];
 
-	prefetch(bnapi->status_blk_msix);
+	prefetch(bnapi->status_blk.msix);
 
 	/* Return here if interrupt is disabled. */
 	if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3079,19 +3089,28 @@ bnx2_tx_msix(int irq, void *dev_instance)
 	return IRQ_HANDLED;
 }
 
-#define STATUS_ATTN_EVENTS	(STATUS_ATTN_BITS_LINK_STATE | \
-				 STATUS_ATTN_BITS_TIMER_ABORT)
-
 static inline int
-bnx2_has_work(struct bnx2_napi *bnapi)
+bnx2_has_fast_work(struct bnx2_napi *bnapi)
 {
 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-	struct status_block *sblk = bnapi->status_blk;
 
 	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 | \
+				 STATUS_ATTN_BITS_TIMER_ABORT)
+
+static inline int
+bnx2_has_work(struct bnx2_napi *bnapi)
+{
+	struct status_block *sblk = bnapi->status_blk.msi;
+
+	if (bnx2_has_fast_work(bnapi))
+		return 1;
 
 	if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
 	    (sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
@@ -3106,7 +3125,7 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
 	struct bnx2 *bp = bnapi->bp;
 	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
 	int work_done = 0;
-	struct status_block_msix *sblk = bnapi->status_blk_msix;
+	struct status_block_msix *sblk = bnapi->status_blk.msix;
 
 	do {
 		work_done += bnx2_tx_int(bp, bnapi, budget - work_done);
@@ -3124,12 +3143,9 @@ static int bnx2_tx_poll(struct napi_struct *napi, int budget)
 	return work_done;
 }
 
-static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
-			  int work_done, int budget)
+static int bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
 {
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
-	struct status_block *sblk = bnapi->status_blk;
+	struct status_block *sblk = bnapi->status_blk.msi;
 	u32 status_attn_bits = sblk->status_attn_bits;
 	u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
 
@@ -3145,6 +3161,13 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 		       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
 		REG_RD(bp, BNX2_HC_COMMAND);
 	}
+}
+
+static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
+			  int work_done, int budget)
+{
+	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
+	struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring;
 
 	if (bnx2_get_hw_tx_cons(bnapi) != txr->hw_tx_cons)
 		bnx2_tx_int(bp, bnapi, 0);
@@ -3160,9 +3183,11 @@ static int bnx2_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 *sblk = bnapi->status_blk;
+	struct status_block *sblk = bnapi->status_blk.msi;
 
 	while (1) {
+		bnx2_poll_link(bp, bnapi);
+
 		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
 
 		if (unlikely(work_done >= budget))
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 1c5ce80..362bef6 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -6609,8 +6609,12 @@ struct bnx2_rx_ring_info {
 struct bnx2_napi {
 	struct napi_struct	napi		____cacheline_aligned;
 	struct bnx2		*bp;
-	struct status_block	*status_blk;
-	struct status_block_msix	*status_blk_msix;
+	union {
+		struct status_block		*msi;
+		struct status_block_msix	*msix;
+	} status_blk;
+	u16			*hw_tx_cons_ptr;
+	u16			*hw_rx_cons_ptr;
 	u32 			last_status_idx;
 	u32			int_num;
 
@@ -6759,7 +6763,6 @@ struct bnx2 {
 
 	u32			stats_ticks;
 
-	struct status_block	*status_blk;
 	dma_addr_t		status_blk_mapping;
 
 	struct statistics_block	*stats_blk;
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
                   ` (2 preceding siblings ...)
  2008-06-19  0:25 ` [PATCH 3/8] bnx2: Optimize fast-path tx and rx work Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:42   ` David Miller
  2008-06-19  0:25 ` [PATCH 6/8] bnx2: Turn on multi rx rings Michael Chan
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

Use the same MSI-X handler to schedule NAPI.  Change the dev_instance
void pointer to the bnx2_napi struct instead so we can have the proper
context for each MSI-X vector.

Add a new bnx2_poll_msix() that is optimized for handling MSI-X
NAPI polling of rx/tx work only.  Remove the old bnx2_tx_poll() that
is no longer needed.  Each MSI-X vector handles 1 tx and 1 rx ring.
The first vector handles link events as well.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |   99 +++++++++++++++++++++-------------------------------
 1 files changed, 40 insertions(+), 59 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index cc70bdb..587d6bc 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2996,9 +2996,9 @@ 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.msi);
 	REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
@@ -3017,9 +3017,9 @@ 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.msi);
 
@@ -3035,9 +3035,9 @@ 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 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
@@ -3072,23 +3072,6 @@ bnx2_interrupt(int irq, void *dev_instance)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-bnx2_tx_msix(int irq, void *dev_instance)
-{
-	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);
-
-	/* 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;
-}
-
 static inline int
 bnx2_has_fast_work(struct bnx2_napi *bnapi)
 {
@@ -3119,30 +3102,6 @@ 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;
-	struct bnx2_tx_ring_info *txr = &bnapi->tx_ring;
-	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) != txr->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->last_status_idx);
-	return work_done;
-}
-
 static int bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
 {
 	struct status_block *sblk = bnapi->status_blk.msi;
@@ -3178,6 +3137,33 @@ static int bnx2_poll_work(struct bnx2 *bp, struct bnx2_napi *bnapi,
 	return work_done;
 }
 
+static int bnx2_poll_msix(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;
+
+	while (1) {
+		work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
+		if (unlikely(work_done >= budget))
+			break;
+
+		bnapi->last_status_idx = sblk->status_idx;
+		/* status idx must be read before checking for more work. */
+		rmb();
+		if (likely(!bnx2_has_fast_work(bnapi))) {
+
+			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->last_status_idx);
+			break;
+		}
+	}
+	return work_done;
+}
+
 static int bnx2_poll(struct napi_struct *napi, int budget)
 {
 	struct bnx2_napi *bnapi = container_of(napi, struct bnx2_napi, napi);
@@ -5636,7 +5622,6 @@ bnx2_restart_timer:
 static int
 bnx2_request_irq(struct bnx2 *bp)
 {
-	struct net_device *dev = bp->dev;
 	unsigned long flags;
 	struct bnx2_irq *irq;
 	int rc = 0, i;
@@ -5649,7 +5634,7 @@ bnx2_request_irq(struct bnx2 *bp)
 	for (i = 0; i < bp->irq_nvecs; i++) {
 		irq = &bp->irq_tbl[i];
 		rc = request_irq(irq->vector, irq->handler, flags, irq->name,
-				 dev);
+				 &bp->bnx2_napi[i]);
 		if (rc)
 			break;
 		irq->requested = 1;
@@ -5660,14 +5645,13 @@ bnx2_request_irq(struct bnx2 *bp)
 static void
 bnx2_free_irq(struct bnx2 *bp)
 {
-	struct net_device *dev = bp->dev;
 	struct bnx2_irq *irq;
 	int i;
 
 	for (i = 0; i < bp->irq_nvecs; i++) {
 		irq = &bp->irq_tbl[i];
 		if (irq->requested)
-			free_irq(irq->vector, dev);
+			free_irq(irq->vector, &bp->bnx2_napi[i]);
 		irq->requested = 0;
 	}
 	if (bp->flags & BNX2_FLAG_USING_MSI)
@@ -5694,10 +5678,7 @@ bnx2_enable_msix(struct bnx2 *bp)
 		msix_ent[i].vector = 0;
 
 		strcpy(bp->irq_tbl[i].name, bp->dev->name);
-		if (i == 0)
-			bp->irq_tbl[i].handler = bnx2_msi_1shot;
-		else
-			bp->irq_tbl[i].handler = bnx2_tx_msix;
+		bp->irq_tbl[i].handler = bnx2_msi_1shot;
 	}
 
 	rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC);
@@ -7567,7 +7548,7 @@ bnx2_init_napi(struct bnx2 *bp)
 		if (i == 0)
 			poll = bnx2_poll;
 		else
-			poll = bnx2_tx_poll;
+			poll = bnx2_poll_msix;
 
 		netif_napi_add(bp->dev, &bp->bnx2_napi[i].napi, poll, 64);
 		bnapi->bp = bp;
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/8] bnx2: Turn on multi rx rings.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
                   ` (3 preceding siblings ...)
  2008-06-19  0:25 ` [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:43   ` David Miller
  2008-06-19  0:25 ` [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open() Michael Chan
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

Enable multiple rx rings if MSI-X vectors are available.  We enable
up to 7 rx rings.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |   71 ++++++++++++++++++++++++++++++++++++++++-----------
 drivers/net/bnx2.h |   26 ++++++++++++++++++-
 2 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 587d6bc..9a722bf 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -4542,15 +4542,25 @@ bnx2_init_chip(struct bnx2 *bp)
 		      BNX2_HC_CONFIG_COLLECT_STATS;
 	}
 
-	if (bp->flags & BNX2_FLAG_USING_MSIX) {
-		u32 base = ((BNX2_TX_VEC - 1) * BNX2_HC_SB_CONFIG_SIZE) +
-			   BNX2_HC_SB_CONFIG_1;
-
+	if (bp->irq_nvecs > 1) {
 		REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
 		       BNX2_HC_MSIX_BIT_VECTOR_VAL);
 
+		val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
+	}
+
+	if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
+		val |= BNX2_HC_CONFIG_ONE_SHOT;
+
+	REG_WR(bp, BNX2_HC_CONFIG, val);
+
+	for (i = 1; i < bp->irq_nvecs; i++) {
+		u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
+			   BNX2_HC_SB_CONFIG_1;
+
 		REG_WR(bp, base,
 			BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
+			BNX2_HC_SB_CONFIG_1_RX_TMR_MODE |
 			BNX2_HC_SB_CONFIG_1_ONE_SHOT);
 
 		REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
@@ -4560,13 +4570,13 @@ bnx2_init_chip(struct bnx2 *bp)
 		REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
 			(bp->tx_ticks_int << 16) | bp->tx_ticks);
 
-		val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
-	}
-
-	if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
-		val |= BNX2_HC_CONFIG_ONE_SHOT;
+		REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
+		       (bp->rx_quick_cons_trip_int << 16) |
+			bp->rx_quick_cons_trip);
 
-	REG_WR(bp, BNX2_HC_CONFIG, val);
+		REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
+			(bp->rx_ticks_int << 16) | bp->rx_ticks);
+	}
 
 	/* Clear internal stats counters. */
 	REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
@@ -4737,7 +4747,7 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
 		val = (bp->rx_buf_use_size << 16) | PAGE_SIZE;
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, val);
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_RBDC_KEY,
-		       BNX2_L2CTX_RBDC_JUMBO_KEY);
+		       BNX2_L2CTX_RBDC_JUMBO_KEY - ring_num);
 
 		val = (u64) rxr->rx_pg_desc_mapping[0] >> 32;
 		bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_HI, val);
@@ -4787,6 +4797,7 @@ static void
 bnx2_init_all_rings(struct bnx2 *bp)
 {
 	int i;
+	u32 val;
 
 	bnx2_clear_ring_states(bp);
 
@@ -4798,8 +4809,33 @@ bnx2_init_all_rings(struct bnx2 *bp)
 		REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
 		       (TX_TSS_CID << 7));
 
+	REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
+	bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0);
+
 	for (i = 0; i < bp->num_rx_rings; i++)
 		bnx2_init_rx_ring(bp, i);
+
+	if (bp->num_rx_rings > 1) {
+		u32 tbl_32;
+		u8 *tbl = (u8 *) &tbl_32;
+
+		bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ,
+				BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES);
+
+		for (i = 0; i < BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES; i++) {
+			tbl[i % 4] = i % (bp->num_rx_rings - 1);
+			if ((i % 4) == 3)
+				bnx2_reg_wr_ind(bp,
+						BNX2_RXP_SCRATCH_RSS_TBL + i,
+						cpu_to_be32(tbl_32));
+		}
+
+		val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
+		      BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI;
+
+		REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
+
+	}
 }
 
 static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
@@ -5663,7 +5699,7 @@ bnx2_free_irq(struct bnx2 *bp)
 }
 
 static void
-bnx2_enable_msix(struct bnx2 *bp)
+bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
 {
 	int i, rc;
 	struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC];
@@ -5685,7 +5721,7 @@ bnx2_enable_msix(struct bnx2 *bp)
 	if (rc != 0)
 		return;
 
-	bp->irq_nvecs = BNX2_MAX_MSIX_VEC;
+	bp->irq_nvecs = msix_vecs;
 	bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI;
 	for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
 		bp->irq_tbl[i].vector = msix_ent[i].vector;
@@ -5694,13 +5730,16 @@ bnx2_enable_msix(struct bnx2 *bp)
 static void
 bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 {
+	int cpus = num_online_cpus();
+	int msix_vecs = min(cpus + 1, RX_MAX_RSS_RINGS);
+
 	bp->irq_tbl[0].handler = bnx2_interrupt;
 	strcpy(bp->irq_tbl[0].name, bp->dev->name);
 	bp->irq_nvecs = 1;
 	bp->irq_tbl[0].vector = bp->pdev->irq;
 
-	if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi)
-		bnx2_enable_msix(bp);
+	if ((bp->flags & BNX2_FLAG_MSIX_CAP) && !dis_msi && cpus > 1)
+		bnx2_enable_msix(bp, msix_vecs);
 
 	if ((bp->flags & BNX2_FLAG_MSI_CAP) && !dis_msi &&
 	    !(bp->flags & BNX2_FLAG_USING_MSIX)) {
@@ -5716,7 +5755,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
 		}
 	}
 	bp->num_tx_rings = 1;
-	bp->num_rx_rings = 1;
+	bp->num_rx_rings = bp->irq_nvecs;
 }
 
 /* Called with rtnl_lock */
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 362bef6..efa0ca9 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -4158,6 +4158,23 @@ struct l2_fhdr {
 
 
 /*
+ *  rlup_reg definition
+ *  offset: 0x2000
+ */
+#define BNX2_RLUP_RSS_CONFIG				0x0000201c
+#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_XI		 (0x3L<<0)
+#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_OFF_XI	 (0L<<0)
+#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI	 (1L<<0)
+#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_IP_ONLY_XI	 (2L<<0)
+#define BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_RES_XI	 (3L<<0)
+#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_XI		 (0x3L<<2)
+#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_OFF_XI	 (0L<<2)
+#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI	 (1L<<2)
+#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_IP_ONLY_XI	 (2L<<2)
+#define BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_RES_XI	 (3L<<2)
+
+
+/*
  *  rbuf_reg definition
  *  offset: 0x200000
  */
@@ -5528,6 +5545,9 @@ struct l2_fhdr {
 #define BNX2_HC_TX_QUICK_CONS_TRIP_OFF	(BNX2_HC_TX_QUICK_CONS_TRIP_1 -	\
 					 BNX2_HC_SB_CONFIG_1)
 #define BNX2_HC_TX_TICKS_OFF	(BNX2_HC_TX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_OFF	(BNX2_HC_RX_QUICK_CONS_TRIP_1 - \
+					 BNX2_HC_SB_CONFIG_1)
+#define BNX2_HC_RX_TICKS_OFF	(BNX2_HC_RX_TICKS_1 - BNX2_HC_SB_CONFIG_1)
 
 
 /*
@@ -5856,6 +5876,9 @@ struct l2_fhdr {
 #define BNX2_RXP_FTQ_CTL_CUR_DEPTH			 (0x3ffL<<22)
 
 #define BNX2_RXP_SCRATCH				0x000e0000
+#define BNX2_RXP_SCRATCH_RSS_TBL_SZ			 0x000e0038
+#define BNX2_RXP_SCRATCH_RSS_TBL			 0x000e003c
+#define BNX2_RXP_SCRATCH_RSS_TBL_MAX_ENTRIES		 128
 
 
 /*
@@ -6480,6 +6503,7 @@ struct l2_fhdr {
 #define TX_TSS_CID	32
 #define RX_CID		0
 #define RX_RSS_CID	4
+#define RX_MAX_RSS_RINGS	7
 
 #define MB_TX_CID_ADDR	MB_GET_CID_ADDR(TX_CID)
 #define MB_RX_CID_ADDR	MB_GET_CID_ADDR(RX_CID)
@@ -6558,7 +6582,7 @@ struct flash_spec {
 };
 
 #define BNX2_MAX_MSIX_HW_VEC	9
-#define BNX2_MAX_MSIX_VEC	2
+#define BNX2_MAX_MSIX_VEC	9
 #define BNX2_BASE_VEC		0
 #define BNX2_TX_VEC		1
 #define BNX2_TX_INT_NUM	(BNX2_TX_VEC << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT)
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open().
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
                   ` (4 preceding siblings ...)
  2008-06-19  0:25 ` [PATCH 6/8] bnx2: Turn on multi rx rings Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:44   ` David Miller
  2008-06-19  0:25 ` [PATCH 8/8] bnx2: Update driver version to 1.7.7 Michael Chan
       [not found] ` <1213835132-5698-6-git-send-email-mchan@broadcom.com>
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

All error handling in bnx2_open() can be consolidated.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |   37 ++++++++++++++-----------------------
 1 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 9a722bf..de4c85e 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -5773,29 +5773,16 @@ bnx2_open(struct net_device *dev)
 	bnx2_setup_int_mode(bp, disable_msi);
 	bnx2_napi_enable(bp);
 	rc = bnx2_alloc_mem(bp);
-	if (rc) {
-		bnx2_napi_disable(bp);
-		bnx2_free_mem(bp);
-		return rc;
-	}
+	if (rc)
+		goto open_err;
 
 	rc = bnx2_request_irq(bp);
-
-	if (rc) {
-		bnx2_napi_disable(bp);
-		bnx2_free_mem(bp);
-		return rc;
-	}
+	if (rc)
+		goto open_err;
 
 	rc = bnx2_init_nic(bp, 1);
-
-	if (rc) {
-		bnx2_napi_disable(bp);
-		bnx2_free_irq(bp);
-		bnx2_free_skbs(bp);
-		bnx2_free_mem(bp);
-		return rc;
-	}
+	if (rc)
+		goto open_err;
 
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 
@@ -5825,11 +5812,8 @@ bnx2_open(struct net_device *dev)
 				rc = bnx2_request_irq(bp);
 
 			if (rc) {
-				bnx2_napi_disable(bp);
-				bnx2_free_skbs(bp);
-				bnx2_free_mem(bp);
 				del_timer_sync(&bp->timer);
-				return rc;
+				goto open_err;
 			}
 			bnx2_enable_int(bp);
 		}
@@ -5842,6 +5826,13 @@ bnx2_open(struct net_device *dev)
 	netif_start_queue(dev);
 
 	return 0;
+
+open_err:
+	bnx2_napi_disable(bp);
+	bnx2_free_skbs(bp);
+	bnx2_free_irq(bp);
+	bnx2_free_mem(bp);
+	return rc;
 }
 
 static void
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 8/8] bnx2: Update driver version to 1.7.7.
  2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
                   ` (5 preceding siblings ...)
  2008-06-19  0:25 ` [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open() Michael Chan
@ 2008-06-19  0:25 ` Michael Chan
  2008-06-19 23:45   ` David Miller
       [not found] ` <1213835132-5698-6-git-send-email-mchan@broadcom.com>
  7 siblings, 1 reply; 16+ messages in thread
From: Michael Chan @ 2008-06-19  0:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, benli, Michael Chan

And update module description.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/bnx2.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index de4c85e..35cf45a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.7.6"
-#define DRV_MODULE_RELDATE	"May 16, 2008"
+#define DRV_MODULE_VERSION	"1.7.7"
+#define DRV_MODULE_RELDATE	"June 17, 2008"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -68,7 +68,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);
 
-- 
1.5.5.GIT




^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/8] bnx2: Put tx ring variables in a separate struct.
  2008-06-19  0:25 ` [PATCH 1/8] bnx2: Put tx ring variables in a separate struct Michael Chan
@ 2008-06-19 23:39   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:39 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:25 -0700

> In preparation for multi-ring support, tx ring variables are now put
> in a separate bnx2_tx_ring_info struct.  Multi tx ring will not be
> enabled until it is fully supported by the stack.  Only 1 tx ring
> will be used at the moment.
> 
> The functions to allocate/free tx memory and to initialize tx rings
> are now modified to handle multiple rings.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/8] bnx2: Put rx ring variables in a separate struct.
  2008-06-19  0:25 ` [PATCH 2/8] bnx2: Put rx " Michael Chan
@ 2008-06-19 23:39   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:39 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:26 -0700

> In preparation for multi-ring support, rx ring variables are now put
> in a separate bnx2_rx_ring_info struct.  With MSI-X, we can support
> multiple rx rings.
> 
> The functions to allocate/free rx memory and to initialize rx rings
> are now modified to handle multiple rings.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/8] bnx2: Optimize fast-path tx and rx work.
  2008-06-19  0:25 ` [PATCH 3/8] bnx2: Optimize fast-path tx and rx work Michael Chan
@ 2008-06-19 23:41   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:41 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:27 -0700

> Add hw_tx_cons_ptr and hw_rx_cons_ptr to speed up the retreival of
> the tx and rx consumer index, since the MSI-X and default status
> blocks have different structures.
> 
> Combine status_blk and status_blk_msix into a union.  We'll only use
> one type of status block for each vector.
> 
> Separate the code to detect more rx and tx work from the code to
> detect link related work.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

This adds a new warning:

drivers/net/bnx2.c: In function ‘bnx2_poll_link’:
drivers/net/bnx2.c:3164: warning: no return statement in function returning non-void

So I changed bnx2_poll_link() to return 'void' when
checking this in.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors.
  2008-06-19  0:25 ` [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors Michael Chan
@ 2008-06-19 23:42   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:42 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:28 -0700

> Use the same MSI-X handler to schedule NAPI.  Change the dev_instance
> void pointer to the bnx2_napi struct instead so we can have the proper
> context for each MSI-X vector.
> 
> Add a new bnx2_poll_msix() that is optimized for handling MSI-X
> NAPI polling of rx/tx work only.  Remove the old bnx2_tx_poll() that
> is no longer needed.  Each MSI-X vector handles 1 tx and 1 rx ring.
> The first vector handles link events as well.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/8] bnx2: Update firmware to support multi rx rings.
       [not found] ` <1213835132-5698-6-git-send-email-mchan@broadcom.com>
@ 2008-06-19 23:42   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:42 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:29 -0700

> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 6/8] bnx2: Turn on multi rx rings.
  2008-06-19  0:25 ` [PATCH 6/8] bnx2: Turn on multi rx rings Michael Chan
@ 2008-06-19 23:43   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:43 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:30 -0700

> Enable multiple rx rings if MSI-X vectors are available.  We enable
> up to 7 rx rings.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

I hope that on the TX side you'll use some power-of-2
number of TX rings as this will make the SW flow hash
function less expensive to compute.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open().
  2008-06-19  0:25 ` [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open() Michael Chan
@ 2008-06-19 23:44   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:44 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:31 -0700

> All error handling in bnx2_open() can be consolidated.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Applied to net-next-2.6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 8/8] bnx2: Update driver version to 1.7.7.
  2008-06-19  0:25 ` [PATCH 8/8] bnx2: Update driver version to 1.7.7 Michael Chan
@ 2008-06-19 23:45   ` David Miller
  0 siblings, 0 replies; 16+ messages in thread
From: David Miller @ 2008-06-19 23:45 UTC (permalink / raw)
  To: mchan; +Cc: netdev, benli

From: "Michael Chan" <mchan@broadcom.com>
Date: Wed, 18 Jun 2008 17:25:32 -0700

> And update module description.
> 
> Signed-off-by: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Benjamin Li <benli@broadcom.com>

Also applied to net-next-2.6

Thanks a lot!

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2008-06-19 23:45 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-19  0:25 [PATCH 0/8] bnx2: Enable multi rx rings Michael Chan
2008-06-19  0:25 ` [PATCH 1/8] bnx2: Put tx ring variables in a separate struct Michael Chan
2008-06-19 23:39   ` David Miller
2008-06-19  0:25 ` [PATCH 2/8] bnx2: Put rx " Michael Chan
2008-06-19 23:39   ` David Miller
2008-06-19  0:25 ` [PATCH 3/8] bnx2: Optimize fast-path tx and rx work Michael Chan
2008-06-19 23:41   ` David Miller
2008-06-19  0:25 ` [PATCH 4/8] bnx2: Use one handler for all MSI-X vectors Michael Chan
2008-06-19 23:42   ` David Miller
2008-06-19  0:25 ` [PATCH 6/8] bnx2: Turn on multi rx rings Michael Chan
2008-06-19 23:43   ` David Miller
2008-06-19  0:25 ` [PATCH 7/8] bnx2: Cleanup error handling in bnx2_open() Michael Chan
2008-06-19 23:44   ` David Miller
2008-06-19  0:25 ` [PATCH 8/8] bnx2: Update driver version to 1.7.7 Michael Chan
2008-06-19 23:45   ` David Miller
     [not found] ` <1213835132-5698-6-git-send-email-mchan@broadcom.com>
2008-06-19 23:42   ` [PATCH 5/8] bnx2: Update firmware to support multi rx rings David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).