netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests
@ 2010-02-01 15:24 Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 1/7] qlcnic: use DEFINE_PCI_DEVICE_TABLE Amit Kumar Salecha
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman

Hi
  Series of 7 patches to add diagnostic test, device identification support and bug fixes.
  These are v2 patches, please ignore previous patches.
  Apply them in net-next-2.6 tree.

Thanks
Amit Salecha

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

* [PATCHv2 NEXT 1/7] qlcnic: use DEFINE_PCI_DEVICE_TABLE
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 2/7] qlcnic: add ethernet identifier in board info Amit Kumar Salecha
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman

Use DEFINE_PCI_DEVICE_TABLE() so we get place PCI ids table into
correct section in every case.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 1698b6a..05275f2 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -102,7 +102,7 @@ static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
 
 #define PCI_DEVICE_ID_QLOGIC_QLE824X  0x8020
 
-static const struct pci_device_id qlcnic_pci_tbl[] __devinitdata = {
+static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
 	ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
 	{0,}
 };
-- 
1.6.0.2


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

* [PATCHv2 NEXT 2/7] qlcnic: add ethernet identifier in board info
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 1/7] qlcnic: use DEFINE_PCI_DEVICE_TABLE Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 3/7] qlcnic: clear device reset state after fw recovery Amit Kumar Salecha
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman, Rajesh K Borundia

Added missing identifier that distinguishes between
FCOE/ISCSI/ETHERNET functions.

Signed-off-by: Rajesh K Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index abec468..9662a37 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1068,7 +1068,7 @@ int qlcnic_reset_context(struct qlcnic_adapter *);
  * QLOGIC Board information
  */
 
-#define QLCNIC_MAX_BOARD_NAME_LEN 64
+#define QLCNIC_MAX_BOARD_NAME_LEN 100
 struct qlcnic_brdinfo {
 	unsigned short  vendor;
 	unsigned short  device;
@@ -1078,8 +1078,12 @@ struct qlcnic_brdinfo {
 };
 
 static const struct qlcnic_brdinfo qlcnic_boards[] = {
-	{0x1077, 0x8020, 0x1077, 0x203, "8200 Series Single Port 10GbE CNA"},
-	{0x1077, 0x8020, 0x1077, 0x207, "8200 Series Dual Port 10GbE CNA"},
+	{0x1077, 0x8020, 0x1077, 0x203,
+		"8200 Series Single Port 10GbE Converged Network Adapter \
+		(TCP/IP Networking)"},
+	{0x1077, 0x8020, 0x1077, 0x207,
+		"8200 Series Dual Port 10GbE Converged Network Adapter \
+		(TCP/IP Networking)"},
 	{0x1077, 0x8020, 0x1077, 0x20b,
 		"3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
 	{0x1077, 0x8020, 0x1077, 0x20c,
-- 
1.6.0.2


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

* [PATCHv2 NEXT 3/7] qlcnic: clear device reset state after fw recovery
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 1/7] qlcnic: use DEFINE_PCI_DEVICE_TABLE Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 2/7] qlcnic: add ethernet identifier in board info Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 4/7] qlcnic: protect resoruce cleanup by rtnl lock Amit Kumar Salecha
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman

o After firmware recovery, clear device reset state transition register.
  Otherwise firmware reload can occur unnecessary.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_main.c |   22 +++++++++++++++++++++-
 1 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 05275f2..9a98285 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1866,6 +1866,23 @@ qlcnic_set_drv_state(struct qlcnic_adapter *adapter, int state)
 	qlcnic_api_unlock(adapter);
 }
 
+static int
+qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
+{
+	u32  val;
+
+	if (qlcnic_api_lock(adapter))
+		return -EBUSY;
+
+	val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE);
+	val &= ~((u32)0x3 << (adapter->portnum * 4));
+	QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val);
+
+	qlcnic_api_unlock(adapter);
+
+	return 0;
+}
+
 static void
 qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter)
 {
@@ -2119,7 +2136,10 @@ qlcnic_attach_work(struct work_struct *work)
 done:
 	adapter->fw_fail_cnt = 0;
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
-	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+
+	if (!qlcnic_clr_drv_state(adapter))
+		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+							FW_POLL_DELAY);
 }
 
 static int
