Netdev List
 help / color / mirror / Atom feed
* [PATCH 09/20] tg3: Create tg3_poll_msix() for non-zero MSIX vecs
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch gives all non-zero MSIX vectors their own NAPI handler.  This
will make NAPI handling for those vectors slightly more efficient.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 1c1cf68..5e17abb 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4706,18 +4706,17 @@ next_pkt_nopost:
 	return received;
 }
 
-static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
+static void tg3_poll_link(struct tg3 *tp)
 {
-	struct tg3 *tp = tnapi->tp;
-	struct tg3_hw_status *sblk = tnapi->hw_status;
-
 	/* handle link change and other phy events */
 	if (!(tp->tg3_flags &
 	      (TG3_FLAG_USE_LINKCHG_REG |
 	       TG3_FLAG_POLL_SERDES))) {
+		struct tg3_hw_status *sblk = tp->napi[0].hw_status;
+
 		if (sblk->status & SD_STATUS_LINK_CHG) {
 			sblk->status = SD_STATUS_UPDATED |
-				(sblk->status & ~SD_STATUS_LINK_CHG);
+				       (sblk->status & ~SD_STATUS_LINK_CHG);
 			spin_lock(&tp->lock);
 			if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
 				tw32_f(MAC_STATUS,
@@ -4731,6 +4730,11 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 			spin_unlock(&tp->lock);
 		}
 	}
+}
+
+static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
+{
+	struct tg3 *tp = tnapi->tp;
 
 	/* run TX completion thread */
 	if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) {
@@ -4749,6 +4753,50 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 	return work_done;
 }
 
+static int tg3_poll_msix(struct napi_struct *napi, int budget)
+{
+	struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi);
+	struct tg3 *tp = tnapi->tp;
+	int work_done = 0;
+	struct tg3_hw_status *sblk = tnapi->hw_status;
+
+	while (1) {
+		work_done = tg3_poll_work(tnapi, work_done, budget);
+
+		if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
+			goto tx_recovery;
+
+		if (unlikely(work_done >= budget))
+			break;
+
+		/* tp->last_tag is used in tg3_restart_ints() below
+		 * to tell the hw how much work has been processed,
+		 * so we must read it before checking for more work.
+		 */
+		tnapi->last_tag = sblk->status_tag;
+		tnapi->last_irq_tag = tnapi->last_tag;
+		rmb();
+
+		/* check for RX/TX work to do */
+		if (sblk->idx[0].tx_consumer == tnapi->tx_cons &&
+		    *(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr) {
+			napi_complete(napi);
+			/* Reenable interrupts. */
+			tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24);
+			mmiowb();
+			break;
+		}
+	}
+
+	return work_done;
+
+tx_recovery:
+	/* work_done is guaranteed to be less than budget. */
+	napi_complete(napi);
+	schedule_work(&tp->reset_task);
+	return work_done;
+}
+
 static int tg3_poll(struct napi_struct *napi, int budget)
 {
 	struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi);
@@ -4757,6 +4805,8 @@ static int tg3_poll(struct napi_struct *napi, int budget)
 	struct tg3_hw_status *sblk = tnapi->hw_status;
 
 	while (1) {
+		tg3_poll_link(tp);
+
 		work_done = tg3_poll_work(tnapi, work_done, budget);
 
 		if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
@@ -14057,10 +14107,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		tnapi->consmbox = rcvmbx;
 		tnapi->prodmbox = sndmbx;
 
-		if (i)
+		if (i) {
 			tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
-		else
+			netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
+		} else {
 			tnapi->coal_now = HOSTCC_MODE_NOW;
+			netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
+		}
 
 		if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
 			break;
@@ -14083,7 +14136,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 			sndmbx += 0xc;
 	}
 
-	netif_napi_add(dev, &tp->napi[0].napi, tg3_poll, 64);
 	dev->ethtool_ops = &tg3_ethtool_ops;
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
 	dev->irq = pdev->irq;
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 11/20] tg3: Make tg3_alloc_rx_skb() a dst-only operation
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch removes the source index parameter of tg3_alloc_rx_skb().  A
later patch will make it possible for the source and destination
producer rings to be different.  This patch opts to make
tg3_alloc_rx_skb() a destination-only implementation and move the code
sensitive to the difference elsewhere.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f0360f8..ef64080 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4409,7 +4409,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
  * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
  */
 static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
-			    int src_idx, u32 dest_idx_unmasked)
+			    u32 dest_idx_unmasked)
 {
 	struct tg3 *tp = tnapi->tp;
 	struct tg3_rx_buffer_desc *desc;
@@ -4425,8 +4425,6 @@ static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
 		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
 		desc = &tpr->rx_std[dest_idx];
 		map = &tpr->rx_std_buffers[dest_idx];
-		if (src_idx >= 0)
-			src_map = &tpr->rx_std_buffers[src_idx];
 		skb_size = tp->rx_pkt_map_sz;
 		break;
 
@@ -4434,8 +4432,6 @@ static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
 		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
 		desc = &tpr->rx_jmb[dest_idx].std;
 		map = &tpr->rx_jmb_buffers[dest_idx];
-		if (src_idx >= 0)
-			src_map = &tpr->rx_jmb_buffers[src_idx];
 		skb_size = TG3_RX_JMB_MAP_SZ;
 		break;
 
@@ -4465,9 +4461,6 @@ static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
 	map->skb = skb;
 	pci_unmap_addr_set(map, mapping, mapping);
 
-	if (src_map != NULL)
-		src_map->skb = NULL;
-
 	desc->addr_hi = ((u64)mapping >> 32);
 	desc->addr_lo = ((u64)mapping & 0xffffffff);
 
@@ -4559,6 +4552,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 	work_mask = 0;
 	received = 0;
 	while (sw_idx != hw_idx && budget > 0) {
+		struct ring_info *ri;
 		struct tg3_rx_buffer_desc *desc = &tnapi->rx_rcb[sw_idx];
 		unsigned int len;
 		struct sk_buff *skb;
@@ -4568,13 +4562,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
 		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
 		if (opaque_key == RXD_OPAQUE_RING_STD) {
-			struct ring_info *ri = &tpr->rx_std_buffers[desc_idx];
+			ri = &tpr->rx_std_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &tpr->rx_std_ptr;
 			rx_std_posted++;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
-			struct ring_info *ri = &tpr->rx_jmb_buffers[desc_idx];
+			ri = &tpr->rx_jmb_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &tpr->rx_jmb_ptr;
@@ -4607,10 +4601,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 			int skb_size;
 
 			skb_size = tg3_alloc_rx_skb(tnapi, opaque_key,
-						    desc_idx, *post_ptr);
+						    *post_ptr);
 			if (skb_size < 0)
 				goto drop_it;
 
+			ri->skb = NULL;
+
 			pci_unmap_single(tp->pdev, dma_addr, skb_size,
 					 PCI_DMA_FROMDEVICE);
 
@@ -5774,7 +5770,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 
 	/* Now allocate fresh SKBs for each rx ring. */
 	for (i = 0; i < tp->rx_pending; i++) {
-		if (tg3_alloc_rx_skb(tnapi, RXD_OPAQUE_RING_STD, -1, i) < 0) {
+		if (tg3_alloc_rx_skb(tnapi, RXD_OPAQUE_RING_STD, i) < 0) {
 			printk(KERN_WARNING PFX
 			       "%s: Using a smaller RX standard ring, "
 			       "only %d out of %d buffers were allocated "
@@ -5806,7 +5802,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 
 		for (i = 0; i < tp->rx_jumbo_pending; i++) {
 			if (tg3_alloc_rx_skb(tnapi, RXD_OPAQUE_RING_JUMBO,
-					     -1, i) < 0) {
+					     i) < 0) {
 				printk(KERN_WARNING PFX
 				       "%s: Using a smaller RX jumbo ring, "
 				       "only %d out of %d buffers were "
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 06/20] tg3: Add new HW_TSO_3 flag for 5717
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

The 5717 sets up TSO slightly differently in the transmit path.  It
looks like this method will be the new way of doing things.  This patch
defines a flag to indicate this.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   41 +++++++++++++++++++++++------------------
 drivers/net/tg3.h |    5 ++++-
 2 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 29276e6..6831289 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5206,7 +5206,7 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
 }
 
 /* hard_start_xmit for devices that don't have any bugs and
- * support TG3_FLG2_HW_TSO_2 only.
+ * support TG3_FLG2_HW_TSO_2 and TG3_FLG2_HW_TSO_3 only.
  */
 static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev)
@@ -5265,7 +5265,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 			hdrlen = ip_tcp_len + tcp_opt_len;
 		}
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
 			mss |= (hdrlen & 0xc) << 12;
 			if (hdrlen & 0x10)
 				base_flags |= 0x00000010;
@@ -7523,7 +7523,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+	if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 		rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
 
@@ -9513,15 +9514,16 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
 		return 0;
 	}
 	if ((dev->features & NETIF_F_IPV6_CSUM) &&
-	    (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)) {
+	    ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
+	     (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3))) {
 		if (value) {
 			dev->features |= NETIF_F_TSO6;
-			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+			if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
+			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
 			    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
 			     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
 			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 				dev->features |= NETIF_F_TSO_ECN;
 		} else
 			dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
@@ -12670,8 +12672,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	}
 
 	/* Determine TSO capabilities */
-	if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+		tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3;
+	else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
+		 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
 	else if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
 		tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
@@ -14136,22 +14140,23 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	 * Firmware TSO on older chips gives lower performance, so it
 	 * is off by default, but can be enabled using ethtool.
 	 */
-	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
-		if (dev->features & NETIF_F_IP_CSUM)
-			dev->features |= NETIF_F_TSO;
-		if ((dev->features & NETIF_F_IPV6_CSUM) &&
-		    (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2))
+	if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) &&
+	    (dev->features & NETIF_F_IP_CSUM))
+		dev->features |= NETIF_F_TSO;
+
+	if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
+	    (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3)) {
+		if (dev->features & NETIF_F_IPV6_CSUM)
 			dev->features |= NETIF_F_TSO6;
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+		if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
 		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
 		     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
 			GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 			dev->features |= NETIF_F_TSO_ECN;
 	}
 
