Netdev List
 help / color / mirror / Atom feed
* [net-next PATCH 07/11] enic: provision for multiple Rx/Tx queues; prepare for RSS support
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: provision for multiple Rx/Tx queues; prepare for RSS support

Provision for multiple Rx/Tx queues.  Max of 8 WQs and 8 RQs.  Max for
completion queue is 8+8=16 and max for interrupt resources is 8+8+2.

Add driver/firmware interface for setting up RSS secret key and indirection
table.

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic.h      |   16 ++++++++++------
 drivers/net/enic/enic_main.c |    6 +++---
 drivers/net/enic/enic_res.c  |   33 ++++++++++++++++++++++++++++-----
 drivers/net/enic/enic_res.h  |    2 ++
 drivers/net/enic/vnic_nic.h  |    7 +++++++
 5 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index f7c5b33..e1c2076 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -29,6 +29,7 @@
 #include "vnic_cq.h"
 #include "vnic_intr.h"
 #include "vnic_stats.h"
+#include "vnic_nic.h"
 #include "vnic_rss.h"
 
 #define DRV_NAME		"enic"
@@ -42,17 +43,20 @@
 
 #define ENIC_BARS_MAX		6
 
+#define ENIC_WQ_MAX		8
+#define ENIC_RQ_MAX		8
+#define ENIC_CQ_MAX		(ENIC_WQ_MAX + ENIC_RQ_MAX)
+#define ENIC_INTR_MAX		(ENIC_CQ_MAX + 2)
+
 enum enic_cq_index {
 	ENIC_CQ_RQ,
 	ENIC_CQ_WQ,
-	ENIC_CQ_MAX,
 };
 
 enum enic_intx_intr_index {
 	ENIC_INTX_WQ_RQ,
 	ENIC_INTX_ERR,
 	ENIC_INTX_NOTIFY,
-	ENIC_INTX_MAX,
 };
 
 enum enic_msix_intr_index {
@@ -90,13 +94,13 @@ struct enic {
 	u32 port_mtu;
 
 	/* work queue cache line section */
-	____cacheline_aligned struct vnic_wq wq[1];
-	spinlock_t wq_lock[1];
+	____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
+	spinlock_t wq_lock[ENIC_WQ_MAX];
 	unsigned int wq_count;
 	struct vlan_group *vlan_group;
 
 	/* receive queue cache line section */
-	____cacheline_aligned struct vnic_rq rq[1];
+	____cacheline_aligned struct vnic_rq rq[ENIC_RQ_MAX];
 	unsigned int rq_count;
 	int (*rq_alloc_buf)(struct vnic_rq *rq);
 	u64 rq_truncated_pkts;
@@ -106,7 +110,7 @@ struct enic {
 	struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC];
 
 	/* interrupt resource cache line section */
-	____cacheline_aligned struct vnic_intr intr[ENIC_MSIX_MAX];
+	____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX];
 	unsigned int intr_count;
 	u32 __iomem *legacy_pba;		/* memory-mapped */
 
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 139c380..6068904 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1585,7 +1585,7 @@ static int enic_set_niccfg(struct enic *enic)
 	const u8 ig_vlan_strip_en = 1;
 
 	/* Enable VLAN tag stripping.  RSS not enabled (yet).
-	*/
+	 */
 
 	return enic_set_nic_cfg(enic,
 		rss_default_cpu, rss_hash_type,
@@ -1620,8 +1620,8 @@ static void enic_reset(struct work_struct *work)
 
 static int enic_set_intr_mode(struct enic *enic)
 {
-	unsigned int n = ARRAY_SIZE(enic->rq);
-	unsigned int m = ARRAY_SIZE(enic->wq);
+	unsigned int n = 1;
+	unsigned int m = 1;
 	unsigned int i;
 
 	/* Set interrupt mode (INTx, MSI, MSI-X) depending
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index e5fc938..3211114 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -156,6 +156,22 @@ int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
 	return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
 }
 
+int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len)
+{
+	u64 a0 = (u64)key_pa, a1 = len;
+	int wait = 1000;
+
+	return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait);
+}
+
+int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len)
+{
+	u64 a0 = (u64)cpu_pa, a1 = len;
+	int wait = 1000;
+
+	return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait);
+}
+
 void enic_free_vnic_resources(struct enic *enic)
 {
 	unsigned int i;
@@ -172,11 +188,18 @@ void enic_free_vnic_resources(struct enic *enic)
 
 void enic_get_res_counts(struct enic *enic)
 {
-	enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
-	enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
-	enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
-	enic->intr_count = vnic_dev_get_res_count(enic->vdev,
-		RES_TYPE_INTR_CTRL);
+	enic->wq_count = min_t(int,
+		vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ),
+		ENIC_WQ_MAX);
+	enic->rq_count = min_t(int,
+		vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ),
+		ENIC_RQ_MAX);
+	enic->cq_count = min_t(int,
+		vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ),
+		ENIC_CQ_MAX);
+	enic->intr_count = min_t(int,
+		vnic_dev_get_res_count(enic->vdev, RES_TYPE_INTR_CTRL),
+		ENIC_INTR_MAX);
 
 	printk(KERN_INFO PFX "vNIC resources avail: "
 		"wq %d rq %d cq %d intr %d\n",
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
index 7bf272f..abc1974 100644
--- a/drivers/net/enic/enic_res.h
+++ b/drivers/net/enic/enic_res.h
@@ -139,6 +139,8 @@ void enic_del_vlan(struct enic *enic, u16 vlanid);
 int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
 	u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
 	u8 ig_vlan_strip_en);
+int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len);
+int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len);
 void enic_get_res_counts(struct enic *enic);
 void enic_init_vnic_resources(struct enic *enic);
 int enic_alloc_vnic_resources(struct enic *);
diff --git a/drivers/net/enic/vnic_nic.h b/drivers/net/enic/vnic_nic.h
index dadf26f..eeaf329 100644
--- a/drivers/net/enic/vnic_nic.h
+++ b/drivers/net/enic/vnic_nic.h
@@ -41,6 +41,13 @@
 #define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD	1UL
 #define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT		24
 
+#define NIC_CFG_RSS_HASH_TYPE_IPV4		(1 << 0)
+#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4		(1 << 1)
+#define NIC_CFG_RSS_HASH_TYPE_IPV6		(1 << 2)
+#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6		(1 << 3)
+#define NIC_CFG_RSS_HASH_TYPE_IPV6_EX		(1 << 4)
+#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX	(1 << 5)
+
 static inline void vnic_set_nic_cfg(u32 *nic_cfg,
 	u8 rss_default_cpu, u8 rss_hash_type,
 	u8 rss_hash_bits, u8 rss_base_cpu,


^ permalink raw reply related

* [net-next PATCH 08/11] enic: bug fix: enable VLAN filtering
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: bug fix: enable VLAN filtering

Bug fix: enable VLAN filtering

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic_main.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 6068904..3a55669 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1967,7 +1967,8 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 		break;
 	}
 
-	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	netdev->features |= NETIF_F_HW_VLAN_TX |
+		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
 	if (ENIC_SETTING(enic, TXCSUM))
 		netdev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
 	if (ENIC_SETTING(enic, TSO))


^ permalink raw reply related

* [net-next PATCH 09/11] enic: changes to driver/firmware interface
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: changes to driver/firmware interface

Deprecate some old APIa; change arguments to stats dump all API; add new
interrupt assert API

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/vnic_dev.c    |   14 ++++++++++++++
 drivers/net/enic/vnic_dev.h    |    1 +
 drivers/net/enic/vnic_devcmd.h |   20 ++++++++++----------
 drivers/net/enic/vnic_intr.c   |    5 +++++
 4 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index c8d3fc7..29a48e8 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -560,6 +560,20 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
 		printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err);
 }
 
+int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr)
+{
+	u64 a0 = intr, a1 = 0;
+	int wait = 1000;
+	int err;
+
+	err = vnic_dev_cmd(vdev, CMD_IAR, &a0, &a1, wait);
+	if (err)
+		printk(KERN_ERR "Failed to raise INTR[%d], err %d\n",
+			intr, err);
+
+	return err;
+}
+
 int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
 {
 	u64 a0, a1;
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index db1d63e..fc5e3eb 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -106,6 +106,7 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
 void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
 void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
 int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
+int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr);
 int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr);
 void vnic_dev_notify_unset(struct vnic_dev *vdev);
 int vnic_dev_link_status(struct vnic_dev *vdev);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 2587f34..d78bbcc 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -105,14 +105,6 @@ enum vnic_devcmd_cmd {
 	CMD_MAC_ADDR            = _CMDC(_CMD_DIR_READ,
 					_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 9),
 
-	/* disable/enable promisc mode: (u8)a0=0/1 */
-/***** XXX DEPRECATED *****/
-	CMD_PROMISC_MODE        = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 10),
-
-	/* disable/enable all-multi mode: (u8)a0=0/1 */
-/***** XXX DEPRECATED *****/
-	CMD_ALLMULTI_MODE       = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 11),
-
 	/* add addr from (u48)a0 */
 	CMD_ADDR_ADD            = _CMDCNW(_CMD_DIR_WRITE,
 					_CMD_VTYPE_ENET | _CMD_VTYPE_FC, 12),
@@ -182,7 +174,9 @@ enum vnic_devcmd_cmd {
 	/* disable virtual link */
 	CMD_DISABLE		= _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29),
 
-	/* stats dump all vnics on uplink in mem: (u64)a0=paddr (u32)a1=uif */
+	/* stats dump sum of all vnic stats on same uplink in mem:
+	 *     (u64)a0=paddr
+	 *     (u16)a1=sizeof stats area */
 	CMD_STATS_DUMP_ALL	= _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 30),
 
 	/* init status:
@@ -211,7 +205,12 @@ enum vnic_devcmd_cmd {
 	/* persistent binding info
 	 * in:  (u64)a0=paddr of arg
 	 *      (u32)a1=CMD_PERBI_XXX */