-- 
1.6.0.2


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

* [PATCHv2 NEXT 4/7] qlcnic: protect resoruce cleanup by rtnl lock
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
                   ` (2 preceding siblings ...)
  2010-02-01 15:24 ` [PATCHv2 NEXT 3/7] qlcnic: clear device reset state after fw recovery Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 5/7] qlcnic: support LED blink for device identification Amit Kumar Salecha
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman

o context resources can be in used, while resoruce cleanup is in progress,
  during fw recover.
o Null pointer execption can occur in send_cmd_desc, if fw recovery
  module frees tx ring without rtnl lock.
o Same applies to ethtool register dump and FW health registers should be dump
  in any case.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_ethtool.c |    6 +++---
 drivers/net/qlcnic/qlcnic_main.c    |    2 ++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 65e9620..37df5f6 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -326,12 +326,12 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 	    (adapter->pdev)->device;
 
-	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
-		return;
-
 	for (i = 0; diag_registers[i] != -1; i++)
 		regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
 
+	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+		return;
+
 	regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
 
 	regs_buff[i++] = 1; /* No. of tx ring */
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 9a98285..7259adc 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2051,7 +2051,9 @@ qlcnic_detach_work(struct work_struct *work)
 
 	qlcnic_down(adapter, netdev);
 
+	rtnl_lock();
 	qlcnic_detach(adapter);
+	rtnl_unlock();
 
 	status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1);
 
-- 
1.6.0.2


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