-
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&
 	    !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
 	    !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 590a692..5fe5760 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2753,6 +2753,7 @@ struct tg3 {
 #define TG3_FLG2_SERDES_PREEMPHASIS	0x00020000
 #define TG3_FLG2_5705_PLUS		0x00040000
 #define TG3_FLG2_5750_PLUS		0x00080000
+#define TG3_FLG2_HW_TSO_3		0x00100000
 #define TG3_FLG2_USING_MSI		0x00200000
 #define TG3_FLG2_USING_MSIX		0x00400000
 #define TG3_FLG2_USING_MSI_OR_MSIX	(TG3_FLG2_USING_MSI | \
@@ -2764,7 +2765,9 @@ struct tg3 {
 #define TG3_FLG2_ICH_WORKAROUND		0x02000000
 #define TG3_FLG2_5780_CLASS		0x04000000
 #define TG3_FLG2_HW_TSO_2		0x08000000
-#define TG3_FLG2_HW_TSO			(TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
+#define TG3_FLG2_HW_TSO			(TG3_FLG2_HW_TSO_1 | \
+					 TG3_FLG2_HW_TSO_2 | \
+					 TG3_FLG2_HW_TSO_3)
 #define TG3_FLG2_1SHOT_MSI		0x10000000
 #define TG3_FLG2_PHY_JITTER_BUG		0x20000000
 #define TG3_FLG2_NO_FWARE_REPORTED	0x40000000
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 15/20] tg3: Consider rx_std_prod_idx a hw mailbox
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch changes how the code uses the rx_std_prod_idx member.  In the
following patch, the code will be changed so that it will act just like
a hardware mailbox.  This patch prepares the code so that memory barriers
can be more easily inserted.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 59a715a..beda9bf 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4537,6 +4537,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 {
 	struct tg3 *tp = tnapi->tp;
 	u32 work_mask, rx_std_posted = 0;
+	u32 std_prod_idx, jmb_prod_idx;
 	u32 sw_idx = tnapi->rx_rcb_ptr;
 	u16 hw_idx;
 	int received;
@@ -4550,6 +4551,8 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 	rmb();
 	work_mask = 0;
 	received = 0;
+	std_prod_idx = tpr->rx_std_prod_idx;
+	jmb_prod_idx = tpr->rx_jmb_prod_idx;
 	while (sw_idx != hw_idx && budget > 0) {
 		struct ring_info *ri;
 		struct tg3_rx_buffer_desc *desc = &tnapi->rx_rcb[sw_idx];
@@ -4564,13 +4567,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 			ri = &tpr->rx_std_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
-			post_ptr = &tpr->rx_std_prod_idx;
+			post_ptr = &std_prod_idx;
 			rx_std_posted++;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
 			ri = &tpr->rx_jmb_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
-			post_ptr = &tpr->rx_jmb_prod_idx;
+			post_ptr = &jmb_prod_idx;
 		} else
 			goto next_pkt_nopost;
 
@@ -4687,14 +4690,14 @@ next_pkt_nopost:
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
-		sw_idx = tpr->rx_std_prod_idx % TG3_RX_RING_SIZE;
+		tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
 		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
-			     sw_idx);
+			     tpr->rx_std_prod_idx);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
-		sw_idx = tpr->rx_jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
+		tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
 		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
-			     sw_idx);
+			     tpr->rx_jmb_prod_idx);
 	}
 	mmiowb();
 
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 17/20] tg3: Create aliases for rx producer mailbox regs
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson, Michael Chan

The rx producer mailbox registers are used in several spots in the code.
The addition of TG3_64BIT_REG_LOW makes register references
uncomfortably long.  This patch creates an alias for the standard and
jumbo ring producer index registers to make the code cleaner.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   18 ++++++------------
 drivers/net/tg3.h |    4 ++++
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 168a7ca..05fd42f 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -402,7 +402,7 @@ static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
 				       TG3_64BIT_REG_LOW, val);
 		return;
 	}
-	if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) {
+	if (off == TG3_RX_STD_PROD_IDX_REG) {
 		pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
 				       TG3_64BIT_REG_LOW, val);
 		return;
@@ -4684,9 +4684,7 @@ next_pkt:
 
 		if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
 			u32 idx = *post_ptr % TG3_RX_RING_SIZE;
-
-			tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX +
-				     TG3_64BIT_REG_LOW, idx);
+			tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx);
 			work_mask &= ~RXD_OPAQUE_RING_STD;
 			rx_std_posted = 0;
 		}
@@ -4708,13 +4706,11 @@ next_pkt_nopost:
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
 		tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
-		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
-			     tpr->rx_std_prod_idx);
+		tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
 		tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
-		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
-			     tpr->rx_jmb_prod_idx);
+		tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx);
 	}
 	mmiowb();
 
@@ -7526,13 +7522,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
 
 	tpr->rx_std_prod_idx = tp->rx_pending;
-	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
-		     tpr->rx_std_prod_idx);
+	tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx);
 
 	tpr->rx_jmb_prod_idx = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ?
 			  tp->rx_jumbo_pending : 0;
-	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
-		     tpr->rx_jmb_prod_idx);
+	tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
 		tw32(STD_REPLENISH_LWM, 32);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 715df2b..bbfbc5e 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -242,7 +242,11 @@
 #define MAILBOX_GENERAL_7		0x00000258 /* 64-bit */
 #define MAILBOX_RELOAD_STAT		0x00000260 /* 64-bit */
 #define MAILBOX_RCV_STD_PROD_IDX	0x00000268 /* 64-bit */
+#define TG3_RX_STD_PROD_IDX_REG		(MAILBOX_RCV_STD_PROD_IDX + \
+					 TG3_64BIT_REG_LOW)
 #define MAILBOX_RCV_JUMBO_PROD_IDX	0x00000270 /* 64-bit */
+#define TG3_RX_JMB_PROD_IDX_REG		(MAILBOX_RCV_JUMBO_PROD_IDX + \
+					 TG3_64BIT_REG_LOW)
 #define MAILBOX_RCV_MINI_PROD_IDX	0x00000278 /* 64-bit */
 #define MAILBOX_RCVRET_CON_IDX_0	0x00000280 /* 64-bit */
 #define MAILBOX_RCVRET_CON_IDX_1	0x00000288 /* 64-bit */
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 18/20] tg3: Add rx prod ring consolidation
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson, Michael Chan