-	CMD_PERBI               = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
+	CMD_PERBI		= _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
+
+	/* Interrupt Assert Register functionality
+	 * in: (u16)a0=interrupt number to assert
+	 */
+	CMD_IAR			= _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38),
 };
 
 /* flags for CMD_OPEN */
@@ -244,6 +243,7 @@ enum vnic_devcmd_error {
 	ERR_ENOMEM = 7,
 	ERR_ETIMEDOUT = 8,
 	ERR_ELINKDOWN = 9,
+	ERR_EMAXRES = 10,
 };
 
 struct vnic_devcmd_fw_info {
diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c
index ddc38f8..1f8786d 100644
--- a/drivers/net/enic/vnic_intr.c
+++ b/drivers/net/enic/vnic_intr.c
@@ -60,3 +60,8 @@ void vnic_intr_clean(struct vnic_intr *intr)
 {
 	iowrite32(0, &intr->ctrl->int_credits);
 }
+
+void vnic_intr_raise(struct vnic_intr *intr)
+{
+	vnic_dev_raise_intr(intr->vdev, (u16)intr->index);
+}


^ permalink raw reply related

* [net-next PATCH 10/11] enic: bug fix: check for zero port MTU before posting warning
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: bug fix: check for zero port MTU before posting warning

Nic firmware can return zero for port MTU, so check for non-zero value
before checking for change in port MTU.

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 3a55669..9368dae 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -362,7 +362,7 @@ static void enic_mtu_check(struct enic *enic)
 {
 	u32 mtu = vnic_dev_mtu(enic->vdev);
 
-	if (mtu != enic->port_mtu) {
+	if (mtu && mtu != enic->port_mtu) {
 		if (mtu < enic->netdev->mtu)
 			printk(KERN_WARNING PFX
 				"%s: interface MTU (%d) set higher "


^ permalink raw reply related

* [net-next PATCH 11/11] enic: organize device initialization/deinit into separate functions
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: organize device initialization/deinit into separate functions

To unclutter probe() a little bit, put all device initialization code
in one spot and device deinit code in another spot.  Also remove unused
rq->buf_index variable/func.

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic_main.c |  145 ++++++++++++++++++++++++++----------------
 drivers/net/enic/vnic_rq.c   |   27 +++++---
 drivers/net/enic/vnic_rq.h   |   12 +--
 drivers/net/enic/vnic_wq.c   |   20 +++++-
 drivers/net/enic/vnic_wq.h   |    4 +
 5 files changed, 133 insertions(+), 75 deletions(-)

diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 9368dae..2737c0d 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1740,6 +1740,88 @@ static const struct net_device_ops enic_netdev_ops = {
 #endif
 };
 
+void enic_dev_deinit(struct enic *enic)
+{
+	netif_napi_del(&enic->napi);
+	enic_free_vnic_resources(enic);
+	enic_clear_intr_mode(enic);
+}
+
+int enic_dev_init(struct enic *enic)
+{
+	struct net_device *netdev = enic->netdev;
+	int err;
+
+	/* Get vNIC configuration
+	 */
+
+	err = enic_get_vnic_config(enic);
+	if (err) {
+		printk(KERN_ERR PFX
+			"Get vNIC configuration failed, aborting.\n");
+		return err;
+	}
+
+	/* Get available resource counts
+	 */
+
+	enic_get_res_counts(enic);
+
+	/* Set interrupt mode based on resource counts and system
+	 * capabilities
+	 */
+
+	err = enic_set_intr_mode(enic);
+	if (err) {
+		printk(KERN_ERR PFX
+			"Failed to set intr mode, aborting.\n");
+		return err;
+	}
+
+	/* Allocate and configure vNIC resources
+	 */
+
+	err = enic_alloc_vnic_resources(enic);
+	if (err) {
+		printk(KERN_ERR PFX
+			"Failed to alloc vNIC resources, aborting.\n");
+		goto err_out_free_vnic_resources;
+	}
+
+	enic_init_vnic_resources(enic);
+
+	err = enic_set_rq_alloc_buf(enic);
+	if (err) {
+		printk(KERN_ERR PFX
+			"Failed to set RQ buffer allocator, aborting.\n");
+		goto err_out_free_vnic_resources;
+	}
+
+	err = enic_set_niccfg(enic);
+	if (err) {
+		printk(KERN_ERR PFX
+			"Failed to config nic, aborting.\n");
+		goto err_out_free_vnic_resources;
+	}
+
+	switch (vnic_dev_get_intr_mode(enic->vdev)) {
+	default:
+		netif_napi_add(netdev, &enic->napi, enic_poll, 64);
+		break;
+	case VNIC_DEV_INTR_MODE_MSIX:
+		netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64);
+		break;
+	}
+
+	return 0;
+
+err_out_free_vnic_resources:
+	enic_clear_intr_mode(enic);
+	enic_free_vnic_resources(enic);
+
+	return err;
+}
+
 static void enic_iounmap(struct enic *enic)
 {
 	unsigned int i;
@@ -1882,51 +1964,13 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 		goto err_out_dev_close;
 	}
 
-	/* Get vNIC configuration
-	 */
-
-	err = enic_get_vnic_config(enic);
+	err = enic_dev_init(enic);
 	if (err) {
 		printk(KERN_ERR PFX
-			"Get vNIC configuration failed, aborting.\n");
+			"Device initialization failed, aborting.\n");
 		goto err_out_dev_close;
 	}
 
-	/* Get available resource counts
-	 */
-
-	enic_get_res_counts(enic);
-
-	/* Set interrupt mode based on resource counts and system
-	 * capabilities
-	 */
-
-	err = enic_set_intr_mode(enic);
-	if (err) {
-		printk(KERN_ERR PFX
-			"Failed to set intr mode, aborting.\n");
-		goto err_out_dev_close;
-	}
-
-	/* Allocate and configure vNIC resources
-	 */
-
-	err = enic_alloc_vnic_resources(enic);
-	if (err) {
-		printk(KERN_ERR PFX
-			"Failed to alloc vNIC resources, aborting.\n");
-		goto err_out_free_vnic_resources;
-	}
-
-	enic_init_vnic_resources(enic);
-
-	err = enic_set_niccfg(enic);
-	if (err) {
-		printk(KERN_ERR PFX
-			"Failed to config nic, aborting.\n");
-		goto err_out_free_vnic_resources;
-	}
-
 	/* Setup notification timer, HW reset task, and locks
 	 */
 
@@ -1951,22 +1995,13 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	if (err) {
 		printk(KERN_ERR PFX
 			"Invalid MAC address, aborting.\n");
-		goto err_out_free_vnic_resources;
+		goto err_out_dev_deinit;
 	}
 
 	netdev->netdev_ops = &enic_netdev_ops;
 	netdev->watchdog_timeo = 2 * HZ;
 	netdev->ethtool_ops = &enic_ethtool_ops;
 
-	switch (vnic_dev_get_intr_mode(enic->vdev)) {
-	default:
-		netif_napi_add(netdev, &enic->napi, enic_poll, 64);
-		break;
-	case VNIC_DEV_INTR_MODE_MSIX:
-		netif_napi_add(netdev, &enic->napi, enic_poll_msix, 64);
-		break;
-	}
-
 	netdev->features |= NETIF_F_HW_VLAN_TX |
 		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
 	if (ENIC_SETTING(enic, TXCSUM))
@@ -1994,17 +2029,16 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	if (err) {
 		printk(KERN_ERR PFX
 			"Cannot register net device, aborting.\n");
-		goto err_out_free_vnic_resources;
+		goto err_out_dev_deinit;
 	}
 
 	return 0;
 
-err_out_free_vnic_resources:
-	enic_free_vnic_resources(enic);
+err_out_dev_deinit:
+	enic_dev_deinit(enic);
 err_out_dev_close:
 	vnic_dev_close(enic->vdev);
 err_out_vnic_unregister:
-	enic_clear_intr_mode(enic);
 	vnic_dev_unregister(enic->vdev);
 err_out_iounmap:
 	enic_iounmap(enic);
@@ -2028,9 +2062,8 @@ static void __devexit enic_remove(struct pci_dev *pdev)
 
 		flush_scheduled_work();
 		unregister_netdev(netdev);
-		enic_free_vnic_resources(enic);
+		enic_dev_deinit(enic);
 		vnic_dev_close(enic->vdev);
-		enic_clear_intr_mode(enic);
 		vnic_dev_unregister(enic->vdev);
 		enic_iounmap(enic);
 		pci_release_regions(pdev);
diff --git a/drivers/net/enic/vnic_rq.c b/drivers/net/enic/vnic_rq.c
index 9365e63..7558397 100644
--- a/drivers/net/enic/vnic_rq.c
+++ b/drivers/net/enic/vnic_rq.c
@@ -62,7 +62,6 @@ static int vnic_rq_alloc_bufs(struct vnic_rq *rq)
 	}
 
 	rq->to_use = rq->to_clean = rq->bufs[0];
-	rq->buf_index = 0;
 
 	return 0;
 }
@@ -113,12 +112,12 @@ int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
 	return 0;
 }
 