* [PATCHv2 NEXT 5/7] qlcnic: support LED blink for device identification
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
                   ` (3 preceding siblings ...)
  2010-02-01 15:24 ` [PATCHv2 NEXT 4/7] qlcnic: protect resoruce cleanup by rtnl lock Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:24 ` [PATCHv2 NEXT 6/7] qlcnic: add interrupt diagnostic test Amit Kumar Salecha
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem
  Cc: netdev, dhananjay.phadke, ameen.rahman, Sucheta Chakraborty,
	Sucheta Chakraborty

From: Sucheta Chakraborty <sucheta@dut6195.unminc.com>

Added support of device identification by blinking LED for specified time.

Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h         |    1 +
 drivers/net/qlcnic/qlcnic_ethtool.c |   26 ++++++++++++++++++++++++++
 drivers/net/qlcnic/qlcnic_hw.c      |   22 ++++++++++++++++++++++
 3 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9662a37..514e805 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1015,6 +1015,7 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
 
 int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
 int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
+int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
 
 /* Functions from qlcnic_init.c */
 int qlcnic_phantom_init(struct qlcnic_adapter *adapter);
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 37df5f6..7212319 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -618,6 +618,7 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 		     u64 *data)
 {
 	memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
+
 	data[0] = qlcnic_reg_test(dev);
 	if (data[0])
 		eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -693,6 +694,30 @@ static int qlcnic_set_tso(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static int qlcnic_blink_led(struct net_device *dev, u32 val)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(dev);
+	int ret;
+
+	ret = qlcnic_config_led(adapter, 1, 0xf);
+	if (ret) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to set LED blink state.\n");
+		return ret;
+	}
+
+	msleep_interruptible(val * 1000);
+
+	ret = qlcnic_config_led(adapter, 0, 0xf);
+	if (ret) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to reset LED blink state.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static void
 qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
@@ -867,4 +892,5 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
 	.set_coalesce = qlcnic_set_intr_coalesce,
 	.get_flags = ethtool_op_get_flags,
 	.set_flags = qlcnic_set_flags,
+	.phys_id = qlcnic_blink_led,
 };
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 91234e7..8724e56 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -1199,3 +1199,25 @@ qlcnic_wol_supported(struct qlcnic_adapter *adapter)
 
 	return 0;
 }
+
+int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
+{
+	struct qlcnic_nic_req   req;
+	int rv;
+	u64 word;
+
+	memset(&req, 0, sizeof(struct qlcnic_nic_req));
+	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+	word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16);
+	req.req_hdr = cpu_to_le64(word);
+
+	req.words[0] = cpu_to_le64((u64)rate << 32);
+	req.words[1] = cpu_to_le64(state);
+
+	rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv)
+		dev_err(&adapter->pdev->dev, "LED configuration failed.\n");
+
+	return rv;
+}
-- 
1.6.0.2


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

* [PATCHv2 NEXT 6/7] qlcnic: add interrupt diagnostic test
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
                   ` (4 preceding siblings ...)
  2010-02-01 15:24 ` [PATCHv2 NEXT 5/7] qlcnic: support LED blink for device identification Amit Kumar Salecha
@ 2010-02-01 15:24 ` Amit Kumar Salecha
  2010-02-01 15:25 ` [PATCHv2 NEXT 7/7] qlcnic: add loppback " Amit Kumar Salecha
  2010-02-03  0:00 ` [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:24 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman, Sucheta Chakraborty

Interrupt test (offline) added in ethtool self test.
Register a temporary interrupt handler and then send command to fw
to raise an interrupt.

Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h         |   13 ++++-
 drivers/net/qlcnic/qlcnic_ctx.c     |    4 +-
 drivers/net/qlcnic/qlcnic_ethtool.c |   41 ++++++++++++-
 drivers/net/qlcnic/qlcnic_main.c    |  112 +++++++++++++++++++++++++++++++---
 4 files changed, 154 insertions(+), 16 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 514e805..a5a67e9 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -560,6 +560,8 @@ struct qlcnic_recv_context {
 /*
  * Context state
  */
+#define QLCHAL_VERSION	1
+
 #define QLCNIC_HOST_CTX_STATE_ACTIVE	2
 
 /*
@@ -894,6 +896,8 @@ struct qlcnic_mac_req {
 #define __QLCNIC_RESETTING		2
 #define __QLCNIC_START_FW 		4
 
+#define QLCNIC_INTERRUPT_TEST		1
+
 struct qlcnic_adapter {
 	struct qlcnic_hardware_context ahw;
 
@@ -946,9 +950,10 @@ struct qlcnic_adapter {
 	u32 heartbit;
 
 	u8 dev_state;
+	u8 diag_test;
+	u8 diag_cnt;
 	u8 rsrd1;
-	u32 rsrd2;
-
+	u16 rsrd2;
 
 	u8 mac_addr[ETH_ALEN];
 
@@ -1064,6 +1069,10 @@ int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac);
 
 /* Functions from qlcnic_main.c */
 int qlcnic_reset_context(struct qlcnic_adapter *);
+u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
+	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
+void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
+int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
 
 /*
  * QLOGIC Board information
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index 71c16a1..0a6a399 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -24,8 +24,6 @@
 
 #include "qlcnic.h"
 
-#define QLCHAL_VERSION	1
-
 static u32
 qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
 {
@@ -45,7 +43,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
 	return rsp;
 }
 
-static u32
+u32
 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
 {
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 7212319..58c50ed 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -65,7 +65,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
 
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register_Test_on_offline",
-	"Link_Test_on_offline"
+	"Link_Test_on_offline",
+	"Interrupt_Test_offline"
 };
 
 #define QLCNIC_TEST_LEN	ARRAY_SIZE(qlcnic_gstrings_test)
@@ -613,12 +614,50 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 	}
 }
 
+static int qlcnic_irq_test(struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	int max_sds_rings = adapter->max_sds_rings;
+	int ret;
+
+	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+		return -EIO;
+
+	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
+	if (ret)
+		goto clear_it;
+
+	adapter->diag_cnt = 0;
+	ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func,
+			QLCHAL_VERSION, adapter->portnum, 0, 0, 0x00000011);
+	if (ret)
+		goto done;
+
+	msleep(10);
+
+	ret = !adapter->diag_cnt;
+
+done:
+	qlcnic_diag_free_res(netdev, max_sds_rings);
+
+clear_it:
+	adapter->max_sds_rings = max_sds_rings;
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	return ret;
+}
+
 static void
 qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 		     u64 *data)
 {
 	memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
 
+	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
+		data[2] = qlcnic_irq_test(dev);
+		if (data[2])
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+	}
+
 	data[0] = qlcnic_reg_test(dev);
 	if (data[0])
 		eth_test->flags |= ETH_TEST_FL_FAILED;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 7259adc..a8b0712 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -88,6 +88,7 @@ static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
 static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter);
 static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
 
+static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
 static irqreturn_t qlcnic_intr(int irq, void *data);
 static irqreturn_t qlcnic_msi_intr(int irq, void *data);
 static irqreturn_t qlcnic_msix_intr(int irq, void *data);
@@ -720,13 +721,20 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
 
-	if (adapter->flags & QLCNIC_MSIX_ENABLED)
-		handler = qlcnic_msix_intr;
-	else if (adapter->flags & QLCNIC_MSI_ENABLED)
-		handler = qlcnic_msi_intr;
-	else {
-		flags |= IRQF_SHARED;
-		handler = qlcnic_intr;
+	if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+		handler = qlcnic_tmp_intr;
+		if (!QLCNIC_IS_MSI_FAMILY(adapter))
+			flags |= IRQF_SHARED;
+
+	} else {
+		if (adapter->flags & QLCNIC_MSIX_ENABLED)
+			handler = qlcnic_msix_intr;
+		else if (adapter->flags & QLCNIC_MSI_ENABLED)
+			handler = qlcnic_msi_intr;
+		else {
+			flags |= IRQF_SHARED;
+			handler = qlcnic_intr;
+		}
 	}
 	adapter->irq = netdev->irq;
 
@@ -923,6 +931,60 @@ qlcnic_detach(struct qlcnic_adapter *adapter)
 	adapter->is_up = 0;
 }
 
+void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_host_sds_ring *sds_ring;
+	int ring;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &adapter->recv_ctx.sds_rings[ring];
+		qlcnic_disable_int(sds_ring);
+	}
+
+	qlcnic_detach(adapter);
+
+	adapter->diag_test = 0;
+	adapter->max_sds_rings = max_sds_rings;
+
+	if (qlcnic_attach(adapter))
+		return;
+
+	if (netif_running(netdev))
+		__qlcnic_up(adapter, netdev);
+
+	netif_device_attach(netdev);
+}
+
+int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_host_sds_ring *sds_ring;
+	int ring;
+	int ret;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		__qlcnic_down(adapter, netdev);
+
+	qlcnic_detach(adapter);
+
+	adapter->max_sds_rings = 1;
+	adapter->diag_test = test;
+
+	ret = qlcnic_attach(adapter);
+	if (ret)
+		return ret;
+
+	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+		sds_ring = &adapter->recv_ctx.sds_rings[ring];
+		qlcnic_enable_int(sds_ring);
+	}
+
+	return 0;
+}
+
 int
 qlcnic_reset_context(struct qlcnic_adapter *adapter)
 {
@@ -1689,10 +1751,8 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
 	return stats;
 }
 
-static irqreturn_t qlcnic_intr(int irq, void *data)
+static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
 {
-	struct qlcnic_host_sds_ring *sds_ring = data;
-	struct qlcnic_adapter *adapter = sds_ring->adapter;
 	u32 status;
 
 	status = readl(adapter->isr_int_vec);
@@ -1710,6 +1770,38 @@ static irqreturn_t qlcnic_intr(int irq, void *data)
 	readl(adapter->isr_int_vec);
 	readl(adapter->isr_int_vec);
 
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
+{
+	struct qlcnic_host_sds_ring *sds_ring = data;
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+	if (adapter->flags & QLCNIC_MSIX_ENABLED)
+		goto done;
+	else if (adapter->flags & QLCNIC_MSI_ENABLED) {
+		writel(0xffffffff, adapter->tgt_status_reg);
+		goto done;
+	}
+
+	if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+		return IRQ_NONE;
+
+done:
+	adapter->diag_cnt++;
+	qlcnic_enable_int(sds_ring);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t qlcnic_intr(int irq, void *data)
+{
+	struct qlcnic_host_sds_ring *sds_ring = data;
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+	if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+		return IRQ_NONE;
+
 	napi_schedule(&sds_ring->napi);
 
 	return IRQ_HANDLED;
-- 
1.6.0.2


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

* [PATCHv2 NEXT 7/7] qlcnic: add loppback diagnostic test
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
                   ` (5 preceding siblings ...)
  2010-02-01 15:24 ` [PATCHv2 NEXT 6/7] qlcnic: add interrupt diagnostic test Amit Kumar Salecha
@ 2010-02-01 15:25 ` Amit Kumar Salecha
  2010-02-03  0:00 ` [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: Amit Kumar Salecha @ 2010-02-01 15:25 UTC (permalink / raw)
  To: davem; +Cc: netdev, dhananjay.phadke, ameen.rahman

Loopback test (offline) added in ethtool self test.
o Set device in loopback mode
o Send packets
o Process receive packets in qlcnic_process_rcv_ring_diag()
o Compare packets
o Reset device in normal mode.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h         |    6 +++
 drivers/net/qlcnic/qlcnic_ethtool.c |   82 ++++++++++++++++++++++++++++++++++-
 drivers/net/qlcnic/qlcnic_hw.c      |   52 ++++++++++++++++++++++
 drivers/net/qlcnic/qlcnic_init.c    |   75 ++++++++++++++++++++++++++++++++
 drivers/net/qlcnic/qlcnic_main.c    |   20 +++++----
 5 files changed, 225 insertions(+), 10 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index a5a67e9..b40a851 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -897,6 +897,7 @@ struct qlcnic_mac_req {
 #define __QLCNIC_START_FW 		4
 
 #define QLCNIC_INTERRUPT_TEST		1
+#define QLCNIC_LOOPBACK_TEST		2
 
 struct qlcnic_adapter {
 	struct qlcnic_hardware_context ahw;
@@ -1066,6 +1067,8 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
 void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
 		struct qlcnic_host_tx_ring *tx_ring);
 int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac);
+void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
+int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
 
 /* Functions from qlcnic_main.c */
 int qlcnic_reset_context(struct qlcnic_adapter *);
@@ -1073,6 +1076,9 @@ u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd);
 void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
 int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
+int qlcnic_check_loopback_buff(unsigned char *data);
+netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
 
 /*
  * QLOGIC Board information
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 58c50ed..8da6ec8 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -66,7 +66,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 	"Register_Test_on_offline",
 	"Link_Test_on_offline",
-	"Interrupt_Test_offline"
+	"Interrupt_Test_offline",
+	"Loopback_Test_offline"
 };
 
 #define QLCNIC_TEST_LEN	ARRAY_SIZE(qlcnic_gstrings_test)
@@ -614,6 +615,80 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 	}
 }
 
+#define QLC_ILB_PKT_SIZE 64
+
+static void qlcnic_create_loopback_buff(unsigned char *data)
+{
+	unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
+	memset(data, 0x4e, QLC_ILB_PKT_SIZE);
+	memset(data, 0xff, 12);
+	memcpy(data + 12, random_data, sizeof(random_data));
+}
+
+int qlcnic_check_loopback_buff(unsigned char *data)
+{
+	unsigned char buff[QLC_ILB_PKT_SIZE];
+	qlcnic_create_loopback_buff(buff);
+	return memcmp(data, buff, QLC_ILB_PKT_SIZE);
+}
+
+static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+	struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
+	struct sk_buff *skb;
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
+		qlcnic_create_loopback_buff(skb->data);
+		skb_put(skb, QLC_ILB_PKT_SIZE);
+
+		adapter->diag_cnt = 0;
+
+		qlcnic_xmit_frame(skb, adapter->netdev);
+
+		msleep(5);
+
+		qlcnic_process_rcv_ring_diag(sds_ring);
+
+		dev_kfree_skb_any(skb);
+		if (!adapter->diag_cnt)
+			return -1;
+	}
+	return 0;
+}
+
+static int qlcnic_loopback_test(struct net_device *netdev)
+{
+	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	int max_sds_rings = adapter->max_sds_rings;
+	int ret;
+
+	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
+		return -EIO;
+
+	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
+	if (ret)
+		goto clear_it;
+
+	ret = qlcnic_set_ilb_mode(adapter);
+	if (ret)
+		goto done;
+
+	ret = qlcnic_do_ilb_test(adapter);
+
+	qlcnic_clear_ilb_mode(adapter);
+
+done:
+	qlcnic_diag_free_res(netdev, max_sds_rings);
+
+clear_it:
+	adapter->max_sds_rings = max_sds_rings;
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	return ret;
+}
+
 static int qlcnic_irq_test(struct net_device *netdev)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -656,6 +731,11 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 		data[2] = qlcnic_irq_test(dev);
 		if (data[2])
 			eth_test->flags |= ETH_TEST_FL_FAILED;
+
+		data[3] = qlcnic_loopback_test(dev);
+		if (data[3])
+			eth_test->flags |= ETH_TEST_FL_FAILED;
+
 	}
 
 	data[0] = qlcnic_reg_test(dev);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 8724e56..dc6cd69 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -1221,3 +1221,55 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
 
 	return rv;
 }
+
+static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u32 flag)
+{
+	struct qlcnic_nic_req	req;
+	int			rv;
+	u64			word;
+
+	memset(&req, 0, sizeof(struct qlcnic_nic_req));
+	req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
+
+	word = QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK |
+			((u64)adapter->portnum << 16);
+	req.req_hdr = cpu_to_le64(word);
+	req.words[0] = cpu_to_le64(flag);
+
+	rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv)
+		dev_err(&adapter->pdev->dev,
+			"%sting loopback mode failed.\n",
+					flag ? "Set" : "Reset");
+	return rv;
+}
+
+int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter)
+{
+	if (qlcnic_set_fw_loopback(adapter, 1))
+		return -EIO;
+
+	if (qlcnic_nic_set_promisc(adapter,
+				VPORT_MISS_MODE_ACCEPT_ALL)) {
+		qlcnic_set_fw_loopback(adapter, 0);
+		return -EIO;
+	}
+
+	msleep(1000);
+	return 0;
+}
+
+void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter)
+{
+	int mode = VPORT_MISS_MODE_DROP;
+	struct net_device *netdev = adapter->netdev;
+
+	qlcnic_set_fw_loopback(adapter, 0);
+
+	if (netdev->flags & IFF_PROMISC)
+		mode = VPORT_MISS_MODE_ACCEPT_ALL;
+	else if (netdev->flags & IFF_ALLMULTI)
+		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+
+	qlcnic_nic_set_promisc(adapter, mode);
+}
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 7ae8bcc..ea00ab4 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1464,3 +1464,78 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
 	spin_unlock(&rds_ring->lock);
 }
 
+static struct qlcnic_rx_buffer *
+qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
+		struct qlcnic_host_sds_ring *sds_ring,
+		int ring, u64 sts_data0)
+{
+	struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+	struct qlcnic_rx_buffer *buffer;
+	struct sk_buff *skb;
+	struct qlcnic_host_rds_ring *rds_ring;
+	int index, length, cksum, pkt_offset;
+
+	if (unlikely(ring >= adapter->max_rds_rings))
+		return NULL;
+
+	rds_ring = &recv_ctx->rds_rings[ring];
+
+	index = qlcnic_get_sts_refhandle(sts_data0);
+	if (unlikely(index >= rds_ring->num_desc))
+		return NULL;
+
+	buffer = &rds_ring->rx_buf_arr[index];
+
+	length = qlcnic_get_sts_totallength(sts_data0);
+	cksum  = qlcnic_get_sts_status(sts_data0);
+	pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+	skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+	if (!skb)
+		return buffer;
+
+	skb_put(skb, rds_ring->skb_size);
+
+	if (pkt_offset)
+		skb_pull(skb, pkt_offset);
+
+	skb->truesize = skb->len + sizeof(struct sk_buff);
+
+	if (!qlcnic_check_loopback_buff(skb->data))
+		adapter->diag_cnt++;
+
+	dev_kfree_skb_any(skb);
+
+	return buffer;
+}
+
+void
+qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+	struct qlcnic_adapter *adapter = sds_ring->adapter;
+	struct status_desc *desc;
+	struct qlcnic_rx_buffer *rxbuf;
+	u64 sts_data0;
+
+	int opcode, ring, desc_cnt;
+	u32 consumer = sds_ring->consumer;
+
+	desc = &sds_ring->desc_head[consumer];
+	sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+	if (!(sts_data0 & STATUS_OWNER_HOST))
+		return;
+
+	desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+	opcode = qlcnic_get_sts_opcode(sts_data0);
+
+	ring = qlcnic_get_sts_type(sts_data0);
+	rxbuf = qlcnic_process_rcv_diag(adapter, sds_ring,
+					ring, sts_data0);
+
+	desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+	consumer = get_next_index(consumer, sds_ring->num_desc);
+
+	sds_ring->consumer = consumer;
+	writel(consumer, sds_ring->crb_sts_consumer);
+}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index a8b0712..665e8e5 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -65,8 +65,6 @@ static int __devinit qlcnic_probe(struct pci_dev *pdev,
 static void __devexit qlcnic_remove(struct pci_dev *pdev);
 static int qlcnic_open(struct net_device *netdev);
 static int qlcnic_close(struct net_device *netdev);
-static netdev_tx_t qlcnic_xmit_frame(struct sk_buff *,
-					       struct net_device *);
 static void qlcnic_tx_timeout(struct net_device *netdev);
 static void qlcnic_tx_timeout_task(struct work_struct *work);
 static void qlcnic_attach_work(struct work_struct *work);
@@ -937,9 +935,11 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
 	struct qlcnic_host_sds_ring *sds_ring;
 	int ring;
 
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &adapter->recv_ctx.sds_rings[ring];
-		qlcnic_disable_int(sds_ring);
+	if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+		for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+			sds_ring = &adapter->recv_ctx.sds_rings[ring];
+			qlcnic_disable_int(sds_ring);
+		}
 	}
 
 	qlcnic_detach(adapter);
@@ -977,9 +977,11 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
 	if (ret)
 		return ret;
 
-	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-		sds_ring = &adapter->recv_ctx.sds_rings[ring];
-		qlcnic_enable_int(sds_ring);
+	if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+		for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+			sds_ring = &adapter->recv_ctx.sds_rings[ring];
+			qlcnic_enable_int(sds_ring);
+		}
 	}
 
 	return 0;
@@ -1549,7 +1551,7 @@ qlcnic_clear_cmddesc(u64 *desc)
 	desc[2] = 0ULL;
 }
 
-static netdev_tx_t
+netdev_tx_t
 qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
-- 
1.6.0.2


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

* Re: [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests
  2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
                   ` (6 preceding siblings ...)
  2010-02-01 15:25 ` [PATCHv2 NEXT 7/7] qlcnic: add loppback " Amit Kumar Salecha
@ 2010-02-03  0:00 ` David Miller
  7 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2010-02-03  0:00 UTC (permalink / raw)
  To: amit.salecha; +Cc: netdev, dhananjay.phadke, ameen.rahman

From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Date: Mon,  1 Feb 2010 07:24:53 -0800

> Hi
>   Series of 7 patches to add diagnostic test, device identification support and bug fixes.
>   These are v2 patches, please ignore previous patches.
>   Apply them in net-next-2.6 tree.

All applied, thank you.

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

end of thread, other threads:[~2010-02-03  0:00 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-01 15:24 [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 1/7] qlcnic: use DEFINE_PCI_DEVICE_TABLE Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 2/7] qlcnic: add ethernet identifier in board info Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 3/7] qlcnic: clear device reset state after fw recovery Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 4/7] qlcnic: protect resoruce cleanup by rtnl lock Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 5/7] qlcnic: support LED blink for device identification Amit Kumar Salecha
2010-02-01 15:24 ` [PATCHv2 NEXT 6/7] qlcnic: add interrupt diagnostic test Amit Kumar Salecha
2010-02-01 15:25 ` [PATCHv2 NEXT 7/7] qlcnic: add loppback " Amit Kumar Salecha
2010-02-03  0:00 ` [PATCHv2 NEXT 0/7]qlcnic: add diagnostic tests David Miller

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