This patch adds code to funnel each MSI-X vector's rx packet buffers
into a single set of producer rings which will then be submitted to the
hardware.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |  171 +++++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/net/tg3.h |    3 +
 2 files changed, 164 insertions(+), 10 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 05fd42f..3ff2d40 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4558,7 +4558,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 	u32 sw_idx = tnapi->rx_rcb_ptr;
 	u16 hw_idx;
 	int received;
-	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+	struct tg3_rx_prodring_set *tpr = tnapi->prodring;
 
 	hw_idx = *(tnapi->rx_rcb_prod_idx);
 	/*
@@ -4581,13 +4581,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
 		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
 		if (opaque_key == RXD_OPAQUE_RING_STD) {
-			ri = &tpr->rx_std_buffers[desc_idx];
+			ri = &tp->prodring[0].rx_std_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &std_prod_idx;
 			rx_std_posted++;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
-			ri = &tpr->rx_jmb_buffers[desc_idx];
+			ri = &tp->prodring[0].rx_jmb_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
 			post_ptr = &jmb_prod_idx;
@@ -4704,15 +4704,30 @@ next_pkt_nopost:
 	tw32_rx_mbox(tnapi->consmbox, sw_idx);
 
 	/* Refill RX ring(s). */
-	if (work_mask & RXD_OPAQUE_RING_STD) {
+	if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) || tnapi == &tp->napi[1]) {
+		if (work_mask & RXD_OPAQUE_RING_STD) {
+			tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+			tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
+				     tpr->rx_std_prod_idx);
+		}
+		if (work_mask & RXD_OPAQUE_RING_JUMBO) {
+			tpr->rx_jmb_prod_idx = jmb_prod_idx %
+					       TG3_RX_JUMBO_RING_SIZE;
+			tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG,
+				     tpr->rx_jmb_prod_idx);
+		}
+		mmiowb();
+	} else if (work_mask) {
+		/* rx_std_buffers[] and rx_jmb_buffers[] entries must be
+		 * updated before the producer indices can be updated.
+		 */
+		smp_wmb();
+
 		tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
-		tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, tpr->rx_std_prod_idx);
-	}
-	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
 		tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
-		tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx);
+
+		napi_schedule(&tp->napi[1].napi);
 	}
-	mmiowb();
 
 	return received;
 }
@@ -4743,6 +4758,93 @@ static void tg3_poll_link(struct tg3 *tp)
 	}
 }
 
+static void tg3_rx_prodring_xfer(struct tg3 *tp,
+				 struct tg3_rx_prodring_set *dpr,
+				 struct tg3_rx_prodring_set *spr)
+{
+	u32 si, di, cpycnt, src_prod_idx;
+	int i;
+
+	while (1) {
+		src_prod_idx = spr->rx_std_prod_idx;
+
+		/* Make sure updates to the rx_std_buffers[] entries and the
+		 * standard producer index are seen in the correct order.
+		 */
+		smp_rmb();
+
+		if (spr->rx_std_cons_idx == src_prod_idx)
+			break;
+
+		if (spr->rx_std_cons_idx < src_prod_idx)
+			cpycnt = src_prod_idx - spr->rx_std_cons_idx;
+		else
+			cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx;
+
+		cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx);
+
+		si = spr->rx_std_cons_idx;
+		di = dpr->rx_std_prod_idx;
+
+		memcpy(&dpr->rx_std_buffers[di],
+		       &spr->rx_std_buffers[si],
+		       cpycnt * sizeof(struct ring_info));
+
+		for (i = 0; i < cpycnt; i++, di++, si++) {
+			struct tg3_rx_buffer_desc *sbd, *dbd;
+			sbd = &spr->rx_std[si];
+			dbd = &dpr->rx_std[di];
+			dbd->addr_hi = sbd->addr_hi;
+			dbd->addr_lo = sbd->addr_lo;
+		}
+
+		spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) %
+				       TG3_RX_RING_SIZE;
+		dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) %
+				       TG3_RX_RING_SIZE;
+	}
+
+	while (1) {
+		src_prod_idx = spr->rx_jmb_prod_idx;
+
+		/* Make sure updates to the rx_jmb_buffers[] entries and
+		 * the jumbo producer index are seen in the correct order.
+		 */
+		smp_rmb();
+
+		if (spr->rx_jmb_cons_idx == src_prod_idx)
+			break;
+
+		if (spr->rx_jmb_cons_idx < src_prod_idx)
+			cpycnt = src_prod_idx - spr->rx_jmb_cons_idx;
+		else
+			cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx;
+
+		cpycnt = min(cpycnt,
+			     TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx);
+
+		si = spr->rx_jmb_cons_idx;
+		di = dpr->rx_jmb_prod_idx;
+
+		memcpy(&dpr->rx_jmb_buffers[di],
+		       &spr->rx_jmb_buffers[si],
+		       cpycnt * sizeof(struct ring_info));
+
+		for (i = 0; i < cpycnt; i++, di++, si++) {
+			struct tg3_rx_buffer_desc *sbd, *dbd;
+			sbd = &spr->rx_jmb[si].std;
+			dbd = &dpr->rx_jmb[di].std;
+			dbd->addr_hi = sbd->addr_hi;
+			dbd->addr_lo = sbd->addr_lo;
+		}
+
+		spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) %
+				       TG3_RX_JUMBO_RING_SIZE;
+		dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) %
+				       TG3_RX_JUMBO_RING_SIZE;
+	}
+}
+
 static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 {
 	struct tg3 *tp = tnapi->tp;
@@ -4761,6 +4863,30 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 	if (*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
 		work_done += tg3_rx(tnapi, budget - work_done);
 
+	if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) {
+		int i;
+		u32 std_prod_idx = tp->prodring[0].rx_std_prod_idx;
+		u32 jmb_prod_idx = tp->prodring[0].rx_jmb_prod_idx;
+
+		for (i = 2; i < tp->irq_cnt; i++)
+			tg3_rx_prodring_xfer(tp, tnapi->prodring,
+					     tp->napi[i].prodring);
+
+		wmb();
+
+		if (std_prod_idx != tp->prodring[0].rx_std_prod_idx) {
+			u32 mbox = TG3_RX_STD_PROD_IDX_REG;
+			tw32_rx_mbox(mbox, tp->prodring[0].rx_std_prod_idx);
+		}
+
+		if (jmb_prod_idx != tp->prodring[0].rx_jmb_prod_idx) {
+			u32 mbox = TG3_RX_JMB_PROD_IDX_REG;
+			tw32_rx_mbox(mbox, tp->prodring[0].rx_jmb_prod_idx);
+		}
+
+		mmiowb();
+	}
+
 	return work_done;
 }
 
@@ -5715,8 +5841,23 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
 {
 	int i;
 
-	if (tpr != &tp->prodring[0])
+	if (tpr != &tp->prodring[0]) {
+		for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx;
+		     i = (i + 1) % TG3_RX_RING_SIZE)
+			tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
+					tp->rx_pkt_map_sz);
+
+		if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
+			for (i = tpr->rx_jmb_cons_idx;
+			     i != tpr->rx_jmb_prod_idx;
+			     i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) {
+				tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
+						TG3_RX_JMB_MAP_SZ);
+			}
+		}
+
 		return;
+	}
 
 	for (i = 0; i < TG3_RX_RING_SIZE; i++)
 		tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