-void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
+void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
+	unsigned int fetch_index, unsigned int posted_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset)
 {
 	u64 paddr;
-	u32 fetch_index;
 
 	paddr = (u64)rq->ring.base_addr | VNIC_PADDR_TARGET;
 	writeq(paddr, &rq->ctrl->ring_base);
@@ -128,15 +127,27 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
 	iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset);
 	iowrite32(0, &rq->ctrl->dropped_packet_count);
 	iowrite32(0, &rq->ctrl->error_status);
+	iowrite32(fetch_index, &rq->ctrl->fetch_index);
+	iowrite32(posted_index, &rq->ctrl->posted_index);
 
-	/* Use current fetch_index as the ring starting point */
-	fetch_index = ioread32(&rq->ctrl->fetch_index);
 	rq->to_use = rq->to_clean =
 		&rq->bufs[fetch_index / VNIC_RQ_BUF_BLK_ENTRIES]
 			[fetch_index % VNIC_RQ_BUF_BLK_ENTRIES];
-	iowrite32(fetch_index, &rq->ctrl->posted_index);
+}
+
+void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
+	unsigned int error_interrupt_enable,
+	unsigned int error_interrupt_offset)
+{
+	u32 fetch_index;
 
-	rq->buf_index = 0;
+	/* Use current fetch_index as the ring starting point */
+	fetch_index = ioread32(&rq->ctrl->fetch_index);
+
+	vnic_rq_init_start(rq, cq_index,
+		fetch_index, fetch_index,
+		error_interrupt_enable,
+		error_interrupt_offset);
 }
 
 unsigned int vnic_rq_error_status(struct vnic_rq *rq)
@@ -192,8 +203,6 @@ void vnic_rq_clean(struct vnic_rq *rq,
 			[fetch_index % VNIC_RQ_BUF_BLK_ENTRIES];
 	iowrite32(fetch_index, &rq->ctrl->posted_index);
 
-	rq->buf_index = 0;
-
 	vnic_dev_clear_desc_ring(&rq->ring);
 }
 
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
index f7b5730..35e736c 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/enic/vnic_rq.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
+ * Copyright 2008, 2009 Cisco Systems, Inc.  All rights reserved.
  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
  *
  * This program is free software; you may redistribute it and/or modify
@@ -79,7 +79,6 @@ struct vnic_rq {
 	struct vnic_rq_buf *to_use;
 	struct vnic_rq_buf *to_clean;
 	void *os_buf_head;
-	unsigned int buf_index;
 	unsigned int pkts_outstanding;
 };
 
@@ -105,11 +104,6 @@ static inline unsigned int vnic_rq_next_index(struct vnic_rq *rq)
 	return rq->to_use->index;
 }
 
-static inline unsigned int vnic_rq_next_buf_index(struct vnic_rq *rq)
-{
-	return rq->buf_index++;
-}
-
 static inline void vnic_rq_post(struct vnic_rq *rq,
 	void *os_buf, unsigned int os_buf_index,
 	dma_addr_t dma_addr, unsigned int len)
@@ -204,6 +198,10 @@ static inline int vnic_rq_fill(struct vnic_rq *rq,
 void vnic_rq_free(struct vnic_rq *rq);
 int vnic_rq_alloc(struct vnic_dev *vdev, struct vnic_rq *rq, unsigned int index,
 	unsigned int desc_count, unsigned int desc_size);
+void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index,
+	unsigned int fetch_index, unsigned int posted_index,
+	unsigned int error_interrupt_enable,
+	unsigned int error_interrupt_offset);
 void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset);
diff --git a/drivers/net/enic/vnic_wq.c b/drivers/net/enic/vnic_wq.c
index a576d04..d2e00e5 100644
--- a/drivers/net/enic/vnic_wq.c
+++ b/drivers/net/enic/vnic_wq.c
@@ -112,7 +112,8 @@ int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
 	return 0;
 }
 
-void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
+void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+	unsigned int fetch_index, unsigned int posted_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset)
 {
@@ -121,12 +122,25 @@ void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
 	paddr = (u64)wq->ring.base_addr | VNIC_PADDR_TARGET;
 	writeq(paddr, &wq->ctrl->ring_base);
 	iowrite32(wq->ring.desc_count, &wq->ctrl->ring_size);
-	iowrite32(0, &wq->ctrl->fetch_index);
-	iowrite32(0, &wq->ctrl->posted_index);
+	iowrite32(fetch_index, &wq->ctrl->fetch_index);
+	iowrite32(posted_index, &wq->ctrl->posted_index);
 	iowrite32(cq_index, &wq->ctrl->cq_index);
 	iowrite32(error_interrupt_enable, &wq->ctrl->error_interrupt_enable);
 	iowrite32(error_interrupt_offset, &wq->ctrl->error_interrupt_offset);
 	iowrite32(0, &wq->ctrl->error_status);
+
+	wq->to_use = wq->to_clean =
+		&wq->bufs[fetch_index / VNIC_WQ_BUF_BLK_ENTRIES]
+			[fetch_index % VNIC_WQ_BUF_BLK_ENTRIES];
+}
+
+void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
+	unsigned int error_interrupt_enable,
+	unsigned int error_interrupt_offset)
+{
+	vnic_wq_init_start(wq, cq_index, 0, 0,
+		error_interrupt_enable,
+		error_interrupt_offset);
 }
 
 unsigned int vnic_wq_error_status(struct vnic_wq *wq)
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h
index c826137..9c34d41 100644
--- a/drivers/net/enic/vnic_wq.h
+++ b/drivers/net/enic/vnic_wq.h
@@ -149,6 +149,10 @@ static inline void vnic_wq_service(struct vnic_wq *wq,
 void vnic_wq_free(struct vnic_wq *wq);
 int vnic_wq_alloc(struct vnic_dev *vdev, struct vnic_wq *wq, unsigned int index,
 	unsigned int desc_count, unsigned int desc_size);
+void vnic_wq_init_start(struct vnic_wq *wq, unsigned int cq_index,
+	unsigned int fetch_index, unsigned int posted_index,
+	unsigned int error_interrupt_enable,
+	unsigned int error_interrupt_offset);
 void vnic_wq_init(struct vnic_wq *wq, unsigned int cq_index,
 	unsigned int error_interrupt_enable,
 	unsigned int error_interrupt_offset);


^ permalink raw reply related

* Re: [PATCH NEXT 1/3] netxen: fix lro buffer allocation
From: David Miller @ 2009-09-04  3:06 UTC (permalink / raw)
  To: dhananjay; +Cc: davem, netdev, dhananjay
In-Reply-To: <1252019455-30683-1-git-send-email-dhananjay@netxen.com>

From: Dhananjay Phadke <dhananjay@netxen.com>
Date: Thu,  3 Sep 2009 16:10:53 -0700

> From: Dhananjay Phadke <dhananjay@qlogic.com>
> 
> Alloc 12k skbuffs so that firmware can aggregate more
> packets into one buffer. This doesn't raise memory
> consumption since 9k skbs use 16k slab cache anyway.
> 
> Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>

Applied.  But allocating such huge linear buffers is asking for
guarenteed trouble.  Can't you split them up into page sized chunks
with this chip?

^ permalink raw reply

* Re: [PATCH NEXT 2/3] netxen: remove duplicate napi_add
From: David Miller @ 2009-09-04  3:07 UTC (permalink / raw)
  To: dhananjay; +Cc: davem, netdev
In-Reply-To: <1252019455-30683-2-git-send-email-dhananjay@netxen.com>

From: Dhananjay Phadke <dhananjay@netxen.com>
Date: Thu,  3 Sep 2009 16:10:54 -0700

> Remove duplicate calls to netxen_napi_add().
> 
> Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>

Applied, but:

> @@ -2038,8 +2034,6 @@ netxen_remove_sysfs_entries(struct netxen_adapter *adapter)
>  		device_remove_file(dev, &dev_attr_bridged_mode);
>  }
>  
> -static void netxen_watchdog(unsigned long);
> -
>  #ifdef CONFIG_INET
>  
>  #define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops)

Give me a friggin' break, really.

If you're going to slip unrelated cleanups like this into your
patches, at least DOCUMENT them in the commit message.

^ permalink raw reply

* Re: [PATCH NEXT 3/3] netxen: fix infinite loop on dma mapping failure
From: David Miller @ 2009-09-04  3:07 UTC (permalink / raw)
  To: dhananjay; +Cc: davem, netdev
In-Reply-To: <1252019455-30683-3-git-send-email-dhananjay@netxen.com>

From: Dhananjay Phadke <dhananjay@netxen.com>
Date: Thu,  3 Sep 2009 16:10:55 -0700

> Fix a perpetual while() loop in unwinding partial
> mapped tx skb on dma mapping failure.
> 
> Reported-by: "Juha Leppanen" <juha_motorsportcom@luukku.com>
> Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>

Applied.

^ permalink raw reply

* Re: [net-next PATCH 1/3] igb: add support for set_rx_mode netdevice operation
From: David Miller @ 2009-09-04  3:07 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
In-Reply-To: <20090904004828.14537.72187.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:48:56 -0700

> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> This patch adds support for the set_rx_mode netdevice operation so that igb
> can better support multiple unicast addresses.
> 
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-next PATCH 2/3] igb: only disable/enable interrupt bits for igb physical function
From: David Miller @ 2009-09-04  3:07 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
In-Reply-To: <20090904004914.14537.67180.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:49:15 -0700

> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> The igb_irq_disable/enable calls were causing virtual functions associated
> with the igb physical function to have their interrupts disabled.  In order
> to prevent this from occuring we should only clear/set the bits related to
> the physical function.
> 
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-next PATCH 3/3] igb: set vf rlpml wasn't taking vlan tag into account
From: David Miller @ 2009-09-04  3:07 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, alexander.h.duyck
In-Reply-To: <20090904004932.14537.49991.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:49:33 -0700

> From: Alexander Duyck <alexander.h.duyck@intel.com>
> 
> This patch updates things so that vlan tags are taken into account when
> setting the receive large packet maximum length.  This allows the VF driver
> to correctly receive full sized frames when vlans are enabled.
> 
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-next PATCH 1/3] ixgbe: Add support for multiple Tx queues for FCoE in 82599
From: David Miller @ 2009-09-04  3:08 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, yi.zou
In-Reply-To: <20090904005549.14869.66878.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:55:50 -0700

> From: Yi Zou <yi.zou@intel.com>
> 
> This patch adds support for multiple transmit queues to the Fiber Channel
> over Ethernet (FCoE) feature found in 82599. Currently, FCoE has multiple
> Rx queues available, along with a redirection table, that helps distribute
> the I/O load across multiple CPUs based on the FC exchange ID. To make
> this the most effective, we need to provide the same layout of transmit
> queues to match receive.
> 
> Particularly, when Data Center Bridging (DCB) is enabled, the designated
> traffic class for FCoE can have dedicated queues for just FCoE traffic,
> while not affecting any other type of traffic flow.
> 
> Signed-off-by: Yi Zou <yi.zou@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

So does this eat into the TX queues available to non-FCOE traffic
or is this a shared setup?

^ permalink raw reply

* Re: [net-next PATCH 2/3] ixgbe: Distribute transmission of FCoE traffic in 82599
From: David Miller @ 2009-09-04  3:09 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, yi.zou
In-Reply-To: <20090904005609.14869.89202.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:56:10 -0700

> From: Yi Zou <yi.zou@intel.com>
> 
> This adds a simple selection of a FCoE tx queue based on the current cpu id to
> distribute transmission of FCoE traffic evenly among multiple FCoE transmit
> queues.
> 
> Signed-off-by: Yi Zou <yi.zou@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

Does it matter that arbitrary programs or other stacks could transmit
ETH_P_FCOE traffic as well?  Would that interfere with how this offload
hardware works now that you're directing all ETH_P_FCOE traffic to
FCOE rings?

^ permalink raw reply

* Re: [net-next PATCH 3/3] ixgbe: Add support for using FCoE DDP in 82599 as FCoE targets
From: David Miller @ 2009-09-04  3:09 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, yi.zou
In-Reply-To: <20090904005630.14869.67340.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Thu, 03 Sep 2009 17:56:31 -0700

> From: Yi Zou <yi.zou@intel.com>
> 
> The FCoE DDP in 82599 can be used for both FCoE initiator as well as FCoE
> target, depending on the indication of the exchange being the responder or
> originator in the F_CTL (frame control) field in the encapsulated Fiber
> Channel frame header (T10 Spec., FC-FS). For the initiator, OX_ID is used
> for FCoE DDP, where for the target RX_ID is used for FCoE DDP.
> 
> Signed-off-by: Yi Zou <yi.zou@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/3] netdev: Remove SIOCDEVPRIVATE aliases for MDIO ioctls
From: David Miller @ 2009-09-04  3:09 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev
In-Reply-To: <1252010313.2781.14.camel@achroite>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Thu, 03 Sep 2009 21:38:33 +0100

> The standard MDIO ioctl numbers are well-established and these should
> no longer be needed.
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/3] netdev: Remove redundant checks for CAP_NET_ADMIN in MDIO implementations
From: David Miller @ 2009-09-04  3:10 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers
In-Reply-To: <1252010383.2781.17.camel@achroite>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Thu, 03 Sep 2009 21:39:43 +0100

> dev_ioctl() already checks capable(CAP_NET_ADMIN) before calling the
> driver's implementation of MDIO ioctls.
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Man, it wasn't fun validating the cases where you removed the
check function-wide for a ->ndo_dev_ioctl() implementation. :-/

Applied...

^ permalink raw reply

* Re: [PATCH 3/3] netdev: Convert MDIO ioctl implementation to use struct mii_ioctl_data
From: David Miller @ 2009-09-04  3:10 UTC (permalink / raw)
  To: bhutchings; +Cc: netdev, linux-net-drivers
In-Reply-To: <1252010477.2781.20.camel@achroite>

From: Ben Hutchings <bhutchings@solarflare.com>
Date: Thu, 03 Sep 2009 21:41:17 +0100

> A few drivers still access the arguments to MDIO ioctls as an array of
> u16.  Convert them to use struct mii_ioctl_data.
> 
> Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>

Applied.

^ permalink raw reply

* Re: [PATCH] sky2: only enable Vaux if capable of wakeup
From: David Miller @ 2009-09-04  3:10 UTC (permalink / raw)
  To: shemminger; +Cc: rene.mayrhofer, mikem, netdev, leitner
In-Reply-To: <20090903091625.2e6aff91@nehalam>

From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Thu, 3 Sep 2009 09:16:25 -0700

> While perusing vendor driver, I saw that it did not enable the Vaux
> power unless device was able to wake from lan for D3cold.
> This might help for Rene's power issue.
> 
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next-2.6] macvlan: add multiqueue capability
From: David Miller @ 2009-09-04  3:10 UTC (permalink / raw)
  To: eric.dumazet; +Cc: kaber, netdev
In-Reply-To: <4A9F9661.7020301@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 03 Sep 2009 12:11:45 +0200

> macvlan devices are currently not multi-queue capable.
> 
> We can do that defining rtnl_link_ops method,
> get_tx_queues(), called from rtnl_create_link()
> 
> This new method gets num_tx_queues/real_num_tx_queues
> from lower device.
> 
> macvlan_get_tx_queues() is a copy of vlan_get_tx_queues().
> 
> Because macvlan_start_xmit() has to update netdev_queue
> stats only (and not dev->stats), I chose to change
> tx_errors/tx_aborted_errors accounting to tx_dropped,
> since netdev_queue structure doesnt define tx_errors /
> tx_aborted_errors.
> 
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next-2.6] vlan: adds drops accounting
From: David Miller @ 2009-09-04  3:11 UTC (permalink / raw)
  To: eric.dumazet; +Cc: kaber, netdev
In-Reply-To: <4A9F9CD4.7040408@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 03 Sep 2009 12:39:16 +0200

> Its hard to tell if vlans are dropping frames, since
> every frame given to vlan_???_start_xmit() functions
> is accounted as fully transmitted by lower device.
> 
> We can test dev_queue_xmit() return values to
> properly account for dropped frames.
> 
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>

Applied.

But, how inappropriate would it be to keep doing the accounting
but pass the status back to the caller?  Or will that screw up
the qdisc running engine?

^ permalink raw reply

* [net-next PATCH 04/11] enic: use netdev_alloc_skb
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: use netdev_alloc_skb

Use netdev_alloc_skb rather than dev_alloc_skb

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic_main.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index a9e9be1..d77119a 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -868,11 +868,12 @@ static void enic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf)
 	dev_kfree_skb_any(buf->os_buf);
 }
 
-static inline struct sk_buff *enic_rq_alloc_skb(unsigned int size)
+static inline struct sk_buff *enic_rq_alloc_skb(struct net_device *netdev,
+	unsigned int size)
 {
 	struct sk_buff *skb;
 
-	skb = dev_alloc_skb(size + NET_IP_ALIGN);
+	skb = netdev_alloc_skb(netdev, size + NET_IP_ALIGN);
 
 	if (skb)
 		skb_reserve(skb, NET_IP_ALIGN);
@@ -883,12 +884,13 @@ static inline struct sk_buff *enic_rq_alloc_skb(unsigned int size)
 static int enic_rq_alloc_buf(struct vnic_rq *rq)
 {
 	struct enic *enic = vnic_dev_priv(rq->vdev);
+	struct net_device *netdev = enic->netdev;
 	struct sk_buff *skb;
-	unsigned int len = enic->netdev->mtu + ETH_HLEN;
+	unsigned int len = netdev->mtu + ETH_HLEN;
 	unsigned int os_buf_index = 0;
 	dma_addr_t dma_addr;
 
-	skb = enic_rq_alloc_skb(len);
+	skb = enic_rq_alloc_skb(netdev, len);
 	if (!skb)
 		return -ENOMEM;
 


^ permalink raw reply related

* [net-next PATCH 03/11] enic: bug fix: split TSO fragments larger than 16K into multiple descs
From: Scott Feldman @ 2009-09-04  3:02 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

enic: bug fix: split TSO fragments larger than 16K into multiple descs

enic WQ desc supports a maximum 16K buf size, so split any send fragments
larger than 16K into several descs.

Signed-off-by: Scott Feldman <scofeldm@cisco.com>
---
 drivers/net/enic/enic_main.c |   87 +++++++++++++++++++++++++++++++++---------
 1 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 3d7838d..a9e9be1 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -44,10 +44,15 @@
 #include "enic.h"
 
 #define ENIC_NOTIFY_TIMER_PERIOD	(2 * HZ)
+#define WQ_ENET_MAX_DESC_LEN		(1 << WQ_ENET_LEN_BITS)
+#define MAX_TSO				(1 << 16)
+#define ENIC_DESC_MAX_SPLITS		(MAX_TSO / WQ_ENET_MAX_DESC_LEN + 1)
+
+#define PCI_DEVICE_ID_CISCO_VIC_ENET         0x0043  /* ethernet vnic */
 
 /* Supported devices */
 static struct pci_device_id enic_id_table[] = {
-	{ PCI_VDEVICE(CISCO, 0x0043) },
+	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
 	{ 0, }	/* end of table */
 };
 
@@ -310,7 +315,8 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
 		opaque);
 
 	if (netif_queue_stopped(enic->netdev) &&
-	    vnic_wq_desc_avail(&enic->wq[q_number]) >= MAX_SKB_FRAGS + 1)
+	    vnic_wq_desc_avail(&enic->wq[q_number]) >=
+	    (MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS))
 		netif_wake_queue(enic->netdev);
 
 	spin_unlock(&enic->wq_lock[q_number]);
@@ -525,7 +531,11 @@ static inline void enic_queue_wq_skb_vlan(struct enic *enic,
 	unsigned int len_left = skb->len - head_len;
 	int eop = (len_left == 0);
 
-	/* Queue the main skb fragment */
+	/* Queue the main skb fragment. The fragments are no larger
+	 * than max MTU(9000)+ETH_HDR_LEN(14) bytes, which is less
+	 * than WQ_ENET_MAX_DESC_LEN length. So only one descriptor
+	 * per fragment is queued.
+	 */
 	enic_queue_wq_desc(wq, skb,
 		pci_map_single(enic->pdev, skb->data,
 			head_len, PCI_DMA_TODEVICE),
@@ -547,7 +557,11 @@ static inline void enic_queue_wq_skb_csum_l4(struct enic *enic,
 	unsigned int csum_offset = hdr_len + skb->csum_offset;
 	int eop = (len_left == 0);
 
-	/* Queue the main skb fragment */
+	/* Queue the main skb fragment. The fragments are no larger
+	 * than max MTU(9000)+ETH_HDR_LEN(14) bytes, which is less
+	 * than WQ_ENET_MAX_DESC_LEN length. So only one descriptor
+	 * per fragment is queued.
+	 */
 	enic_queue_wq_desc_csum_l4(wq, skb,
 		pci_map_single(enic->pdev, skb->data,
 			head_len, PCI_DMA_TODEVICE),
@@ -565,10 +579,14 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic,
 	struct vnic_wq *wq, struct sk_buff *skb, unsigned int mss,
 	int vlan_tag_insert, unsigned int vlan_tag)
 {
-	unsigned int head_len = skb_headlen(skb);
-	unsigned int len_left = skb->len - head_len;
+	unsigned int frag_len_left = skb_headlen(skb);
+	unsigned int len_left = skb->len - frag_len_left;
 	unsigned int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int eop = (len_left == 0);
+	unsigned int len;
+	dma_addr_t dma_addr;
+	unsigned int offset = 0;
+	skb_frag_t *frag;
 
 	/* Preload TCP csum field with IP pseudo hdr calculated
 	 * with IP length set to zero.  HW will later add in length
@@ -584,17 +602,49 @@ static inline void enic_queue_wq_skb_tso(struct enic *enic,
 			&ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
 	}
 
-	/* Queue the main skb fragment */
-	enic_queue_wq_desc_tso(wq, skb,
-		pci_map_single(enic->pdev, skb->data,
-			head_len, PCI_DMA_TODEVICE),
-		head_len,
-		mss, hdr_len,
-		vlan_tag_insert, vlan_tag,
-		eop);
+	/* Queue WQ_ENET_MAX_DESC_LEN length descriptors
+	 * for the main skb fragment
+	 */
+	while (frag_len_left) {
+		len = min(frag_len_left, (unsigned int)WQ_ENET_MAX_DESC_LEN);
+		dma_addr = pci_map_single(enic->pdev, skb->data + offset,
+				len, PCI_DMA_TODEVICE);
+		enic_queue_wq_desc_tso(wq, skb,
+			dma_addr,
+			len,
+			mss, hdr_len,
+			vlan_tag_insert, vlan_tag,
+			eop && (len == frag_len_left));
+		frag_len_left -= len;
+		offset += len;
+	}
 
-	if (!eop)
-		enic_queue_wq_skb_cont(enic, wq, skb, len_left);
+	if (eop)
+		return;
+
+	/* Queue WQ_ENET_MAX_DESC_LEN length descriptors
+	 * for additional data fragments
+	 */
+	for (frag = skb_shinfo(skb)->frags; len_left; frag++) {
+		len_left -= frag->size;
+		frag_len_left = frag->size;
+		offset = frag->page_offset;
+
+		while (frag_len_left) {
+			len = min(frag_len_left,
+				(unsigned int)WQ_ENET_MAX_DESC_LEN);
+			dma_addr = pci_map_page(enic->pdev, frag->page,
+				offset, len,
+				PCI_DMA_TODEVICE);
+			enic_queue_wq_desc_cont(wq, skb,
+				dma_addr,
+				len,
+				(len_left == 0) &&
+				(len == frag_len_left));	/* EOP? */
+			frag_len_left -= len;
+			offset += len;
+		}
+	}
 }
 
 static inline void enic_queue_wq_skb(struct enic *enic,
@@ -647,7 +697,8 @@ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 	spin_lock_irqsave(&enic->wq_lock[0], flags);
 
-	if (vnic_wq_desc_avail(wq) < skb_shinfo(skb)->nr_frags + 1) {
+	if (vnic_wq_desc_avail(wq) <
+	    skb_shinfo(skb)->nr_frags + ENIC_DESC_MAX_SPLITS) {
 		netif_stop_queue(netdev);
 		/* This is a hard error, log it */
 		printk(KERN_ERR PFX "%s: BUG! Tx ring full when "
@@ -658,7 +709,7 @@ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 	enic_queue_wq_skb(enic, wq, skb);
 
-	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + 1)
+	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
 		netif_stop_queue(netdev);
 
 	spin_unlock_irqrestore(&enic->wq_lock[0], flags);


^ permalink raw reply related

* RE: [PATCH NEXT 1/3] netxen: fix lro buffer allocation
From: Dhananjay Phadke @ 2009-09-04  3:14 UTC (permalink / raw)
  To: David Miller; +Cc: davem@davemloft.com, netdev@vger.kernel.org
In-Reply-To: <20090903.200615.220020629.davem@davemloft.net>

 

> Applied.  But allocating such huge linear buffers is asking for
> guarenteed trouble.  Can't you split them up into page sized chunks
> with this chip?

"chained" LRO is not enabled by firmware. Contiguous LRO requires
fewer commands (internal) from firmware to DMA engines.

-Dhananjay

^ permalink raw reply

* Re: [PATCH NEXT 1/3] netxen: fix lro buffer allocation
From: David Miller @ 2009-09-04  3:15 UTC (permalink / raw)
  To: dhananjay.phadke; +Cc: davem, netdev
In-Reply-To: <7608421F3572AB4292BB2532AE89D565865FA8A556@AVEXMB1.qlogic.org>

From: Dhananjay Phadke <dhananjay.phadke@qlogic.com>
Date: Thu, 3 Sep 2009 20:14:01 -0700

>  
> 
>> Applied.  But allocating such huge linear buffers is asking for
>> guarenteed trouble.  Can't you split them up into page sized chunks
>> with this chip?
> 
> "chained" LRO is not enabled by firmware. Contiguous LRO requires
> fewer commands (internal) from firmware to DMA engines.

But if the page allocator can't satisfy allocation requests
it doesn't matter how many microseconds you're saving here.

I think you're priorities are backwards.

^ permalink raw reply

* Re: [net-next PATCH 00/11] enic: updates
From: David Miller @ 2009-09-04  3:23 UTC (permalink / raw)
  To: scofeldm; +Cc: netdev
In-Reply-To: <20090904030046.5047.46509.stgit@palito_client100.nuovasystems.com>

From: Scott Feldman <scofeldm@cisco.com>
Date: Thu, 03 Sep 2009 20:01:43 -0700

> The following series implements updates to the enic netdev driver for
> Cisco's 10G Ethernet NIC:
> 
>       01 enic: add support for multiple BARs
>       02 enic: workaround A0 erratum
>       03 enic: bug fix: split TSO fragments larger than 16K into
>          multiple descs
>       04 enic: use netdev_alloc_skb
>       05 enic: bug fix: protect fw call i/f with spinlock
>       06 enic: bug fix: included MAC drops in rx_dropped netstat
>       07 enic: provision for multiple Rx/Tx queues; prepare for RSS support
>       08 enic: bug fix: enable VLAN filtering
>       09 enic: changes to driver/firmware interface
>       10 enic: bug fix: check for zero port MTU before posting warning
>       11 enic: organize device initialization/deinit into separate functions
> 
> Please apply.
> 
> Signed-off-by: Scott Feldman <scofeldm@cisco.com>

Looks good, all aplied, thanks!

^ 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