@@ -5741,6 +5882,11 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 {
 	u32 i, rx_pkt_dma_sz;
 
+	tpr->rx_std_cons_idx = 0;
+	tpr->rx_std_prod_idx = 0;
+	tpr->rx_jmb_cons_idx = 0;
+	tpr->rx_jmb_prod_idx = 0;
+
 	if (tpr != &tp->prodring[0]) {
 		memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
 		if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
@@ -6062,6 +6208,11 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 			break;
 		}
 
+		if (tp->irq_cnt == 1)
+			tnapi->prodring = &tp->prodring[0];
+		else if (i)
+			tnapi->prodring = &tp->prodring[i - 1];
+
 		/*
 		 * If multivector RSS is enabled, vector 0 does not handle
 		 * rx or tx interrupts.  Don't allocate any resources for it.
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index bbfbc5e..6be46ab 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2575,7 +2575,9 @@ struct tg3_ethtool_stats {
 
 struct tg3_rx_prodring_set {
 	u32				rx_std_prod_idx;
+	u32				rx_std_cons_idx;
 	u32				rx_jmb_prod_idx;
+	u32				rx_jmb_cons_idx;
 	struct tg3_rx_buffer_desc	*rx_std;
 	struct tg3_ext_rx_buffer_desc	*rx_jmb;
 	struct ring_info		*rx_std_buffers;
@@ -2603,6 +2605,7 @@ struct tg3_napi {
 	u32				consmbox;
 	u32				rx_rcb_ptr;
 	u16				*rx_rcb_prod_idx;
+	struct tg3_rx_prodring_set	*prodring;
 
 	struct tg3_rx_buffer_desc	*rx_rcb;
 	struct tg3_tx_buffer_desc	*tx_ring;
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 13/20] tg3: tg3_alloc_rx_skb(tnapi => tp)
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch converts the tnapi argument of tg3_alloc_rx_skb() to tp.  The
level of indirection is unnecessary.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   11 ++++-------
 1 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9251bb5..00e7e14 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4408,11 +4408,9 @@ static void tg3_tx(struct tg3_napi *tnapi)
  * buffers the cpu only reads the last cacheline of the RX descriptor
  * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
  */
-static int tg3_alloc_rx_skb(struct tg3_napi *tnapi,
-			    struct tg3_rx_prodring_set *tpr,
+static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
 			    u32 opaque_key, u32 dest_idx_unmasked)
 {
-	struct tg3 *tp = tnapi->tp;
 	struct tg3_rx_buffer_desc *desc;
 	struct ring_info *map, *src_map;
 	struct sk_buff *skb;
@@ -4601,7 +4599,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		) {
 			int skb_size;
 
-			skb_size = tg3_alloc_rx_skb(tnapi, tpr, opaque_key,
+			skb_size = tg3_alloc_rx_skb(tp, tpr, opaque_key,
 						    *post_ptr);
 			if (skb_size < 0)
 				goto drop_it;
@@ -5744,7 +5742,6 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 				 struct tg3_rx_prodring_set *tpr)
 {
 	u32 i, rx_pkt_dma_sz;
-	struct tg3_napi *tnapi = &tp->napi[0];
 
 	/* Zero out all descriptors. */
 	memset(tpr->rx_std, 0, TG3_RX_RING_BYTES);
@@ -5771,7 +5768,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 
 	/* Now allocate fresh SKBs for each rx ring. */
 	for (i = 0; i < tp->rx_pending; i++) {
-		if (tg3_alloc_rx_skb(tnapi, tpr, RXD_OPAQUE_RING_STD, i) < 0) {
+		if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) {
 			printk(KERN_WARNING PFX
 			       "%s: Using a smaller RX standard ring, "
 			       "only %d out of %d buffers were allocated "
@@ -5802,7 +5799,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 		}
 
 		for (i = 0; i < tp->rx_jumbo_pending; i++) {
-			if (tg3_alloc_rx_skb(tnapi, tpr, RXD_OPAQUE_RING_JUMBO,
+			if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO,
 					     i) < 0) {
 				printk(KERN_WARNING PFX
 				       "%s: Using a smaller RX jumbo ring, "
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 10/20] tg3: Move napi_add calls below tg3_get_invariants
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

tg3_get_invariants(), among other things, discovers whether or not
the device is MSI-X capable and how many interrupts it supports.
This discovery needs to happen before registering NAPI instances with
netdev.  This patch moves the code block that calls napi_add later in
tg3_init_one() so that tg3_get_invariants() has a chance to run first.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   94 ++++++++++++++++++++++++++--------------------------
 1 files changed, 47 insertions(+), 47 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5e17abb..f0360f8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -14089,53 +14089,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
-	intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
-	rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
-	sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
-	for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
-		struct tg3_napi *tnapi = &tp->napi[i];
-
-		tnapi->tp = tp;
-		tnapi->tx_pending = TG3_DEF_TX_RING_PENDING;
-
-		tnapi->int_mbox = intmbx;
-		if (i < 4)
-			intmbx += 0x8;
-		else
-			intmbx += 0x4;
-
-		tnapi->consmbox = rcvmbx;
-		tnapi->prodmbox = sndmbx;
-
-		if (i) {
-			tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
-			netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
-		} else {
-			tnapi->coal_now = HOSTCC_MODE_NOW;
-			netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
-		}
-
-		if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
-			break;
-
-		/*
-		 * If we support MSIX, we'll be using RSS.  If we're using
-		 * RSS, the first vector only handles link interrupts and the
-		 * remaining vectors handle rx and tx interrupts.  Reuse the
-		 * mailbox values for the next iteration.  The values we setup
-		 * above are still useful for the single vectored mode.
-		 */
-		if (!i)
-			continue;
-
-		rcvmbx += 0x8;
-
-		if (sndmbx & 0x4)
-			sndmbx -= 0x4;
-		else
-			sndmbx += 0xc;
-	}
-
 	dev->ethtool_ops = &tg3_ethtool_ops;
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
 	dev->irq = pdev->irq;
@@ -14278,6 +14231,53 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
 	tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
 
+	intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+	rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+	sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+	for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+
+		tnapi->tp = tp;
+		tnapi->tx_pending = TG3_DEF_TX_RING_PENDING;
+
+		tnapi->int_mbox = intmbx;
+		if (i < 4)
+			intmbx += 0x8;
+		else
+			intmbx += 0x4;
+
+		tnapi->consmbox = rcvmbx;
+		tnapi->prodmbox = sndmbx;
+
+		if (i) {
+			tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
+			netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
+		} else {
+			tnapi->coal_now = HOSTCC_MODE_NOW;
+			netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
+		}
+
+		if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
+			break;
+
+		/*
+		 * If we support MSIX, we'll be using RSS.  If we're using
+		 * RSS, the first vector only handles link interrupts and the
+		 * remaining vectors handle rx and tx interrupts.  Reuse the
+		 * mailbox values for the next iteration.  The values we setup
+		 * above are still useful for the single vectored mode.
+		 */
+		if (!i)
+			continue;
+
+		rcvmbx += 0x8;
+
+		if (sndmbx & 0x4)
+			sndmbx -= 0x4;
+		else
+			sndmbx += 0xc;
+	}
+
 	tg3_init_coal(tp);
 
 	pci_set_drvdata(pdev, dev);
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 12/20] tg3: Add prodring parameter to tg3_alloc_rx_skb()
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch changes the tg3_alloc_rx_skb() implementation to accept the
destination producer ring set pointer as a parameter rather than
assuming the source and destination producer rings are the same.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   41 +++++++++++++++++++++--------------------
 1 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ef64080..9251bb5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4408,8 +4408,9 @@ static void tg3_tx(struct tg3_napi *tnapi)
  * buffers the cpu only reads the last cacheline of the RX descriptor
  * (to fetch the error flags, vlan tag, checksum, and opaque cookie).
  */
-static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
-			    u32 dest_idx_unmasked)
+static int tg3_alloc_rx_skb(struct tg3_napi *tnapi,
+			    struct tg3_rx_prodring_set *tpr,
+			    u32 opaque_key, u32 dest_idx_unmasked)
 {
 	struct tg3 *tp = tnapi->tp;
 	struct tg3_rx_buffer_desc *desc;
@@ -4417,7 +4418,6 @@ static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
 	struct sk_buff *skb;
 	dma_addr_t mapping;
 	int skb_size, dest_idx;
-	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
 
 	src_map = NULL;
 	switch (opaque_key) {
@@ -4471,30 +4471,32 @@ static int tg3_alloc_rx_skb(struct tg3_napi *tnapi, u32 opaque_key,
  * members of the RX descriptor are invariant.  See notes above
  * tg3_alloc_rx_skb for full details.
  */
-static void tg3_recycle_rx(struct tg3_napi *tnapi, u32 opaque_key,
-			   int src_idx, u32 dest_idx_unmasked)
+static void tg3_recycle_rx(struct tg3_napi *tnapi,
+			   struct tg3_rx_prodring_set *dpr,
+			   u32 opaque_key, int src_idx,
+			   u32 dest_idx_unmasked)
 {
 	struct tg3 *tp = tnapi->tp;
 	struct tg3_rx_buffer_desc *src_desc, *dest_desc;
 	struct ring_info *src_map, *dest_map;
 	int dest_idx;
-	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
+	struct tg3_rx_prodring_set *spr = &tp->prodring[0];
 
 	switch (opaque_key) {
 	case RXD_OPAQUE_RING_STD:
 		dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
-		dest_desc = &tpr->rx_std[dest_idx];
-		dest_map = &tpr->rx_std_buffers[dest_idx];
-		src_desc = &tpr->rx_std[src_idx];
-		src_map = &tpr->rx_std_buffers[src_idx];
+		dest_desc = &dpr->rx_std[dest_idx];
+		dest_map = &dpr->rx_std_buffers[dest_idx];
+		src_desc = &spr->rx_std[src_idx];
+		src_map = &spr->rx_std_buffers[src_idx];
 		break;
 
 	case RXD_OPAQUE_RING_JUMBO:
 		dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
-		dest_desc = &tpr->rx_jmb[dest_idx].std;
-		dest_map = &tpr->rx_jmb_buffers[dest_idx];
-		src_desc = &tpr->rx_jmb[src_idx].std;
-		src_map = &tpr->rx_jmb_buffers[src_idx];
+		dest_desc = &dpr->rx_jmb[dest_idx].std;
+		dest_map = &dpr->rx_jmb_buffers[dest_idx];
+		src_desc = &spr->rx_jmb[src_idx].std;
+		src_map = &spr->rx_jmb_buffers[src_idx];
 		break;
 
 	default:
@@ -4506,7 +4508,6 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi, u32 opaque_key,
 			   pci_unmap_addr(src_map, mapping));
 	dest_desc->addr_hi = src_desc->addr_hi;
 	dest_desc->addr_lo = src_desc->addr_lo;
-
 	src_map->skb = NULL;
 }
 
@@ -4580,7 +4581,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
 		    (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) {
 		drop_it:
-			tg3_recycle_rx(tnapi, opaque_key,
+			tg3_recycle_rx(tnapi, tpr, opaque_key,
 				       desc_idx, *post_ptr);
 		drop_it_no_recycle:
 			/* Other statistics kept track of by card. */
@@ -4600,7 +4601,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		) {
 			int skb_size;
 
-			skb_size = tg3_alloc_rx_skb(tnapi, opaque_key,
+			skb_size = tg3_alloc_rx_skb(tnapi, tpr, opaque_key,
 						    *post_ptr);
 			if (skb_size < 0)
 				goto drop_it;
@@ -4614,7 +4615,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 		} else {
 			struct sk_buff *copy_skb;
 
-			tg3_recycle_rx(tnapi, opaque_key,
+			tg3_recycle_rx(tnapi, tpr, opaque_key,
 				       desc_idx, *post_ptr);
 
 			copy_skb = netdev_alloc_skb(tp->dev,
@@ -5770,7 +5771,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 
 	/* Now allocate fresh SKBs for each rx ring. */
 	for (i = 0; i < tp->rx_pending; i++) {
-		if (tg3_alloc_rx_skb(tnapi, RXD_OPAQUE_RING_STD, i) < 0) {
+		if (tg3_alloc_rx_skb(tnapi, tpr, RXD_OPAQUE_RING_STD, i) < 0) {
 			printk(KERN_WARNING PFX
 			       "%s: Using a smaller RX standard ring, "
 			       "only %d out of %d buffers were allocated "
@@ -5801,7 +5802,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 		}
 
 		for (i = 0; i < tp->rx_jumbo_pending; i++) {
-			if (tg3_alloc_rx_skb(tnapi, RXD_OPAQUE_RING_JUMBO,
+			if (tg3_alloc_rx_skb(tnapi, tpr, RXD_OPAQUE_RING_JUMBO,
 					     i) < 0) {
 				printk(KERN_WARNING PFX
 				       "%s: Using a smaller RX jumbo ring, "
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 20/20] tg3: Update version to 3.104
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch updates the tg3 version to 3.104.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b01ea2e..6e6db95 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.103"
-#define DRV_MODULE_RELDATE	"November 2, 2009"
+#define DRV_MODULE_VERSION	"3.104"
+#define DRV_MODULE_RELDATE	"November 13, 2009"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 19/20] tg3: Fix DIDs, Enable 5717 support
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

This patch fixes the 5717 variant device ID enumerations and adds those
DIDs to the PCI ID table.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   10 ++++++----
 drivers/net/tg3.h |    7 +++----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3ff2d40..b01ea2e 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -241,6 +241,9 @@ static struct pci_device_id tg3_pci_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
 	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
+	{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
 	{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -12702,10 +12705,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
 		u32 prod_id_asic_rev;
 
-		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717C ||
-		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717S ||
-		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718C ||
-		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718S)
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724)
 			pci_read_config_dword(tp->pdev,
 					      TG3PCI_GEN2_PRODID_ASICREV,
 					      &prod_id_asic_rev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 6be46ab..453a34f 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -46,10 +46,9 @@
 #define  TG3PCI_DEVICE_TIGON3_57788	 0x1691
 #define  TG3PCI_DEVICE_TIGON3_5785_G	 0x1699 /* GPHY */
 #define  TG3PCI_DEVICE_TIGON3_5785_F	 0x16a0 /* 10/100 only */
-#define  TG3PCI_DEVICE_TIGON3_5717C	 0x1655
-#define  TG3PCI_DEVICE_TIGON3_5717S	 0x1656
-#define  TG3PCI_DEVICE_TIGON3_5718C	 0x1665
-#define  TG3PCI_DEVICE_TIGON3_5718S	 0x1666
+#define  TG3PCI_DEVICE_TIGON3_5717	 0x1655
+#define  TG3PCI_DEVICE_TIGON3_5718	 0x1656
+#define  TG3PCI_DEVICE_TIGON3_5724	 0x165c
 /* 0x04 --> 0x64 unused */
 #define TG3PCI_MSI_DATA			0x00000064
 /* 0x66 --> 0x68 unused */
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 14/20] tg3: rename rx_[std|jmb]_ptr
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

A later patch is going to add consumer indicies for the producer rings.
To keep things readable, this patch renames rx_[std|jmb]_ptr to
rx_[std|jmb]_prod_idx.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   16 ++++++++--------
 drivers/net/tg3.h |    4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 00e7e14..59a715a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4564,13 +4564,13 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 			ri = &tpr->rx_std_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
-			post_ptr = &tpr->rx_std_ptr;
+			post_ptr = &tpr->rx_std_prod_idx;
 			rx_std_posted++;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
 			ri = &tpr->rx_jmb_buffers[desc_idx];
 			dma_addr = pci_unmap_addr(ri, mapping);
 			skb = ri->skb;
-			post_ptr = &tpr->rx_jmb_ptr;
+			post_ptr = &tpr->rx_jmb_prod_idx;
 		} else
 			goto next_pkt_nopost;
 
@@ -4687,12 +4687,12 @@ next_pkt_nopost:
 
 	/* Refill RX ring(s). */
 	if (work_mask & RXD_OPAQUE_RING_STD) {
-		sw_idx = tpr->rx_std_ptr % TG3_RX_RING_SIZE;
+		sw_idx = tpr->rx_std_prod_idx % TG3_RX_RING_SIZE;
 		tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
 	}
 	if (work_mask & RXD_OPAQUE_RING_JUMBO) {
-		sw_idx = tpr->rx_jmb_ptr % TG3_RX_JUMBO_RING_SIZE;
+		sw_idx = tpr->rx_jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
 		tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 			     sw_idx);
 	}
@@ -7509,14 +7509,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
 	tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
 
-	tpr->rx_std_ptr = tp->rx_pending;
+	tpr->rx_std_prod_idx = tp->rx_pending;
 	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
-		     tpr->rx_std_ptr);
+		     tpr->rx_std_prod_idx);
 
-	tpr->rx_jmb_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ?
+	tpr->rx_jmb_prod_idx = (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) ?
 			  tp->rx_jumbo_pending : 0;
 	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
-		     tpr->rx_jmb_ptr);
+		     tpr->rx_jmb_prod_idx);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
 		tw32(STD_REPLENISH_LWM, 32);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 42fefa1..e0b86ba 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2570,8 +2570,8 @@ struct tg3_ethtool_stats {
 };
 
 struct tg3_rx_prodring_set {
-	u32				rx_std_ptr;
-	u32				rx_jmb_ptr;
+	u32				rx_std_prod_idx;
+	u32				rx_jmb_prod_idx;
 	struct tg3_rx_buffer_desc	*rx_std;
 	struct tg3_ext_rx_buffer_desc	*rx_jmb;
 	struct ring_info		*rx_std_buffers;
-- 
1.6.4.4



^ permalink raw reply related

* [PATCH 16/20] tg3: Lay proucer ring handling groundwork
From: Matt Carlson @ 2009-11-13 23:03 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy, Matt Carlson

The patch increases the number of producer rings available and
implements the constructor and destructor code that deals with them.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
---
 drivers/net/tg3.c |   85 ++++++++++++++++++++++++++++++----------------------
 drivers/net/tg3.h |    2 +-
 2 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index beda9bf..168a7ca 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -137,6 +137,12 @@
 #define TG3_RX_STD_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
 #define TG3_RX_JMB_MAP_SZ		TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
 
+#define TG3_RX_STD_BUFF_RING_SIZE \
+	(sizeof(struct ring_info) * TG3_RX_RING_SIZE)
+
+#define TG3_RX_JMB_BUFF_RING_SIZE \
+	(sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE)
+
 /* minimum number of free TX descriptors required to wake up TX process */
 #define TG3_TX_WAKEUP_THRESH(tnapi)		((tnapi)->tx_pending / 4)
 
@@ -4397,6 +4403,17 @@ static void tg3_tx(struct tg3_napi *tnapi)
 	}
 }
 
+static void tg3_rx_skb_free(struct tg3 *tp, struct ring_info *ri, u32 map_sz)
+{
+	if (!ri->skb)
+		return;
+
+	pci_unmap_single(tp->pdev, pci_unmap_addr(ri, mapping),
+			 map_sz, PCI_DMA_FROMDEVICE);
+	dev_kfree_skb_any(ri->skb);
+	ri->skb = NULL;
+}
+
 /* Returns size of skb allocated or < 0 on error.
  *
  * We only need to fill in the address because the other members
@@ -5701,36 +5718,18 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
 				 struct tg3_rx_prodring_set *tpr)
 {
 	int i;
-	struct ring_info *rxp;
 
-	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
-		rxp = &tpr->rx_std_buffers[i];
+	if (tpr != &tp->prodring[0])
+		return;
 
-		if (rxp->skb == NULL)
-			continue;
-
-		pci_unmap_single(tp->pdev,
-				 pci_unmap_addr(rxp, mapping),
-				 tp->rx_pkt_map_sz,
-				 PCI_DMA_FROMDEVICE);
-		dev_kfree_skb_any(rxp->skb);
-		rxp->skb = NULL;
-	}
+	for (i = 0; i < TG3_RX_RING_SIZE; i++)
+		tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
+				tp->rx_pkt_map_sz);
 
 	if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
-			rxp = &tpr->rx_jmb_buffers[i];
-
-			if (rxp->skb == NULL)
-				continue;
-
-			pci_unmap_single(tp->pdev,
-					 pci_unmap_addr(rxp, mapping),
-					 TG3_RX_JMB_MAP_SZ,
-					 PCI_DMA_FROMDEVICE);
-			dev_kfree_skb_any(rxp->skb);
-			rxp->skb = NULL;
-		}
+		for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++)
+			tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
+					TG3_RX_JMB_MAP_SZ);
 	}
 }
 
@@ -5746,6 +5745,14 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
 {
 	u32 i, rx_pkt_dma_sz;
 
+	if (tpr != &tp->prodring[0]) {
+		memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
+		if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
+			memset(&tpr->rx_jmb_buffers[0], 0,
+			       TG3_RX_JMB_BUFF_RING_SIZE);
+		goto done;
+	}
+
 	/* Zero out all descriptors. */
 	memset(tpr->rx_std, 0, TG3_RX_RING_BYTES);
 
@@ -5847,8 +5854,7 @@ static void tg3_rx_prodring_fini(struct tg3 *tp,
 static int tg3_rx_prodring_init(struct tg3 *tp,
 				struct tg3_rx_prodring_set *tpr)
 {
-	tpr->rx_std_buffers = kzalloc(sizeof(struct ring_info) *
-				      TG3_RX_RING_SIZE, GFP_KERNEL);
+	tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE, GFP_KERNEL);
 	if (!tpr->rx_std_buffers)
 		return -ENOMEM;
 
@@ -5858,8 +5864,7 @@ static int tg3_rx_prodring_init(struct tg3 *tp,
 		goto err_out;
 
 	if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-		tpr->rx_jmb_buffers = kzalloc(sizeof(struct ring_info) *
-					      TG3_RX_JUMBO_RING_SIZE,
+		tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE,
 					      GFP_KERNEL);
 		if (!tpr->rx_jmb_buffers)
 			goto err_out;
@@ -5915,9 +5920,10 @@ static void tg3_free_rings(struct tg3 *tp)
 
 			dev_kfree_skb_any(skb);
 		}
-	}
 
-	tg3_rx_prodring_free(tp, &tp->prodring[0]);
+		if (tp->irq_cnt == 1 || j != tp->irq_cnt - 1)
+			tg3_rx_prodring_free(tp, &tp->prodring[j]);
+	}
 }
 
 /* Initialize tx/rx rings for packet processing.
@@ -5951,9 +5957,13 @@ static int tg3_init_rings(struct tg3 *tp)
 		tnapi->rx_rcb_ptr = 0;
 		if (tnapi->rx_rcb)
 			memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+		if ((tp->irq_cnt == 1 || i != tp->irq_cnt - 1) &&
+			tg3_rx_prodring_alloc(tp, &tp->prodring[i]))
+			return -ENOMEM;
 	}
 
-	return tg3_rx_prodring_alloc(tp, &tp->prodring[0]);
+	return 0;
 }
 
 /*
@@ -5997,7 +6007,8 @@ static void tg3_free_consistent(struct tg3 *tp)
 		tp->hw_stats = NULL;
 	}
 
-	tg3_rx_prodring_fini(tp, &tp->prodring[0]);
+	for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++)
+		tg3_rx_prodring_fini(tp, &tp->prodring[i]);
 }
 
 /*
@@ -6008,8 +6019,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 {
 	int i;
 
-	if (tg3_rx_prodring_init(tp, &tp->prodring[0]))
-		return -ENOMEM;
+	for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++) {
+		if (tg3_rx_prodring_init(tp, &tp->prodring[i]))
+			goto err_out;
+	}
 
 	tp->hw_stats = pci_alloc_consistent(tp->pdev,
 					    sizeof(struct tg3_hw_stats),
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index e0b86ba..715df2b 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2682,7 +2682,7 @@ struct tg3 {
 	struct vlan_group		*vlgrp;
 #endif
 
-	struct tg3_rx_prodring_set	prodring[1];
+	struct tg3_rx_prodring_set	prodring[TG3_IRQ_MAX_VECS - 1];
 
 
 	/* begin "everything else" cacheline(s) section */
-- 
1.6.4.4



^ permalink raw reply related

* Re: [PATCH 0/3] macvlan: support for guest vm direct rx/tx
From: Patrick Mullaney @ 2009-11-13 23:05 UTC (permalink / raw)
  To: shemminger; +Cc: arnd, netdev, bridge, linux-kernel, alacrityvm-devel

On Fri, 2009-11-13 at 13:27 -0800, Stephen Hemminger wrote:
> On Fri, 13 Nov 2009 14:55:06 -0500
> Patrick Mullaney <pmullaney@novell.com> wrote:
> 
> > These patches allow other modules to override the receive
> > path of a macvlan. This is being done to support guest
> > VMs operating directly over a macvlan. Routines to allow
> > creation and deletion of macvlans from in-kernel modules
> > were also exposed/added.
> 
> Which guest VM, how will it use it? The kernel is not in the business
> of providing infrastructure for out of tree patches.

Actually, any guest vm or container. macvtap was the first to suggest
a patch like this to provide this functionality. This infrastructure
is generic enough to allow others to use it. My interest is in
supporting kvm guests via vbus drivers which are being integrated
in the alacrityvm tree.

> 
> Also, macvlan should really being calling netif_receive_skb()
> not going through another queue/softirq cycle.
I understand but you are talking about the current behavior of
macvlans - my goal wasn't to change the current behavior
of macvlans, as I didn't want to disturb what the original author
intended, just provide the ability to override the rx path and
provide for management of macvlans from other kernel modules(not
just via rtnl).

^ permalink raw reply

* [PATCH net-next-2.6] bonding: fix 802.3ad standards compliance error
From: Jay Vosburgh @ 2009-11-13 23:13 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, martin


	The language of 802.3ad 43.4.9 requires the "recordPDU" function
to, in part, compare the Partner parameter values in a received LACPDU
to the stored Actor values.  If those match, then the Partner's
synchronization state is set to true.

	The current 802.3ad implementation is performing these steps out
of order; first, the synchronization check is done, then the paramters are
checked to see if they match (the synch check being done against a match
check of a prior LACPDU).  This causes delays in establishing aggregators
in some circumstances.

	This patch modifies the 802.3ad code to call __choose_matched,
the function that does the "match" comparisions, as the first step of
__record_pdu, instead of immediately afterwards.  This new behavior is
in compliance with the language of the standard.

	Some additional commentary relating to code vs. standard is also
added.

	Reported by Martin Patterson <martin@gear6.com> who also supplied
the logic of the fix and verified the patch.

Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
---
 drivers/net/bonding/bond_3ad.c |   85 ++++++++++++++++++++--------------------
 1 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 1d05819..88c3fe8 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -446,6 +446,48 @@ static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
 /////////////////////////////////////////////////////////////////////////////////
 
 /**
+ * __choose_matched - update a port's matched variable from a received lacpdu
+ * @lacpdu: the lacpdu we've received
+ * @port: the port we're looking at
+ *
+ * Update the value of the matched variable, using parameter values from a
+ * newly received lacpdu. Parameter values for the partner carried in the
+ * received PDU are compared with the corresponding operational parameter
+ * values for the actor. Matched is set to TRUE if all of these parameters
+ * match and the PDU parameter partner_state.aggregation has the same value as
+ * actor_oper_port_state.aggregation and lacp will actively maintain the link
+ * in the aggregation. Matched is also set to TRUE if the value of
+ * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
+ * an individual link and lacp will actively maintain the link. Otherwise,
+ * matched is set to FALSE. LACP is considered to be actively maintaining the
+ * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
+ * the actor's actor_oper_port_state.lacp_activity and the PDU's
+ * partner_state.lacp_activity variables are TRUE.
+ *
+ * Note: the AD_PORT_MATCHED "variable" is not specified by 802.3ad; it is
+ * used here to implement the language from 802.3ad 43.4.9 that requires
+ * recordPDU to "match" the LACPDU parameters to the stored values.
+ */
+static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
+{
+	// check if all parameters are alike
+	if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
+	     (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
+	     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
+	     (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
+	     (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
+	     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
+	    // or this is individual link(aggregation == FALSE)
+	    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
+		) {
+		// update the state machine Matched variable
+		port->sm_vars |= AD_PORT_MATCHED;
+	} else {
+		port->sm_vars &= ~AD_PORT_MATCHED;
+	}
+}
+
+/**
  * __record_pdu - record parameters from a received lacpdu
  * @lacpdu: the lacpdu we've received
  * @port: the port we're looking at
@@ -459,6 +501,7 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
 	if (lacpdu && port) {
 		struct port_params *partner = &port->partner_oper;
 
+		__choose_matched(lacpdu, port);
 		// record the new parameter values for the partner operational
 		partner->port_number = ntohs(lacpdu->actor_port);
 		partner->port_priority = ntohs(lacpdu->actor_port_priority);
@@ -563,47 +606,6 @@ static void __update_default_selected(struct port *port)
 }
 
 /**
- * __choose_matched - update a port's matched variable from a received lacpdu
- * @lacpdu: the lacpdu we've received
- * @port: the port we're looking at
- *
- * Update the value of the matched variable, using parameter values from a
- * newly received lacpdu. Parameter values for the partner carried in the
- * received PDU are compared with the corresponding operational parameter
- * values for the actor. Matched is set to TRUE if all of these parameters
- * match and the PDU parameter partner_state.aggregation has the same value as
- * actor_oper_port_state.aggregation and lacp will actively maintain the link
- * in the aggregation. Matched is also set to TRUE if the value of
- * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
- * an individual link and lacp will actively maintain the link. Otherwise,
- * matched is set to FALSE. LACP is considered to be actively maintaining the
- * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
- * the actor's actor_oper_port_state.lacp_activity and the PDU's
- * partner_state.lacp_activity variables are TRUE.
- */
-static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
-{
-	// validate lacpdu and port
-	if (lacpdu && port) {
-		// check if all parameters are alike
-		if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
-		     (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
-		     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
-		     (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
-		     (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
-		     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
-		    // or this is individual link(aggregation == FALSE)
-		    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
-		   ) {
-			// update the state machine Matched variable
-			port->sm_vars |= AD_PORT_MATCHED;
-		} else {
-			port->sm_vars &= ~AD_PORT_MATCHED;
-		}
-	}
-}
-
-/**
  * __update_ntt - update a port's ntt variable from a received lacpdu
  * @lacpdu: the lacpdu we've received
  * @port: the port we're looking at
@@ -1134,7 +1136,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
 			__update_selected(lacpdu, port);
 			__update_ntt(lacpdu, port);
 			__record_pdu(lacpdu, port);
-			__choose_matched(lacpdu, port);
 			port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
 			port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
 			// verify that if the aggregator is enabled, the port is enabled too.
-- 
1.5.4.5


^ permalink raw reply related

* Re: [PATCH] ifb: add multi-queue support
From: Changli Gao @ 2009-11-13 23:28 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, Eric Dumazet, David S. Miller, Patrick McHardy,
	Tom Herbert, netdev
In-Reply-To: <20091113081553.0568296c@s6510>

On Sat, Nov 14, 2009 at 12:15 AM, Stephen Hemminger
<shemminger@vyatta.com> wrote:
> On Fri, 13 Nov 2009 17:38:56 +0800
> Changli Gao <xiaosuo@gmail.com> wrote:
>>
>> Oh, :) . I know more than one companies use kernel threads to forward
>> packets, and there isn't explicit extra overhead at all. And as you
>> know, as throughput increases, NAPI will bind the NIC to a CPU, and
>> softirqd will be waked up to do the work, which should be done in
>> SoftIRQ context. At that time, there isn't any difference between my
>> approach and the current kernel's.
>>
> Why not make IFB a NAPI device. This would get rid of the extra soft-irq
> round trip from going through netif_rx().  It would also behave like
> regular multi-queue recieive device, and eliminate need for seperate
> tasklets or threads.
>

It needs to send remote SoftIRQ, as Receiving Packet Steering, and we
must support a extra interface to map load to CPUs.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH net-next-2.6] bonding: fix 802.3ad standards compliance error
From: Stephen Hemminger @ 2009-11-13 23:30 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: netdev, David S. Miller, martin
In-Reply-To: <3048.1258153981@death.nxdomain.ibm.com>

On Fri, 13 Nov 2009 15:13:01 -0800
Jay Vosburgh <fubar@us.ibm.com> wrote:

> +	// check if all parameters are alike
> +	if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
> +	     (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
> +	     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
> +	     (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
> +	     (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
> +	     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
> +	    // or this is individual link(aggregation == FALSE)

I know the code here doesn't follow kernel style, but please don't
add more C99 comments or overly long lines.

-- 

^ permalink raw reply

* Re: [PATCH] ifb: add multi-queue support
From: Stephen Hemminger @ 2009-11-13 23:32 UTC (permalink / raw)
  To: Changli Gao
  Cc: Jarek Poplawski, Eric Dumazet, David S. Miller, Patrick McHardy,
	Tom Herbert, netdev
In-Reply-To: <412e6f7f0911131528i3105648y49213143e12f2522@mail.gmail.com>

On Sat, 14 Nov 2009 07:28:42 +0800
Changli Gao <xiaosuo@gmail.com> wrote:

> On Sat, Nov 14, 2009 at 12:15 AM, Stephen Hemminger
> <shemminger@vyatta.com> wrote:
> > On Fri, 13 Nov 2009 17:38:56 +0800
> > Changli Gao <xiaosuo@gmail.com> wrote:
> >>
> >> Oh, :) . I know more than one companies use kernel threads to forward
> >> packets, and there isn't explicit extra overhead at all. And as you
> >> know, as throughput increases, NAPI will bind the NIC to a CPU, and
> >> softirqd will be waked up to do the work, which should be done in
> >> SoftIRQ context. At that time, there isn't any difference between my
> >> approach and the current kernel's.
> >>
> > Why not make IFB a NAPI device. This would get rid of the extra soft-irq
> > round trip from going through netif_rx().  It would also behave like
> > regular multi-queue recieive device, and eliminate need for seperate
> > tasklets or threads.
> >
> 
> It needs to send remote SoftIRQ, as Receiving Packet Steering, and we
> must support a extra interface to map load to CPUs.
> 

But it still could use NAPI to avoid causing excess packet overhead.
The softirq could be equivalent of hardirq in network device.

-- 

^ permalink raw reply

* Re: [net-next-2.6 PATCH] net: fast consecutive name allocation
From: Benjamin LaHaise @ 2009-11-13 23:35 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Octavian Purdila, Eric Dumazet, netdev
In-Reply-To: <20091113144937.23693bb4@nehalam>

On Fri, Nov 13, 2009 at 02:49:37PM -0800, Stephen Hemminger wrote:
> Then maybe network devices aren't the right layering model. At some
> point the paradigm has to be re-examined.

What is the right model for dealing with lots of connections to users and 
routes?  This problem isn't going to go away given the increases in 
connectivity and processing power that happen each year.  Today, software 
routing of 10Gbps links is a reality -- part of what comes with that ability 
of hardware is the need to deal with the fact that 10Gbps aggregates a lot 
of users.

		-ben

^ permalink raw reply

* Re: [net-next-2.6 PATCH] net: fast consecutive name allocation
From: Stephen Hemminger @ 2009-11-13 23:39 UTC (permalink / raw)
  To: Benjamin LaHaise; +Cc: Octavian Purdila, Eric Dumazet, netdev
In-Reply-To: <20091113233504.GQ19478@kvack.org>

On Fri, 13 Nov 2009 18:35:04 -0500
Benjamin LaHaise <bcrl@lhnet.ca> wrote:

> On Fri, Nov 13, 2009 at 02:49:37PM -0800, Stephen Hemminger wrote:
> > Then maybe network devices aren't the right layering model. At some
> > point the paradigm has to be re-examined.
> 
> What is the right model for dealing with lots of connections to users and 
> routes?  This problem isn't going to go away given the increases in 
> connectivity and processing power that happen each year.  Today, software 
> routing of 10Gbps links is a reality -- part of what comes with that ability 
> of hardware is the need to deal with the fact that 10Gbps aggregates a lot 
> of users.
> 
> 		-ben

Well TCP handles lots of connections, but a socket has different overhead
than a network device. Why should 10Gbps need 10K PPPoE sessions?
Even Vlan's are less overhead than PPP

-- 

^ permalink raw reply

* Re: [PATCH] ifb: add multi-queue support
From: Changli Gao @ 2009-11-13 23:42 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jarek Poplawski, Eric Dumazet, David S. Miller, Patrick McHardy,
	Tom Herbert, netdev
In-Reply-To: <20091113153229.408c889f@nehalam>

On Sat, Nov 14, 2009 at 7:32 AM, Stephen Hemminger
<shemminger@vyatta.com> wrote:
> On Sat, 14 Nov 2009 07:28:42 +0800
> Changli Gao <xiaosuo@gmail.com> wrote:
>
>> On Sat, Nov 14, 2009 at 12:15 AM, Stephen Hemminger
>>
>> It needs to send remote SoftIRQ, as Receiving Packet Steering, and we
>> must support a extra interface to map load to CPUs.
>>
>
> But it still could use NAPI to avoid causing excess packet overhead.
> The softirq could be equivalent of hardirq in network device.
>

Yea, the overhead of SoftIRQ is less than kernel threads, and I'll try
to find a way to solve both flexibility and efficiency. Maybe I need
some real NIC drivers as examples. Is there a standard API to bind RQs
of NIC to CPUs, such as ioctl or setsockopt?


-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: [PATCH net-next-2.6] bonding: fix 802.3ad standards compliance error
From: Jay Vosburgh @ 2009-11-13 23:47 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, David S. Miller, martin
In-Reply-To: <20091113153058.4b739ea3@nehalam>

Stephen Hemminger <shemminger@vyatta.com> wrote:

>On Fri, 13 Nov 2009 15:13:01 -0800
>Jay Vosburgh <fubar@us.ibm.com> wrote:
>
>> +	// check if all parameters are alike
>> +	if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
>> +	     (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
>> +	     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
>> +	     (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
>> +	     (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
>> +	     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
>> +	    // or this is individual link(aggregation == FALSE)
>
>I know the code here doesn't follow kernel style, but please don't
>add more C99 comments or overly long lines.

	I didn't, really; I moved the function up in the file rather
than adding a forward declaration.

	-J

---
	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com

^ permalink raw reply

* Re: [net-next-2.6 PATCH] net: fast consecutive name allocation
From: Benjamin LaHaise @ 2009-11-13 23:52 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Octavian Purdila, Eric Dumazet, netdev
In-Reply-To: <20091113153924.6130135f@nehalam>

On Fri, Nov 13, 2009 at 03:39:24PM -0800, Stephen Hemminger wrote:
> Well TCP handles lots of connections, but a socket has different overhead
> than a network device. Why should 10Gbps need 10K PPPoE sessions?
> Even Vlan's are less overhead than PPP

PPP's overhead is acceptable.  It makes managing networks a lot easier, since 
the authentication done by PPP is able to look up any end user specific 
information required (ie static ips and routes), while the access part of 
the network is a fairly generic config that uses switchs and things like the 
GVRP.  Without that, the configuration of any aggregation switch becomes a 
huge management nightmare.

If you don't want the overhead from this kind of scaling, stick it under a 
config option, but please don't stop other people from pushing Linux into 
new uses which have these scaling requirements.

		-ben

^ permalink raw reply

* Re: [net-next-2.6 PATCH] net: fast consecutive name allocation
From: Stephen Hemminger @ 2009-11-14  0:04 UTC (permalink / raw)
  To: Octavian Purdila; +Cc: netdev
In-Reply-To: <200911130720.19671.opurdila@ixiacom.com>

On Fri, 13 Nov 2009 07:20:19 +0200
Octavian Purdila <opurdila@ixiacom.com> wrote:

> On Friday 13 November 2009 07:01:14 you wrote:
> > This patch speeds up the network device name allocation for the case
> > where a significant number of devices of the same type are created
> > consecutively.
> > 
> > Tests performed on a PPC750 @ 800Mhz machine with per device sysctl
> > and sysfs entries disabled:
> > 
> > Without the patch           With the patch
> > 
> > real    0m 43.43s	    real    0m 0.49s
> > user    0m 0.00s	    user    0m 0.00s
> > sys     0m 43.43s	    sys     0m 0.48s

Since the main overhead here is building the bitmap table used in the
name scan. Why not mantain the bitmap table between calls by
implementing a rbtree with prefix -> bitmap.
The tree would have to be limited and per namespace but then you
could handle the general case of adding a device, then its vlans,
then another device, ...


-- 

^ permalink raw reply

* Re: [net-next-2.6 PATCH] net: fast consecutive name allocation
From: Octavian Purdila @ 2009-11-14  0:14 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20091113160445.7a3538ef@nehalam>

On Saturday 14 November 2009 02:04:45 you wrote:
> On Fri, 13 Nov 2009 07:20:19 +0200
> 
> Octavian Purdila <opurdila@ixiacom.com> wrote:
> > On Friday 13 November 2009 07:01:14 you wrote:
> > > This patch speeds up the network device name allocation for the case
> > > where a significant number of devices of the same type are created
> > > consecutively.
> > >
> > > Tests performed on a PPC750 @ 800Mhz machine with per device sysctl
> > > and sysfs entries disabled:
> > >
> > > Without the patch           With the patch
> > >
> > > real    0m 43.43s	    real    0m 0.49s
> > > user    0m 0.00s	    user    0m 0.00s
> > > sys     0m 43.43s	    sys     0m 0.48s
> 
> Since the main overhead here is building the bitmap table used in the
> name scan. Why not mantain the bitmap table between calls by
> implementing a rbtree with prefix -> bitmap.
> The tree would have to be limited and per namespace but then you
> could handle the general case of adding a device, then its vlans,
> then another device, ...
> 

I'll do that !

That was my original intent but I thought it would be too much bloat :) But I 
see your point, even if it is more complex, its more useful.

Thanks,
tavi

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox