netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/8] qlcnic: Driver updates
@ 2013-06-21 16:30 Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 1/8] qlcnic: Handle qlcnic_alloc_mbx_args() failure Jitendra Kalsaria
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Jitendra Kalsaria

From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>

Please apply to net-next.

Thanks,
    Jiten

Jitendra Kalsaria (3):
  qlcnic: Secondary unicast address support.
  qlcnic: Minimize sleep duration within loopback diagnostic test.
  qlcnic: Update version to 5.2.44

Pratik Pujar (2):
  qlcnic: Cleanup of structure qlcnic_hardware_context
  qlcnic: Add support for 'set driver version' in 83XX

Rajesh Borundia (1):
  qlcnic: Add support for 83xx suspend and resume.

Shahed Shaikh (2):
  qlcnic: Handle qlcnic_alloc_mbx_args() failure
  qlcnic: Add support for PEX DMA method to read memory section of
    adapter dump

 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |   36 +++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |  269 ++++++++++++++++----
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |   12 +-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |   24 ++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c  |   23 ++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |  129 +++++++---
 .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |    6 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h    |    1 +
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |   88 ++++++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h     |    7 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |  138 +++++------
 .../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c   |  225 ++++++++++++++++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h  |    2 +
 .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c   |   53 ++++
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c  |    2 +-
 15 files changed, 816 insertions(+), 199 deletions(-)

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

* [PATCH net-next 1/8] qlcnic: Handle qlcnic_alloc_mbx_args() failure
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support Jitendra Kalsaria
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem; +Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver

From: Shahed Shaikh <shahed.shaikh@qlogic.com>

qlcnic_alloc_mbx_args() may fail due to failure in memory allocation.
This patch checks for failure of qlcnic_alloc_mbx_args() to avoid
potential invalid memory access.

Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |  133 +++++++++++++++-----
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |    6 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |  125 ++++++++++++++-----
 .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c    |    6 +-
 4 files changed, 206 insertions(+), 64 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index f63a695..88e2e23 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -844,7 +844,9 @@ void qlcnic_83xx_idc_aen_work(struct work_struct *work)
 	int i, err = 0;
 
 	adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
+	if (err)
+		return;
 
 	for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
 		cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
@@ -1085,8 +1087,10 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
 		cap |= QLC_83XX_FW_CAP_LRO_MSS;
 
 	/* set mailbox hdr and capabilities */
-	qlcnic_alloc_mbx_args(&cmd, adapter,
-			      QLCNIC_CMD_CREATE_RX_CTX);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_CREATE_RX_CTX);
+	if (err)
+		return err;
 
 	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
 		cmd.req.arg[0] |= (0x3 << 29);
@@ -1244,7 +1248,9 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
 		mbx.intr_id = 0xffff;
 	mbx.src = 0;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
+	if (err)
+		return err;
 
 	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
 		cmd.req.arg[0] |= (0x3 << 29);
@@ -1390,8 +1396,11 @@ int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
 
 	if (state) {
 		/* Get LED configuration */
-		qlcnic_alloc_mbx_args(&cmd, adapter,
-				      QLCNIC_CMD_GET_LED_CONFIG);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_GET_LED_CONFIG);
+		if (status)
+			return status;
+
 		status = qlcnic_issue_cmd(adapter, &cmd);
 		if (status) {
 			dev_err(&adapter->pdev->dev,
@@ -1405,8 +1414,11 @@ int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
 		/* Set LED Configuration */
 		mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
 			  LSW(QLC_83XX_LED_CONFIG);
-		qlcnic_alloc_mbx_args(&cmd, adapter,
-				      QLCNIC_CMD_SET_LED_CONFIG);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_SET_LED_CONFIG);
+		if (status)
+			return status;
+
 		cmd.req.arg[1] = mbx_in;
 		cmd.req.arg[2] = mbx_in;
 		cmd.req.arg[3] = mbx_in;
@@ -1423,8 +1435,11 @@ mbx_err:
 
 	} else {
 		/* Restoring default LED configuration */
-		qlcnic_alloc_mbx_args(&cmd, adapter,
-				      QLCNIC_CMD_SET_LED_CONFIG);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_SET_LED_CONFIG);
+		if (status)
+			return status;
+
 		cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
 		cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
 		cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
@@ -1494,10 +1509,18 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,
 		return;
 
 	if (enable) {
-		qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_INIT_NIC_FUNC);
+		if (status)
+			return;
+
 		cmd.req.arg[1] = BIT_0 | BIT_31;
 	} else {
-		qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_STOP_NIC_FUNC);
+		if (status)
+			return;
+
 		cmd.req.arg[1] = BIT_0 | BIT_31;
 	}
 	status = qlcnic_issue_cmd(adapter, &cmd);
@@ -1514,7 +1537,10 @@ int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
 	struct qlcnic_cmd_args cmd;
 	int err;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = adapter->ahw->port_config;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err)
@@ -1528,7 +1554,10 @@ int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
 	struct qlcnic_cmd_args cmd;
 	int err;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
+	if (err)
+		return err;
+
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err)
 		dev_info(&adapter->pdev->dev, "Get Port config failed\n");
@@ -1544,7 +1573,10 @@ int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
 	u32 temp;
 	struct qlcnic_cmd_args cmd;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
+	if (err)
+		return err;
+
 	temp = adapter->recv_ctx->context_id << 16;
 	cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
 	err = qlcnic_issue_cmd(adapter, &cmd);
@@ -1575,7 +1607,11 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return -EIO;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
+	if (err)
+		return err;
+
 	qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
 	cmd.req.arg[1] = (mode ? 1 : 0) | temp;
 	err = qlcnic_issue_cmd(adapter, &cmd);
@@ -1762,7 +1798,11 @@ void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
 	u32 temp = 0, temp_ip;
 	struct qlcnic_cmd_args cmd;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_CONFIGURE_IP_ADDR);
+	if (err)
+		return;
+
 	qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp);
 
 	if (mode == QLCNIC_IP_UP)
@@ -1801,7 +1841,10 @@ int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return 0;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
+	if (err)
+		return err;
+
 	temp = adapter->recv_ctx->context_id << 16;
 	arg1 = lro_bit_mask | temp;
 	cmd.req.arg[1] = arg1;
@@ -1823,8 +1866,9 @@ int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
 			    0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
 			    0x255b0ec26d5a56daULL };
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
-
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
+	if (err)
+		return err;
 	/*
 	 * RSS request:
 	 * bits 3-0: Rsvd
@@ -1930,7 +1974,10 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
 	struct qlcnic_cmd_args cmd;
 	u32 mac_low, mac_high;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
+	if (err)
+		return err;
+
 	qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
 	err = qlcnic_issue_cmd(adapter, &cmd);
 
@@ -1961,7 +2008,10 @@ void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter)
 	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
 		return;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
+	if (err)
+		return;
+
 	if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) {
 		temp = adapter->recv_ctx->context_id;
 		cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16;
@@ -2033,7 +2083,10 @@ int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable)
 		return err;
 	}
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = (port & 0xf) | BIT_4;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 
@@ -2061,7 +2114,10 @@ int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
 		return err;
 	}
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = (nic->pci_func << 16);
 	cmd.req.arg[2] = 0x1 << 16;
 	cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
@@ -2093,7 +2149,10 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
 	u8 op = 0;
 	struct qlcnic_cmd_args cmd;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
+	if (err)
+		return err;
+
 	if (func_id != adapter->ahw->pci_func) {
 		temp = func_id << 16;
 		cmd.req.arg[1] = op | BIT_31 | temp;
@@ -2140,7 +2199,10 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
 	int i, err = 0, j = 0;
 	u32 temp;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
+	if (err)
+		return err;
+
 	err = qlcnic_issue_cmd(adapter, &cmd);
 
 	ahw->act_pci_func = 0;
@@ -2195,7 +2257,10 @@ int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
 	struct qlcnic_cmd_args cmd;
 
 	max_ints = adapter->ahw->num_msix - 1;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = max_ints;
 
 	if (qlcnic_sriov_vf_check(adapter))
@@ -2823,7 +2888,11 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
 		dev_info(&adapter->pdev->dev, "link state down\n");
 		return config;
 	}
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
+
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
+	if (err)
+		return err;
+
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err) {
 		dev_info(&adapter->pdev->dev,
@@ -3049,7 +3118,9 @@ void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
 	struct net_device *netdev = adapter->netdev;
 	int ret = 0;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
+	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
+	if (ret)
+		return;
 	/* Get Tx stats */
 	cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16);
 	cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
@@ -3139,7 +3210,9 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
 		goto fail_diag_irq;
 
 	ahw->diag_cnt = 0;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
+	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
+	if (ret)
+		goto fail_diag_irq;
 
 	if (adapter->flags & QLCNIC_MSIX_ENABLED)
 		intrpt_id = ahw->intr_tbl[0].id;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index aa26250..f073c08 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2083,7 +2083,11 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
 	audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT);
 
 	if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) {
-		qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC);
+		status = qlcnic_alloc_mbx_args(&cmd, adapter,
+					       QLCNIC_CMD_STOP_NIC_FUNC);
+		if (status)
+			return;
+
 		cmd.req.arg[1] = BIT_31;
 		status = qlcnic_issue_cmd(adapter, &cmd);
 		if (status)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 9d0ae11..72593a1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -194,7 +194,10 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter)
 		 _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR,
 		 _QLCNIC_LINUX_SUBVERSION);
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER);
+	if (err)
+		return err;
+
 	memcpy(&arg1, drv_string, sizeof(u32));
 	memcpy(&arg2, drv_string + 4, sizeof(u32));
 	memcpy(&arg3, drv_string + 8, sizeof(u32));
@@ -222,7 +225,10 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
 
 	if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
 		return err;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = recv_ctx->context_id;
 	cmd.req.arg[2] = mtu;
 
@@ -336,7 +342,10 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 	}
 
 	phys_addr = hostrq_phys_addr;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX);
+	if (err)
+		goto out_free_rsp;
+
 	cmd.req.arg[1] = MSD(phys_addr);
 	cmd.req.arg[2] = LSD(phys_addr);
 	cmd.req.arg[3] = rq_size;
@@ -374,10 +383,10 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
 	recv_ctx->context_id = le16_to_cpu(prsp->context_id);
 	recv_ctx->virt_port = prsp->virt_port;
 
+	qlcnic_free_mbx_args(&cmd);
 out_free_rsp:
 	dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
-		cardrsp_phys_addr);
-	qlcnic_free_mbx_args(&cmd);
+			  cardrsp_phys_addr);
 out_free_rq:
 	dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
 	return err;
@@ -389,7 +398,10 @@ void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
 	struct qlcnic_cmd_args cmd;
 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX);
+	if (err)
+		return;
+
 	cmd.req.arg[1] = recv_ctx->context_id;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err)
@@ -458,7 +470,10 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
 
 	phys_addr = rq_phys_addr;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
+	if (err)
+		goto out_free_rsp;
+
 	cmd.req.arg[1] = MSD(phys_addr);
 	cmd.req.arg[2] = LSD(phys_addr);
 	cmd.req.arg[3] = rq_size;
@@ -474,12 +489,13 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
 		err = -EIO;
 	}
 
+	qlcnic_free_mbx_args(&cmd);
+
+out_free_rsp:
 	dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
 			  rsp_phys_addr);
-
 out_free_rq:
 	dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
-	qlcnic_free_mbx_args(&cmd);
 
 	return err;
 }
@@ -488,8 +504,11 @@ void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
 				   struct qlcnic_host_tx_ring *tx_ring)
 {
 	struct qlcnic_cmd_args cmd;
+	int ret;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
+	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
+	if (ret)
+		return;
 
 	cmd.req.arg[1] = tx_ring->ctx_id;
 	if (qlcnic_issue_cmd(adapter, &cmd))
@@ -504,7 +523,10 @@ qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
 	int err;
 	struct qlcnic_cmd_args cmd;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = config;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	qlcnic_free_mbx_args(&cmd);
@@ -708,7 +730,10 @@ int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
 	struct qlcnic_cmd_args cmd;
 	u32 mac_low, mac_high;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 
@@ -747,7 +772,10 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
 
 	nic_info = nic_info_addr;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
+	if (err)
+		goto out_free_dma;
+
 	cmd.req.arg[1] = MSD(nic_dma_t);
 	cmd.req.arg[2] = LSD(nic_dma_t);
 	cmd.req.arg[3] = (func_id << 16 | nic_size);
@@ -769,9 +797,10 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
 		npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
 	}
 
+	qlcnic_free_mbx_args(&cmd);
+out_free_dma:
 	dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
 			  nic_dma_t);
-	qlcnic_free_mbx_args(&cmd);
 
 	return err;
 }
@@ -808,7 +837,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
 	nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
 	nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
+	if (err)
+		goto out_free_dma;
+
 	cmd.req.arg[1] = MSD(nic_dma_t);
 	cmd.req.arg[2] = LSD(nic_dma_t);
 	cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
@@ -820,9 +852,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
 		err = -EIO;
 	}
 
-	dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
-		nic_dma_t);
 	qlcnic_free_mbx_args(&cmd);
+out_free_dma:
+	dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
+			  nic_dma_t);
 
 	return err;
 }
@@ -846,7 +879,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
 		return -ENOMEM;
 
 	npar = pci_info_addr;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
+	if (err)
+		goto out_free_dma;
+
 	cmd.req.arg[1] = MSD(pci_info_dma_t);
 	cmd.req.arg[2] = LSD(pci_info_dma_t);
 	cmd.req.arg[3] = pci_size;
@@ -874,9 +910,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
 		err = -EIO;
 	}
 
+	qlcnic_free_mbx_args(&cmd);
+out_free_dma:
 	dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
 		pci_info_dma_t);
-	qlcnic_free_mbx_args(&cmd);
 
 	return err;
 }
@@ -897,7 +934,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
 	arg1 = id | (enable_mirroring ? BIT_4 : 0);
 	arg1 |= pci_func << 8;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORTMIRRORING);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_SET_PORTMIRRORING);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = arg1;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 
@@ -941,7 +982,11 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 	arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
 	arg1 |= rx_tx << 15 | stats_size << 16;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_GET_ESWITCH_STATS);
+	if (err)
+		goto out_free_dma;
+
 	cmd.req.arg[1] = arg1;
 	cmd.req.arg[2] = MSD(stats_dma_t);
 	cmd.req.arg[3] = LSD(stats_dma_t);
@@ -963,9 +1008,10 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 		esw_stats->numbytes = le64_to_cpu(stats->numbytes);
 	}
 
-	dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
-		stats_dma_t);
 	qlcnic_free_mbx_args(&cmd);
+out_free_dma:
+	dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
+			  stats_dma_t);
 
 	return err;
 }
@@ -989,7 +1035,10 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
 	if (!stats_addr)
 		return -ENOMEM;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
+	if (err)
+		goto out_free_dma;
+
 	cmd.req.arg[1] = stats_size << 16;
 	cmd.req.arg[2] = MSD(stats_dma_t);
 	cmd.req.arg[3] = LSD(stats_dma_t);
@@ -1020,11 +1069,12 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
 			"%s: Get mac stats failed, err=%d.\n", __func__, err);
 	}
 
-	dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
-		stats_dma_t);
-
 	qlcnic_free_mbx_args(&cmd);
 
+out_free_dma:
+	dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
+			  stats_dma_t);
+
 	return err;
 }
 
@@ -1108,7 +1158,11 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
 	arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
 	arg1 |= BIT_14 | rx_tx << 15;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_GET_ESWITCH_STATS);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = arg1;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	qlcnic_free_mbx_args(&cmd);
@@ -1127,10 +1181,13 @@ static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
 	struct device *dev = &adapter->pdev->dev;
 	struct qlcnic_cmd_args cmd;
 	u8 pci_func = *arg1 >> 8;
-	int err = -EIO;
+	int err;
+
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
+	if (err)
+		return err;
 
-	qlcnic_alloc_mbx_args(&cmd, adapter,
-			      QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
 	cmd.req.arg[1] = *arg1;
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	*arg1 = cmd.rsp.arg[1];
@@ -1208,7 +1265,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
 		return err;
 	}
 
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_ESWITCH);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter,
+				    QLCNIC_CMD_CONFIGURE_ESWITCH);
+	if (err)
+		return err;
+
 	cmd.req.arg[1] = arg1;
 	cmd.req.arg[2] = arg2;
 	err = qlcnic_issue_cmd(adapter, &cmd);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index f67652d..700a463 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -846,7 +846,9 @@ static int qlcnic_irq_test(struct net_device *netdev)
 		goto clear_diag_irq;
 
 	ahw->diag_cnt = 0;
-	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
+	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
+	if (ret)
+		goto free_diag_res;
 
 	cmd.req.arg[1] = ahw->pci_func;
 	ret = qlcnic_issue_cmd(adapter, &cmd);
@@ -858,6 +860,8 @@ static int qlcnic_irq_test(struct net_device *netdev)
 
 done:
 	qlcnic_free_mbx_args(&cmd);
+
+free_diag_res:
 	qlcnic_diag_free_res(netdev, max_sds_rings);
 
 clear_diag_irq:
-- 
1.7.1

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

* [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support.
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 1/8] qlcnic: Handle qlcnic_alloc_mbx_args() failure Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-21 17:10   ` Joe Perches
  2013-06-21 16:30 ` [PATCH net-next 3/8] qlcnic: Minimize sleep duration within loopback diagnostic test Jitendra Kalsaria
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Jitendra Kalsaria

From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>

Add support for configuring secondary unicast address which
will use existing HW filters to store all the unicast MAC
addresses and prevent device going into promiscuous mode.

Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |    8 ++++
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |   17 ++++++++
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |    3 +
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h    |    1 +
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |   34 +++++++++------
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   43 +++++++++++++++----
 6 files changed, 83 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 534e36e..cb39650 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -421,6 +421,7 @@ struct qlcnic_hardware_context {
 	u8 max_mac_filters;
 	u8 mc_enabled;
 	u8 max_mc_count;
+	u8 max_uc_count;
 	u8 diag_test;
 	u8 num_msix;
 	u8 nic_mode;
@@ -1494,6 +1495,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t);
 int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
 void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
+void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
 int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
 
 /*  eSwitch management functions */
@@ -1631,6 +1633,7 @@ struct qlcnic_hardware_ops {
 	int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
 	void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16);
 	int (*get_board_info) (struct qlcnic_adapter *);
+	void (*set_mac_filter_count) (struct qlcnic_adapter *);
 	void (*free_mac_list) (struct qlcnic_adapter *);
 };
 
@@ -1846,6 +1849,11 @@ static inline void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
 	return adapter->ahw->hw_ops->free_mac_list(adapter);
 }
 
+static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter)
+{
+	adapter->ahw->hw_ops->set_mac_filter_count(adapter);
+}
+
 static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
 					    u32 key)
 {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 88e2e23..a0248b7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -172,6 +172,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
 	.config_promisc_mode		= qlcnic_83xx_nic_set_promisc,
 	.change_l2_filter		= qlcnic_83xx_change_l2_filter,
 	.get_board_info			= qlcnic_83xx_get_port_info,
+	.set_mac_filter_count		= qlcnic_83xx_set_mac_filter_count,
 	.free_mac_list			= qlcnic_82xx_free_mac_list,
 };
 
@@ -609,6 +610,22 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
 	return status;
 }
 
+void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u16 act_pci_fn = ahw->act_pci_func;
+	u8 count;
+
+	ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
+	if (act_pci_fn <= 2)
+		count = (QLC_83XX_MAX_UC_COUNT - QLC_83XX_MAX_MC_COUNT) /
+			 act_pci_fn;
+	else
+		count = (QLC_83XX_LB_MAX_FILTERS - QLC_83XX_MAX_MC_COUNT) /
+			 act_pci_fn;
+	ahw->max_uc_count = count;
+}
+
 void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter)
 {
 	u32 val;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 1bfe283..e821ee4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -393,6 +393,8 @@ enum qlcnic_83xx_states {
 #define QLC_83XX_LB_MAX_FILTERS			2048
 #define QLC_83XX_LB_BUCKET_SIZE			256
 #define QLC_83XX_MINIMUM_VECTOR			3
+#define QLC_83XX_MAX_MC_COUNT			38
+#define QLC_83XX_MAX_UC_COUNT			4096
 
 #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val)	(val & 0x80000000)
 #define QLC_83XX_GET_LRO_CAPABILITY(val)		(val & 0x20)
@@ -624,4 +626,5 @@ u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
 u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
 void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
+void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
 #endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
index c0f0c0d..d262211 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
@@ -672,6 +672,7 @@ enum {
 #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT	10
 
 #define QLCNIC_MAX_MC_COUNT		38
+#define QLCNIC_MAX_UC_COUNT		512
 #define QLCNIC_WATCHDOG_TIMEOUTVALUE	5
 
 #define	ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 218978d..e7f305d 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -499,6 +499,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan)
 void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
 {
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
 	struct netdev_hw_addr *ha;
 	static const u8 bcast_addr[ETH_ALEN] = {
 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
@@ -515,25 +516,30 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan)
 	if (netdev->flags & IFF_PROMISC) {
 		if (!(adapter->flags & QLCNIC_PROMISC_DISABLED))
 			mode = VPORT_MISS_MODE_ACCEPT_ALL;
-		goto send_fw_cmd;
-	}
-
-	if ((netdev->flags & IFF_ALLMULTI) ||
-	    (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
-		mode = VPORT_MISS_MODE_ACCEPT_MULTI;
-		goto send_fw_cmd;
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		if (netdev_mc_count(netdev) > ahw->max_mc_count) {
+			mode = VPORT_MISS_MODE_ACCEPT_MULTI;
+		} else if (!netdev_mc_empty(netdev) &&
+			   !qlcnic_sriov_vf_check(adapter)) {
+				netdev_for_each_mc_addr(ha, netdev)
+					qlcnic_nic_add_mac(adapter, ha->addr,
+							   vlan);
+		}
+		if (mode != VPORT_MISS_MODE_ACCEPT_MULTI &&
+		    qlcnic_sriov_vf_check(adapter))
+			qlcnic_vf_add_mc_list(netdev, vlan);
 	}
 
-	if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) {
-		netdev_for_each_mc_addr(ha, netdev) {
+	/* configure unicast MAC address, if there is not sufficient space
+	 * to store all the unicast addresses then enable promiscuous mode
+	 */
+	if (netdev_uc_count(netdev) > ahw->max_uc_count) {
+		mode = VPORT_MISS_MODE_ACCEPT_ALL;
+	} else if (!netdev_uc_empty(netdev)) {
+		netdev_for_each_uc_addr(ha, netdev)
 			qlcnic_nic_add_mac(adapter, ha->addr, vlan);
-		}
 	}
 
-	if (qlcnic_sriov_vf_check(adapter))
-		qlcnic_vf_add_mc_list(netdev, vlan);
-
-send_fw_cmd:
 	if (!qlcnic_sriov_vf_check(adapter)) {
 		if (mode == VPORT_MISS_MODE_ACCEPT_ALL &&
 		    !adapter->fdb_mac_learn) {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 0ae8835..14d05e3 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -360,12 +360,15 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 		return ndo_dflt_fdb_del(ndm, tb, netdev, addr);
 
 	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
-		if (is_unicast_ether_addr(addr))
-			err = qlcnic_nic_del_mac(adapter, addr);
-		else if (is_multicast_ether_addr(addr))
+		if (is_unicast_ether_addr(addr)) {
+			err = dev_uc_del(netdev, addr);
+			if (!err)
+				err = qlcnic_nic_del_mac(adapter, addr);
+		} else if (is_multicast_ether_addr(addr)) {
 			err = dev_mc_del(netdev, addr);
-		else
+		} else {
 			err =  -EINVAL;
+		}
 	}
 	return err;
 }
@@ -388,12 +391,16 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	if (ether_addr_equal(addr, adapter->mac_addr))
 		return err;
 
-	if (is_unicast_ether_addr(addr))
-		err = qlcnic_nic_add_mac(adapter, addr, 0);
-	else if (is_multicast_ether_addr(addr))
+	if (is_unicast_ether_addr(addr)) {
+		if (netdev_uc_count(netdev) < adapter->ahw->max_uc_count)
+			err = dev_uc_add_excl(netdev, addr);
+		else
+			err = -ENOMEM;
+	} else if (is_multicast_ether_addr(addr)) {
 		err = dev_mc_add_excl(netdev, addr);
-	else
+	} else {
 		err = -EINVAL;
+	}
 
 	return err;
 }
@@ -505,6 +512,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
 	.config_promisc_mode		= qlcnic_82xx_nic_set_promisc,
 	.change_l2_filter		= qlcnic_82xx_change_filter,
 	.get_board_info			= qlcnic_82xx_get_board_info,
+	.set_mac_filter_count		= qlcnic_82xx_set_mac_filter_count,
 	.free_mac_list			= qlcnic_82xx_free_mac_list,
 };
 
@@ -1829,6 +1837,22 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
 	return err;
 }
 
+void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u16 act_pci_fn = ahw->act_pci_func;
+	u8 count;
+
+	ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
+	if (act_pci_fn <= 2)
+		count = (QLCNIC_MAX_UC_COUNT - QLCNIC_MAX_MC_COUNT) /
+			 act_pci_fn;
+	else
+		count = (QLCNIC_LB_MAX_FILTERS - QLCNIC_MAX_MC_COUNT) /
+			 act_pci_fn;
+	ahw->max_uc_count = count;
+}
+
 int
 qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 		    int pci_using_dac)
@@ -1838,7 +1862,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 
 	adapter->rx_csum = 1;
 	adapter->ahw->mc_enabled = 0;
-	adapter->ahw->max_mc_count = QLCNIC_MAX_MC_COUNT;
+	qlcnic_set_mac_filter_count(adapter);
 
 	netdev->netdev_ops	   = &qlcnic_netdev_ops;
 	netdev->watchdog_timeo     = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ;
@@ -1876,6 +1900,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
 		netdev->features |= NETIF_F_LRO;
 
 	netdev->hw_features = netdev->features;
+	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->irq = adapter->msix_entries[0].vector;
 
 	err = register_netdev(netdev);
-- 
1.7.1

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

* [PATCH net-next 3/8] qlcnic: Minimize sleep duration within loopback diagnostic test.
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 1/8] qlcnic: Handle qlcnic_alloc_mbx_args() failure Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump Jitendra Kalsaria
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Jitendra Kalsaria

From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>

o Minimize sleep duration and check for adapter status.
o Exit from loopback test if adapter reset is detected.

Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |   57 +++++++++++++------
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |    3 +-
 2 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index a0248b7..48fdaff 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -1676,13 +1676,19 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
 
 	/* Poll for link up event before running traffic */
 	do {
-		msleep(500);
+		msleep(QLC_83XX_LB_MSLEEP_COUNT);
 		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
 			qlcnic_83xx_process_aen(adapter);
 
-		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
-			dev_info(&adapter->pdev->dev,
-				 "Firmware didn't sent link up event to loopback request\n");
+		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+			netdev_info(netdev,
+				    "Device is resetting, free LB test resources\n");
+			ret = -EIO;
+			goto free_diag_res;
+		}
+		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
+			netdev_info(netdev,
+				    "Firmware didn't sent link up event to loopback request\n");
 			ret = -QLCNIC_FW_NOT_RESPOND;
 			qlcnic_83xx_clear_lb_mode(adapter, mode);
 			goto free_diag_res;
@@ -1711,6 +1717,7 @@ fail_diag_alloc:
 int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct net_device *netdev = adapter->netdev;
 	int status = 0, loop = 0;
 	u32 config;
 
@@ -1728,9 +1735,9 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 
 	status = qlcnic_83xx_set_port_config(adapter);
 	if (status) {
-		dev_err(&adapter->pdev->dev,
-			"Failed to Set Loopback Mode = 0x%x.\n",
-			ahw->port_config);
+		netdev_err(netdev,
+			   "Failed to Set Loopback Mode = 0x%x.\n",
+			   ahw->port_config);
 		ahw->port_config = config;
 		clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 		return status;
@@ -1738,13 +1745,19 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 
 	/* Wait for Link and IDC Completion AEN */
 	do {
-		msleep(300);
+		msleep(QLC_83XX_LB_MSLEEP_COUNT);
 		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
 			qlcnic_83xx_process_aen(adapter);
 
-		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
-			dev_err(&adapter->pdev->dev,
-				"FW did not generate IDC completion AEN\n");
+		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+			netdev_info(netdev,
+				    "Device is resetting, free LB test resources\n");
+			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
+			return -EIO;
+		}
+		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
+			netdev_err(netdev,
+				   "Did not receive IDC completion AEN\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 			qlcnic_83xx_clear_lb_mode(adapter, mode);
 			return -EIO;
@@ -1759,6 +1772,7 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 {
 	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct net_device *netdev = adapter->netdev;
 	int status = 0, loop = 0;
 	u32 config = ahw->port_config;
 
@@ -1770,9 +1784,9 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 
 	status = qlcnic_83xx_set_port_config(adapter);
 	if (status) {
-		dev_err(&adapter->pdev->dev,
-			"Failed to Clear Loopback Mode = 0x%x.\n",
-			ahw->port_config);
+		netdev_err(netdev,
+			   "Failed to Clear Loopback Mode = 0x%x.\n",
+			   ahw->port_config);
 		ahw->port_config = config;
 		clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 		return status;
@@ -1780,13 +1794,20 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
 
 	/* Wait for Link and IDC Completion AEN */
 	do {
-		msleep(300);
+		msleep(QLC_83XX_LB_MSLEEP_COUNT);
 		if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
 			qlcnic_83xx_process_aen(adapter);
 
-		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
-			dev_err(&adapter->pdev->dev,
-				"Firmware didn't sent IDC completion AEN\n");
+		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+			netdev_info(netdev,
+				    "Device is resetting, free LB test resources\n");
+			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
+			return -EIO;
+		}
+
+		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
+			netdev_err(netdev,
+				   "Did not receive IDC completion AEN\n");
 			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
 			return -EIO;
 		}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index e821ee4..e356ee8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -36,7 +36,8 @@
 #define QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT		3
 #define QLC_83XX_DRV_LOCK_RECOVERY_DELAY		200
 #define QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK		0x3
-
+#define QLC_83XX_LB_WAIT_COUNT				250
+#define QLC_83XX_LB_MSLEEP_COUNT			20
 #define QLC_83XX_NO_NIC_RESOURCE	0x5
 #define QLC_83XX_MAC_PRESENT		0xC
 #define QLC_83XX_MAC_ABSENT		0xD
-- 
1.7.1

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

* [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
                   ` (2 preceding siblings ...)
  2013-06-21 16:30 ` [PATCH net-next 3/8] qlcnic: Minimize sleep duration within loopback diagnostic test Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-24  8:56   ` David Laight
  2013-06-21 16:30 ` [PATCH net-next 5/8] qlcnic: Cleanup of structure qlcnic_hardware_context Jitendra Kalsaria
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem; +Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver

From: Shahed Shaikh <shahed.shaikh@qlogic.com>

This patch adds support to read memory section of adapter
dump using PEX DMA method. This method significantly improves
total adapter dump collection time.

Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |    3 +
 .../net/ethernet/qlogic/qlcnic/qlcnic_minidump.c   |  225 +++++++++++++++++++-
 2 files changed, 221 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index cb39650..87d0054 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -393,6 +393,9 @@ struct qlcnic_fw_dump {
 	u32	size;	/* total size of the dump */
 	void	*data;	/* dump data area */
 	struct	qlcnic_dump_template_hdr *tmpl_hdr;
+	dma_addr_t phys_addr;
+	void	*dma_buffer;
+	bool	use_pex_dma;
 };
 
 /*
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index 4b9bab1..ab8a674 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -15,6 +15,7 @@
 #define QLC_83XX_MINIDUMP_FLASH		0x520000
 #define QLC_83XX_OCM_INDEX			3
 #define QLC_83XX_PCI_INDEX			0
+#define QLC_83XX_DMA_ENGINE_INDEX		8
 
 static const u32 qlcnic_ms_read_data[] = {
 	0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC
@@ -32,6 +33,16 @@ static const u32 qlcnic_ms_read_data[] = {
 
 #define QLCNIC_DUMP_MASK_MAX	0xff
 
+struct qlcnic_pex_dma_descriptor {
+	u32	read_data_size;
+	u32	dma_desc_cmd;
+	u32	src_addr_low;
+	u32	src_addr_high;
+	u32	dma_bus_addr_low;
+	u32	dma_bus_addr_high;
+	u32	rsvd[6];
+} __packed;
+
 struct qlcnic_common_entry_hdr {
 	u32     type;
 	u32     offset;
@@ -90,7 +101,10 @@ struct __ocm {
 } __packed;
 
 struct __mem {
-	u8	rsvd[24];
+	u32	desc_card_addr;
+	u32	dma_desc_cmd;
+	u32	start_dma_cmd;
+	u32	rsvd[3];
 	u32	addr;
 	u32	size;
 } __packed;
@@ -466,12 +480,12 @@ skip_poll:
 	return l2->no_ops * l2->read_addr_num * sizeof(u32);
 }
 
-static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
-			      struct qlcnic_dump_entry *entry, __le32 *buffer)
+static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter,
+					 struct __mem *mem, __le32 *buffer,
+					 int *ret)
 {
-	u32 addr, data, test, ret = 0;
+	u32 addr, data, test;
 	int i, reg_read;
-	struct __mem *mem = &entry->region.mem;
 
 	reg_read = mem->size;
 	addr = mem->addr;
@@ -480,7 +494,8 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
 		dev_info(&adapter->pdev->dev,
 			 "Unaligned memory addr:0x%x size:0x%x\n",
 			 addr, reg_read);
-		return -EINVAL;
+		*ret = -EINVAL;
+		return 0;
 	}
 
 	mutex_lock(&adapter->ahw->mem_lock);
@@ -499,7 +514,7 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
 			if (printk_ratelimit()) {
 				dev_err(&adapter->pdev->dev,
 					"failed to read through agent\n");
-				ret = -EINVAL;
+				*ret = -EIO;
 				goto out;
 			}
 		}
@@ -516,6 +531,181 @@ out:
 	return mem->size;
 }
 
+/* DMA register base address */
+#define QLC_DMA_REG_BASE_ADDR(dma_no)	(0x77320000 + (dma_no * 0x10000))
+
+/* DMA register offsets w.r.t base address */
+#define QLC_DMA_CMD_BUFF_ADDR_LOW	0
+#define QLC_DMA_CMD_BUFF_ADDR_HI	4
+#define QLC_DMA_CMD_STATUS_CTRL		8
+
+#define QLC_PEX_DMA_READ_SIZE		(PAGE_SIZE * 16)
+
+static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter,
+				struct __mem *mem)
+{
+	struct qlcnic_dump_template_hdr *tmpl_hdr;
+	struct device *dev = &adapter->pdev->dev;
+	u32 dma_no, dma_base_addr, temp_addr;
+	int i, ret, dma_sts;
+
+	tmpl_hdr = adapter->ahw->fw_dump.tmpl_hdr;
+	dma_no = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX];
+	dma_base_addr = QLC_DMA_REG_BASE_ADDR(dma_no);
+
+	temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_LOW;
+	ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr,
+					   mem->desc_card_addr);
+	if (ret)
+		return ret;
+
+	temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_HI;
+	ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, 0);
+	if (ret)
+		return ret;
+
+	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;
+	ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr,
+					   mem->start_dma_cmd);
+	if (ret)
+		return ret;
+
+	/* Wait for DMA to complete */
+	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;
+	for (i = 0; i < 400; i++) {
+		dma_sts = qlcnic_ind_rd(adapter, temp_addr);
+
+		if (dma_sts & BIT_1)
+			usleep_range(250, 500);
+		else
+			break;
+	}
+
+	if (i >= 400) {
+		dev_info(dev, "PEX DMA operation timed out");
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,
+				     struct __mem *mem,
+				     __le32 *buffer, int *ret)
+{
+	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+	u32 temp, dma_base_addr, size = 0, read_size = 0;
+	struct qlcnic_pex_dma_descriptor *dma_descr;
+	struct qlcnic_dump_template_hdr *tmpl_hdr;
+	struct device *dev = &adapter->pdev->dev;
+	dma_addr_t dma_phys_addr;
+	void *dma_buffer;
+
+	tmpl_hdr = fw_dump->tmpl_hdr;
+
+	/* Check if DMA engine is available */
+	temp = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX];
+	dma_base_addr = QLC_DMA_REG_BASE_ADDR(temp);
+	temp = qlcnic_ind_rd(adapter,
+			     dma_base_addr + QLC_DMA_CMD_STATUS_CTRL);
+
+	if (!(temp & BIT_31)) {
+		dev_info(dev, "%s: DMA engine is not available\n", __func__);
+		*ret = -EIO;
+		return 0;
+	}
+
+	/* Create DMA descriptor */
+	dma_descr = kzalloc(sizeof(struct qlcnic_pex_dma_descriptor),
+			    GFP_KERNEL);
+	if (!dma_descr) {
+		*ret = -ENOMEM;
+		return 0;
+	}
+
+	/* dma_desc_cmd  0:15  = 0
+	 * dma_desc_cmd 16:19  = mem->dma_desc_cmd 0:3
+	 * dma_desc_cmd 20:23  = pci function number
+	 * dma_desc_cmd 24:31  = mem->dma_desc_cmd 8:15
+	 */
+	dma_phys_addr = fw_dump->phys_addr;
+	dma_buffer = fw_dump->dma_buffer;
+	temp = 0;
+	temp = mem->dma_desc_cmd & 0xff0f;
+	temp |= (adapter->ahw->pci_func & 0xf) << 4;
+	dma_descr->dma_desc_cmd = (temp << 16) & 0xffff0000;
+	dma_descr->dma_bus_addr_low = LSD(dma_phys_addr);
+	dma_descr->dma_bus_addr_high = MSD(dma_phys_addr);
+	dma_descr->src_addr_high = 0;
+
+	/* Collect memory dump using multiple DMA operations if required */
+	while (read_size < mem->size) {
+		if (mem->size - read_size >= QLC_PEX_DMA_READ_SIZE)
+			size = QLC_PEX_DMA_READ_SIZE;
+		else
+			size = mem->size - read_size;
+
+		dma_descr->src_addr_low = mem->addr + read_size;
+		dma_descr->read_data_size = size;
+
+		/* Write DMA descriptor to MS memory*/
+		temp = sizeof(struct qlcnic_pex_dma_descriptor) / 16;
+		*ret = qlcnic_83xx_ms_mem_write128(adapter, mem->desc_card_addr,
+						   (u32 *)dma_descr, temp);
+		if (*ret) {
+			dev_info(dev, "Failed to write DMA descriptor to MS memory at address 0x%x\n",
+				 mem->desc_card_addr);
+			goto free_dma_descr;
+		}
+
+		*ret = qlcnic_start_pex_dma(adapter, mem);
+		if (*ret) {
+			dev_info(dev, "Failed to start PEX DMA operation\n");
+			goto free_dma_descr;
+		}
+
+		memcpy(buffer, dma_buffer, size);
+		buffer += size / 4;
+		read_size += size;
+	}
+
+free_dma_descr:
+	kfree(dma_descr);
+
+	return read_size;
+}
+
+static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
+			      struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+	struct device *dev = &adapter->pdev->dev;
+	struct __mem *mem = &entry->region.mem;
+	u32 data_size;
+	int ret = 0;
+
+	if (fw_dump->use_pex_dma) {
+		data_size = qlcnic_read_memory_pexdma(adapter, mem, buffer,
+						      &ret);
+		if (ret)
+			dev_info(dev,
+				 "Failed to read memory dump using PEX DMA: mask[0x%x]\n",
+				 entry->hdr.mask);
+		else
+			return data_size;
+	}
+
+	data_size = qlcnic_read_memory_test_agent(adapter, mem, buffer, &ret);
+	if (ret) {
+		dev_info(dev,
+			 "Failed to read memory dump using test agent method: mask[0x%x]\n",
+			 entry->hdr.mask);
+		return 0;
+	} else {
+		return data_size;
+	}
+}
+
 static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter,
 			   struct qlcnic_dump_entry *entry, __le32 *buffer)
 {
@@ -893,6 +1083,12 @@ flash_temp:
 
 	tmpl_hdr = ahw->fw_dump.tmpl_hdr;
 	tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
+
+	if ((tmpl_hdr->version & 0xffffff) >= 0x20001)
+		ahw->fw_dump.use_pex_dma = true;
+	else
+		ahw->fw_dump.use_pex_dma = false;
+
 	ahw->fw_dump.enable = 1;
 
 	return 0;
@@ -910,7 +1106,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 	struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
 	static const struct qlcnic_dump_operations *fw_dump_ops;
+	struct device *dev = &adapter->pdev->dev;
 	struct qlcnic_hardware_context *ahw;
+	void *temp_buffer;
 
 	ahw = adapter->ahw;
 
@@ -944,6 +1142,16 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 	tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
 	tmpl_hdr->sys_info[1] = adapter->fw_version;
 
+	if (fw_dump->use_pex_dma) {
+		temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE,
+						 &fw_dump->phys_addr,
+						 GFP_KERNEL);
+		if (!temp_buffer)
+			fw_dump->use_pex_dma = false;
+		else
+			fw_dump->dma_buffer = temp_buffer;
+	}
+
 	if (qlcnic_82xx_check(adapter)) {
 		ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops);
 		fw_dump_ops = qlcnic_fw_dump_ops;
@@ -1002,6 +1210,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
 		return 0;
 	}
 error:
+	if (fw_dump->use_pex_dma)
+		dma_free_coherent(dev, QLC_PEX_DMA_READ_SIZE,
+				  fw_dump->dma_buffer, fw_dump->phys_addr);
 	vfree(fw_dump->data);
 	return -EINVAL;
 }
-- 
1.7.1

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

* [PATCH net-next 5/8] qlcnic: Cleanup of structure qlcnic_hardware_context
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
                   ` (3 preceding siblings ...)
  2013-06-21 16:30 ` [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-21 16:30 ` [PATCH net-next 6/8] qlcnic: Add support for 'set driver version' in 83XX Jitendra Kalsaria
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Pratik Pujar

From: Pratik Pujar <pratik.pujar@qlogic.com>

Signed-off-by: Pratik Pujar <pratik.pujar@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h       |    2 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c    |    3 ++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c  |    4 ++--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c |    2 +-
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 87d0054..0b3361e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -449,7 +449,7 @@ struct qlcnic_hardware_context {
 	u16 max_pci_func;
 
 	u32 capabilities;
-	u32 capabilities2;
+	u32 extra_capability[3];
 	u32 temp;
 	u32 int_vec_bit;
 	u32 fw_hal_version;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index e7f305d..9fcbfd4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -786,7 +786,8 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
 	word = 0;
 	if (enable) {
 		word = QLCNIC_ENABLE_IPV4_LRO | QLCNIC_NO_DEST_IPV4_CHECK;
-		if (adapter->ahw->capabilities2 & QLCNIC_FW_CAP2_HW_LRO_IPV6)
+		if (adapter->ahw->extra_capability[0] &
+		    QLCNIC_FW_CAP2_HW_LRO_IPV6)
 			word |= QLCNIC_ENABLE_IPV6_LRO |
 				QLCNIC_NO_DEST_IPV6_CHECK;
 	}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 14d05e3..97d633a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -994,7 +994,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
 	if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
 		u32 temp;
 		temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
-		adapter->ahw->capabilities2 = temp;
+		adapter->ahw->extra_capability[0] = temp;
 	}
 	adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
 	adapter->ahw->max_mtu = nic_info.max_mtu;
@@ -1486,7 +1486,7 @@ static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter)
 	u32 capab = 0;
 
 	if (qlcnic_82xx_check(adapter)) {
-		if (adapter->ahw->capabilities2 &
+		if (adapter->ahw->extra_capability[0] &
 		    QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
 			adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
 	} else {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 7ec030a..10ed82b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -168,7 +168,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter,
 	if (err)
 		return err;
 
-	if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) {
+	if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) {
 		err = qlcnic_get_beacon_state(adapter, &h_beacon_state);
 		if (!err) {
 			dev_info(&adapter->pdev->dev,
-- 
1.7.1

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

* [PATCH net-next 6/8] qlcnic: Add support for 'set driver version' in 83XX
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
                   ` (4 preceding siblings ...)
  2013-06-21 16:30 ` [PATCH net-next 5/8] qlcnic: Cleanup of structure qlcnic_hardware_context Jitendra Kalsaria
@ 2013-06-21 16:30 ` Jitendra Kalsaria
  2013-06-21 16:31 ` [PATCH net-next 7/8] qlcnic: Add support for 83xx suspend and resume Jitendra Kalsaria
  2013-06-21 16:31 ` [PATCH net-next 8/8] qlcnic: Update version to 5.2.44 Jitendra Kalsaria
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:30 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Pratik Pujar

From: Pratik Pujar <pratik.pujar@qlogic.com>

Issue 'set driver version' during driver load and after reset recovery
to notify the driver version to the firmware.

Signed-off-by: Pratik Pujar <pratik.pujar@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |    5 ++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |    9 +++++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |    1 +
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c    |    6 ++--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h     |    3 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   25 +++++++++++++------
 6 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 0b3361e..45d9329 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -819,7 +819,7 @@ struct qlcnic_mac_list_s {
 
 #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG	BIT_2
 #define QLCNIC_FW_CAP2_HW_LRO_IPV6		BIT_3
-#define QLCNIC_FW_CAPABILITY_2_OCBB		BIT_5
+#define QLCNIC_FW_CAPABILITY_SET_DRV_VER	BIT_5
 #define QLCNIC_FW_CAPABILITY_2_BEACON		BIT_7
 
 /* module types */
@@ -1476,7 +1476,7 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *);
 void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter);
 
 int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
-int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *);
+int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32);
 int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
 netdev_features_t qlcnic_fix_features(struct net_device *netdev,
 	netdev_features_t features);
@@ -1500,6 +1500,7 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32);
 void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
 void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
 int qlcnic_enable_msix(struct qlcnic_adapter *, u32);
+void qlcnic_set_drv_version(struct qlcnic_adapter *);
 
 /*  eSwitch management functions */
 int qlcnic_config_switch_port(struct qlcnic_adapter *,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 48fdaff..a1887e4 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -63,6 +63,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
 	{QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
 	{QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
 	{QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
+	{QLCNIC_CMD_83XX_SET_DRV_VER, 4, 1},
 	{QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
 	{QLCNIC_CMD_CONFIG_VPORT, 4, 4},
 	{QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
@@ -2186,16 +2187,17 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
 	u32 temp;
 	u8 op = 0;
 	struct qlcnic_cmd_args cmd;
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
 
 	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
 	if (err)
 		return err;
 
-	if (func_id != adapter->ahw->pci_func) {
+	if (func_id != ahw->pci_func) {
 		temp = func_id << 16;
 		cmd.req.arg[1] = op | BIT_31 | temp;
 	} else {
-		cmd.req.arg[1] = adapter->ahw->pci_func << 16;
+		cmd.req.arg[1] = ahw->pci_func << 16;
 	}
 	err = qlcnic_issue_cmd(adapter, &cmd);
 	if (err) {
@@ -2222,6 +2224,9 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
 		temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
 		npar_info->max_linkspeed_reg_offset = temp;
 	}
+	if (npar_info->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS)
+		memcpy(ahw->extra_capability, &cmd.rsp.arg[16],
+		       sizeof(ahw->extra_capability));
 
 out:
 	qlcnic_free_mbx_args(&cmd);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index f073c08..e2d04d5 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -629,6 +629,7 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
 		return -EIO;
 	}
 
+	qlcnic_set_drv_version(adapter);
 	qlcnic_83xx_idc_attach_driver(adapter);
 
 	return 0;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
index 72593a1..0d54fce 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -36,7 +36,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
 	{QLCNIC_CMD_CONFIG_PORT, 4, 1},
 	{QLCNIC_CMD_TEMP_SIZE, 4, 4},
 	{QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
-	{QLCNIC_CMD_SET_DRV_VER, 4, 1},
+	{QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1},
 	{QLCNIC_CMD_GET_LED_STATUS, 4, 2},
 };
 
@@ -182,7 +182,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
 	return cmd->rsp.arg[0];
 }
 
-int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter)
+int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter, u32 fw_cmd)
 {
 	struct qlcnic_cmd_args cmd;
 	u32 arg1, arg2, arg3;
@@ -194,7 +194,7 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter)
 		 _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR,
 		 _QLCNIC_LINUX_SUBVERSION);
 
-	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER);
+	err = qlcnic_alloc_mbx_args(&cmd, adapter, fw_cmd);
 	if (err)
 		return err;
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 812fd07..b190c84 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -86,7 +86,7 @@ enum qlcnic_regs {
 #define QLCNIC_CMD_BC_EVENT_SETUP		0x31
 #define	QLCNIC_CMD_CONFIG_VPORT			0x32
 #define QLCNIC_CMD_GET_MAC_STATS		0x37
-#define QLCNIC_CMD_SET_DRV_VER			0x38
+#define QLCNIC_CMD_82XX_SET_DRV_VER		0x38
 #define QLCNIC_CMD_GET_LED_STATUS		0x3C
 #define QLCNIC_CMD_CONFIGURE_RSS		0x41
 #define QLCNIC_CMD_CONFIG_INTR_COAL		0x43
@@ -103,6 +103,7 @@ enum qlcnic_regs {
 #define QLCNIC_CMD_GET_LINK_STATUS		0x68
 #define QLCNIC_CMD_SET_LED_CONFIG		0x69
 #define QLCNIC_CMD_GET_LED_CONFIG		0x6A
+#define QLCNIC_CMD_83XX_SET_DRV_VER		0x6F
 #define QLCNIC_CMD_ADD_RCV_RINGS		0x0B
 
 #define QLCNIC_INTRPT_INTX			1
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 97d633a..6859836 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -1985,6 +1985,21 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter,
 	return 0;
 }
 
+void qlcnic_set_drv_version(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	u32 fw_cmd = 0;
+
+	if (qlcnic_82xx_check(adapter))
+		fw_cmd = QLCNIC_CMD_82XX_SET_DRV_VER;
+	else if (qlcnic_83xx_check(adapter))
+		fw_cmd = QLCNIC_CMD_83XX_SET_DRV_VER;
+
+	if ((ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) &&
+	    (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER))
+		qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
+}
+
 static int
 qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -1992,7 +2007,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct qlcnic_adapter *adapter = NULL;
 	struct qlcnic_hardware_context *ahw;
 	int err, pci_using_dac = -1;
-	u32 capab2;
 	char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */
 
 	if (pdev->is_virtfn)
@@ -2147,13 +2161,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_out_disable_mbx_intr;
 
-	if (qlcnic_82xx_check(adapter)) {
-		if (ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
-			capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
-			if (capab2 & QLCNIC_FW_CAPABILITY_2_OCBB)
-				qlcnic_fw_cmd_set_drv_version(adapter);
-		}
-	}
+	qlcnic_set_drv_version(adapter);
 
 	pci_set_drvdata(pdev, adapter);
 
@@ -3124,6 +3132,7 @@ done:
 	adapter->fw_fail_cnt = 0;
 	adapter->flags &= ~QLCNIC_FW_HANG;
 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+	qlcnic_set_drv_version(adapter);
 
 	if (!qlcnic_clr_drv_state(adapter))
 		qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
-- 
1.7.1

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

* [PATCH net-next 7/8] qlcnic: Add support for 83xx suspend and resume.
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
                   ` (5 preceding siblings ...)
  2013-06-21 16:30 ` [PATCH net-next 6/8] qlcnic: Add support for 'set driver version' in 83XX Jitendra Kalsaria
@ 2013-06-21 16:31 ` Jitendra Kalsaria
  2013-06-21 16:31 ` [PATCH net-next 8/8] qlcnic: Update version to 5.2.44 Jitendra Kalsaria
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Rajesh Borundia

From: Rajesh Borundia <rajesh.borundia@qlogic.com>

o Implement shutdown and resume handlers for 83xx.
o Refactor 82xx shutdown and resume handlers.

Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h        |   14 ++++
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c    |   53 ++++++++++++++++
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h    |    6 ++
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c  |   17 ++++-
 .../net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c  |   23 +++++++-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |   51 +++++++++++++++
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h     |    4 +
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |   66 ++-----------------
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h  |    2 +
 .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c   |   53 ++++++++++++++++
 10 files changed, 225 insertions(+), 64 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 45d9329..57762b9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -1596,6 +1596,8 @@ struct qlcnic_nic_template {
 	void (*napi_del)(struct qlcnic_adapter *);
 	void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int);
 	irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *);
+	int (*shutdown)(struct pci_dev *);
+	int (*resume)(struct qlcnic_adapter *);
 };
 
 /* Adapter hardware abstraction */
@@ -1800,6 +1802,18 @@ static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
 	adapter->ahw->hw_ops->napi_enable(adapter);
 }
 
+static inline int __qlcnic_shutdown(struct pci_dev *pdev)
+{
+	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+
+	return adapter->nic_ops->shutdown(pdev);
+}
+
+static inline int __qlcnic_resume(struct qlcnic_adapter *adapter)
+{
+	return adapter->nic_ops->resume(adapter);
+}
+
 static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
 {
 	adapter->ahw->hw_ops->napi_disable(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index a1887e4..969489f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -186,6 +186,8 @@ static struct qlcnic_nic_template qlcnic_83xx_ops = {
 	.napi_del		= qlcnic_83xx_napi_del,
 	.config_ipaddr		= qlcnic_83xx_config_ipaddr,
 	.clear_legacy_intr	= qlcnic_83xx_clear_legacy_intr,
+	.shutdown		= qlcnic_83xx_shutdown,
+	.resume			= qlcnic_83xx_resume,
 };
 
 void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
@@ -3393,3 +3395,54 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
 	}
 	return 0;
 }
+
+int qlcnic_83xx_shutdown(struct pci_dev *pdev)
+{
+	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
+	int retval;
+
+	netif_device_detach(netdev);
+	qlcnic_cancel_idc_work(adapter);
+
+	if (netif_running(netdev))
+		qlcnic_down(adapter, netdev);
+
+	qlcnic_83xx_disable_mbx_intr(adapter);
+	cancel_delayed_work_sync(&adapter->idc_aen_work);
+
+	retval = pci_save_state(pdev);
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlc_83xx_idc *idc = &ahw->idc;
+	int err = 0;
+
+	err = qlcnic_83xx_idc_init(adapter);
+	if (err)
+		return err;
+
+	if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) {
+		if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
+			qlcnic_83xx_set_vnic_opmode(adapter);
+		} else {
+			err = qlcnic_83xx_check_vnic_state(adapter);
+			if (err)
+				return err;
+		}
+	}
+
+	err = qlcnic_83xx_idc_reattach_driver(adapter);
+	if (err)
+		return err;
+
+	qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
+			     idc->delay);
+	return err;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index e356ee8..2548d14 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -628,4 +628,10 @@ u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
 void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
 void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
+int qlcnic_83xx_shutdown(struct pci_dev *);
+int qlcnic_83xx_resume(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *);
+int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *);
+int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *);
 #endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index e2d04d5..f41dfab 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -606,7 +606,7 @@ static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
 {
 	int err;
 
@@ -1135,7 +1135,7 @@ qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
 {
 	int ret = -EIO;
 
@@ -1554,9 +1554,18 @@ static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev)
 
 int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
 {
-	u8 *p_buff;
-	u32 addr, count;
 	struct qlcnic_hardware_context *ahw = p_dev->ahw;
+	u32 addr, count, prev_ver, curr_ver;
+	u8 *p_buff;
+
+	if (ahw->reset.buff != NULL) {
+		prev_ver = p_dev->fw_version;
+		curr_ver = qlcnic_83xx_get_fw_version(p_dev);
+		if (curr_ver > prev_ver)
+			kfree(ahw->reset.buff);
+		else
+			return 0;
+	}
 
 	ahw->reset.seq_error = 0;
 	ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
index b5054e1..599d1fd 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
@@ -39,7 +39,7 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
 	return 0;
 }
 
-static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
 {
 	u8 id;
 	int ret = -EBUSY;
@@ -218,3 +218,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
 
 	return 0;
 }
+
+int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
+{
+	struct qlcnic_hardware_context *ahw = adapter->ahw;
+	struct qlc_83xx_idc *idc = &ahw->idc;
+	u32 state;
+
+	state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
+	while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) {
+		msleep(1000);
+		state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
+	}
+
+	if (!idc->vnic_wait_limit) {
+		dev_err(&adapter->pdev->dev,
+			"vNIC mode not operational, state check timed out.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index 9fcbfd4..5b5d2ed 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -1577,3 +1577,54 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *adapter)
 {
 	qlcnic_pcie_sem_unlock(adapter, 5);
 }
+
+int qlcnic_82xx_shutdown(struct pci_dev *pdev)
+{
+	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
+	int retval;
+
+	netif_device_detach(netdev);
+
+	qlcnic_cancel_idc_work(adapter);
+
+	if (netif_running(netdev))
+		qlcnic_down(adapter, netdev);
+
+	qlcnic_clr_all_drv_state(adapter, 0);
+
+	clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+	retval = pci_save_state(pdev);
+	if (retval)
+		return retval;
+
+	if (qlcnic_wol_supported(adapter)) {
+		pci_enable_wake(pdev, PCI_D3cold, 1);
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+	}
+
+	return 0;
+}
+
+int qlcnic_82xx_resume(struct qlcnic_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err;
+
+	err = qlcnic_start_firmware(adapter);
+	if (err) {
+		dev_err(&adapter->pdev->dev, "failed to start firmware\n");
+		return err;
+	}
+
+	if (netif_running(netdev)) {
+		err = qlcnic_up(adapter, netdev);
+		if (!err)
+			qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+	}
+
+	netif_device_attach(netdev);
+	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+	return err;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index b190c84..2c22504 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -199,4 +199,8 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *);
 void qlcnic_82xx_napi_enable(struct qlcnic_adapter *);
 void qlcnic_82xx_napi_disable(struct qlcnic_adapter *);
 void qlcnic_82xx_napi_del(struct qlcnic_adapter *);
+int qlcnic_82xx_shutdown(struct pci_dev *);
+int qlcnic_82xx_resume(struct qlcnic_adapter *);
+void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed);
+void qlcnic_fw_poll_work(struct work_struct *work);
 #endif				/* __QLCNIC_HW_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 6859836..fe0f1f8 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -59,13 +59,11 @@ static int qlcnic_close(struct net_device *netdev);
 static void qlcnic_tx_timeout(struct net_device *netdev);
 static void qlcnic_attach_work(struct work_struct *work);
 static void qlcnic_fwinit_work(struct work_struct *work);
-static void qlcnic_fw_poll_work(struct work_struct *work);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev);
 #endif
 
 static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
-static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
 static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
 
 static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
@@ -469,6 +467,8 @@ static struct qlcnic_nic_template qlcnic_ops = {
 	.napi_add		= qlcnic_82xx_napi_add,
 	.napi_del		= qlcnic_82xx_napi_del,
 	.config_ipaddr		= qlcnic_82xx_config_ipaddr,
+	.shutdown		= qlcnic_82xx_shutdown,
+	.resume			= qlcnic_82xx_resume,
 	.clear_legacy_intr	= qlcnic_82xx_clear_legacy_intr,
 };
 
@@ -2277,37 +2277,6 @@ static void qlcnic_remove(struct pci_dev *pdev)
 	kfree(ahw);
 	free_netdev(netdev);
 }
-static int __qlcnic_shutdown(struct pci_dev *pdev)
-{
-	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev = adapter->netdev;
-	int retval;
-
-	netif_device_detach(netdev);
-
-	qlcnic_cancel_idc_work(adapter);
-
-	if (netif_running(netdev))
-		qlcnic_down(adapter, netdev);
-
-	qlcnic_sriov_cleanup(adapter);
-	if (qlcnic_82xx_check(adapter))
-		qlcnic_clr_all_drv_state(adapter, 0);
-
-	clear_bit(__QLCNIC_RESETTING, &adapter->state);
-
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-	if (qlcnic_82xx_check(adapter)) {
-		if (qlcnic_wol_supported(adapter)) {
-			pci_enable_wake(pdev, PCI_D3cold, 1);
-			pci_enable_wake(pdev, PCI_D3hot, 1);
-		}
-	}
-
-	return 0;
-}
 
 static void qlcnic_shutdown(struct pci_dev *pdev)
 {
@@ -2318,8 +2287,7 @@ static void qlcnic_shutdown(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int
-qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
+static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	int retval;
 
@@ -2331,11 +2299,9 @@ qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
 	return 0;
 }
 
-static int
-qlcnic_resume(struct pci_dev *pdev)
+static int qlcnic_resume(struct pci_dev *pdev)
 {
 	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev = adapter->netdev;
 	int err;
 
 	err = pci_enable_device(pdev);
@@ -2346,23 +2312,7 @@ qlcnic_resume(struct pci_dev *pdev)
 	pci_set_master(pdev);
 	pci_restore_state(pdev);
 
-	err = qlcnic_start_firmware(adapter);
-	if (err) {
-		dev_err(&pdev->dev, "failed to start firmware\n");
-		return err;
-	}
-
-	if (netif_running(netdev)) {
-		err = qlcnic_up(adapter, netdev);
-		if (err)
-			goto done;
-
-		qlcnic_restore_indev_addr(netdev, NETDEV_UP);
-	}
-done:
-	netif_device_attach(netdev);
-	qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
-	return 0;
+	return  __qlcnic_resume(adapter);
 }
 #endif
 
@@ -2701,8 +2651,7 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter)
 	return 0;
 }
 
-static void
-qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
+void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
 {
 	u32  val;
 
@@ -3213,8 +3162,7 @@ detach:
 	return 1;
 }
 
-static void
-qlcnic_fw_poll_work(struct work_struct *work)
+void qlcnic_fw_poll_work(struct work_struct *work)
 {
 	struct qlcnic_adapter *adapter = container_of(work,
 				struct qlcnic_adapter, fw_work.work);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
index 9176cb0..0daf660 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -195,6 +195,8 @@ int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *,
 int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
 				   struct qlcnic_info *, u16);
 int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
+int qlcnic_sriov_vf_shutdown(struct pci_dev *);
+int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
 
 static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
 {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index bcd200e..d556249 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -76,6 +76,8 @@ static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
 	.cancel_idc_work        = qlcnic_sriov_vf_cancel_fw_work,
 	.napi_add		= qlcnic_83xx_napi_add,
 	.napi_del		= qlcnic_83xx_napi_del,
+	.shutdown		= qlcnic_sriov_vf_shutdown,
+	.resume			= qlcnic_sriov_vf_resume,
 	.config_ipaddr		= qlcnic_83xx_config_ipaddr,
 	.clear_legacy_intr	= qlcnic_83xx_clear_legacy_intr,
 };
@@ -1954,3 +1956,54 @@ static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter)
 		kfree(cur);
 	}
 }
+
+int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev)
+{
+	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+	struct net_device *netdev = adapter->netdev;
+	int retval;
+
+	netif_device_detach(netdev);
+	qlcnic_cancel_idc_work(adapter);
+
+	if (netif_running(netdev))
+		qlcnic_down(adapter, netdev);
+
+	qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM);
+	qlcnic_sriov_cfg_bc_intr(adapter, 0);
+	qlcnic_83xx_disable_mbx_intr(adapter);
+	cancel_delayed_work_sync(&adapter->idc_aen_work);
+
+	retval = pci_save_state(pdev);
+	if (retval)
+		return retval;
+
+	return 0;
+}
+
+int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter)
+{
+	struct qlc_83xx_idc *idc = &adapter->ahw->idc;
+	struct net_device *netdev = adapter->netdev;
+	int err;
+
+	set_bit(QLC_83XX_MODULE_LOADED, &idc->status);
+	qlcnic_83xx_enable_mbx_intrpt(adapter);
+	err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
+	if (err)
+		return err;
+
+	err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT);
+	if (!err) {
+		if (netif_running(netdev)) {
+			err = qlcnic_up(adapter, netdev);
+			if (!err)
+				qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+		}
+	}
+
+	netif_device_attach(netdev);
+	qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state,
+			     idc->delay);
+	return err;
+}
-- 
1.7.1

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

* [PATCH net-next 8/8] qlcnic: Update version to 5.2.44
  2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
                   ` (6 preceding siblings ...)
  2013-06-21 16:31 ` [PATCH net-next 7/8] qlcnic: Add support for 83xx suspend and resume Jitendra Kalsaria
@ 2013-06-21 16:31 ` Jitendra Kalsaria
  7 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 16:31 UTC (permalink / raw)
  To: davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver,
	Jitendra Kalsaria

From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>

Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 57762b9..d59be02 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -38,8 +38,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 2
-#define _QLCNIC_LINUX_SUBVERSION 43
-#define QLCNIC_LINUX_VERSIONID  "5.2.43"
+#define _QLCNIC_LINUX_SUBVERSION 44
+#define QLCNIC_LINUX_VERSIONID  "5.2.44"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
 		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
-- 
1.7.1

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

* Re: [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support.
  2013-06-21 16:30 ` [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support Jitendra Kalsaria
@ 2013-06-21 17:10   ` Joe Perches
  2013-06-21 17:45     ` Jitendra Kalsaria
  0 siblings, 1 reply; 15+ messages in thread
From: Joe Perches @ 2013-06-21 17:10 UTC (permalink / raw)
  To: Jitendra Kalsaria
  Cc: davem, netdev, sony.chacko, shahed.shaikh,
	Dept_NX_Linux_NIC_Driver

On Fri, 2013-06-21 at 12:30 -0400, Jitendra Kalsaria wrote:
> From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
> 
> Add support for configuring secondary unicast address which
> will use existing HW filters to store all the unicast MAC
> addresses and prevent device going into promiscuous mode.

[]

> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
[]
> @@ -421,6 +421,7 @@ struct qlcnic_hardware_context {
> +	u8 max_uc_count;

> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
[]
> +#define QLC_83XX_MAX_UC_COUNT			4096

> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
[]
> +#define QLCNIC_MAX_UC_COUNT		512

These #defines don't seem right.
There's no way to fit these values in a u8.

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

* Re: [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support.
  2013-06-21 17:10   ` Joe Perches
@ 2013-06-21 17:45     ` Jitendra Kalsaria
  0 siblings, 0 replies; 15+ messages in thread
From: Jitendra Kalsaria @ 2013-06-21 17:45 UTC (permalink / raw)
  To: Joe Perches
  Cc: David Miller, netdev, Sony Chacko, Shahed Shaikh,
	Dept-NX Linux NIC Driver

On 6/21/13 10:10 AM, "Joe Perches" <joe@perches.com> wrote:

>On Fri, 2013-06-21 at 12:30 -0400, Jitendra Kalsaria wrote:
>> From: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
>> 
>> Add support for configuring secondary unicast address which
>> will use existing HW filters to store all the unicast MAC
>> addresses and prevent device going into promiscuous mode.
>
>[]
>
>> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
>>b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
>[]
>> @@ -421,6 +421,7 @@ struct qlcnic_hardware_context {
>> +	u8 max_uc_count;
>
>> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
>>b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
>[]
>> +#define QLC_83XX_MAX_UC_COUNT			4096
>
>> diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
>>b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
>[]
>> +#define QLCNIC_MAX_UC_COUNT		512
>
>These #defines don't seem right.
>There's no way to fit these values in a u8.

Thanks for pointing it, I will fix it and resubmit these series again.

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

* RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump
  2013-06-21 16:30 ` [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump Jitendra Kalsaria
@ 2013-06-24  8:56   ` David Laight
  2013-06-26 23:43     ` Shahed Shaikh
  0 siblings, 1 reply; 15+ messages in thread
From: David Laight @ 2013-06-24  8:56 UTC (permalink / raw)
  To: Jitendra Kalsaria, davem
  Cc: netdev, sony.chacko, shahed.shaikh, Dept_NX_Linux_NIC_Driver

> From: Shahed Shaikh <shahed.shaikh@qlogic.com>
> 
> This patch adds support to read memory section of adapter
> dump using PEX DMA method. This method significantly improves
> total adapter dump collection time.

Which DMA engine is this using?
My first thought was that it was the one in the CSB bridge
(which ought to have a shared interface), but the structures
don't seem to match the code I have for that.

...
> +struct qlcnic_pex_dma_descriptor {
> +	u32	read_data_size;
> +	u32	dma_desc_cmd;
> +	u32	src_addr_low;
> +	u32	src_addr_high;
> +	u32	dma_bus_addr_low;
> +	u32	dma_bus_addr_high;
> +	u32	rsvd[6];
> +} __packed;

Why __packed??
Why are the structures following also marked __packed.

...
> +	/* Wait for DMA to complete */
> +	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;
> +	for (i = 0; i < 400; i++) {
> +		dma_sts = qlcnic_ind_rd(adapter, temp_addr);
> +
> +		if (dma_sts & BIT_1)
> +			usleep_range(250, 500);
> +		else
> +			break;
> +	}

Do these DMA actually take long enough to need to sleep
for completion?
I'd have thought that they'd normally finish almost immediately.
Sleeping might be reasonable as a 'last hope' check.

I'd also consider putting the 'wait for complete' code into
a separate function - allowing overlapped operations.

...
> +
> +	if ((tmpl_hdr->version & 0xffffff) >= 0x20001)
> +		ahw->fw_dump.use_pex_dma = true;
> +	else
> +		ahw->fw_dump.use_pex_dma = false;

You know what's wrong with the above....

	David

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

* RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump
  2013-06-24  8:56   ` David Laight
@ 2013-06-26 23:43     ` Shahed Shaikh
  2013-06-27  8:56       ` David Laight
  0 siblings, 1 reply; 15+ messages in thread
From: Shahed Shaikh @ 2013-06-26 23:43 UTC (permalink / raw)
  To: David Laight, Jitendra Kalsaria, David Miller
  Cc: netdev, Sony Chacko, Dept-NX Linux NIC Driver

> -----Original Message-----
> From: David Laight [mailto:David.Laight@ACULAB.COM]
> Sent: Monday, June 24, 2013 1:56 AM
> To: Jitendra Kalsaria; David Miller
> Cc: netdev; Sony Chacko; Shahed Shaikh; Dept-NX Linux NIC Driver
> Subject: RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method
> to read memory section of adapter dump
> 
> > From: Shahed Shaikh <shahed.shaikh@qlogic.com>
> >
> > This patch adds support to read memory section of adapter dump using
> > PEX DMA method. This method significantly improves total adapter dump
> > collection time.
> 
> Which DMA engine is this using?
> My first thought was that it was the one in the CSB bridge (which ought to
> have a shared interface), but the structures don't seem to match the code I
> have for that.
> 

It's not the one in the CSB bridge.

> ...
> > +struct qlcnic_pex_dma_descriptor {
> > +	u32	read_data_size;
> > +	u32	dma_desc_cmd;
> > +	u32	src_addr_low;
> > +	u32	src_addr_high;
> > +	u32	dma_bus_addr_low;
> > +	u32	dma_bus_addr_high;
> > +	u32	rsvd[6];
> > +} __packed;
> 
> Why __packed??
> Why are the structures following also marked __packed.
> 

 No need of __packed. Will remove in follow up patch.

> ...
> > +	/* Wait for DMA to complete */
> > +	temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL;
> > +	for (i = 0; i < 400; i++) {
> > +		dma_sts = qlcnic_ind_rd(adapter, temp_addr);
> > +
> > +		if (dma_sts & BIT_1)
> > +			usleep_range(250, 500);
> > +		else
> > +			break;
> > +	}
> 
> Do these DMA actually take long enough to need to sleep for completion?
> I'd have thought that they'd normally finish almost immediately.
> Sleeping might be reasonable as a 'last hope' check.
> 

We need to call sleep to cover worst case scenarios and we have encountered issues without sleep.
In the follow up patch we will be using usleep_range(50, 100).

> I'd also consider putting the 'wait for complete' code into a separate function
> - allowing overlapped operations.
> 

Sure. I will create a separate function.

> ...
> > +
> > +	if ((tmpl_hdr->version & 0xffffff) >= 0x20001)
> > +		ahw->fw_dump.use_pex_dma = true;
> > +	else
> > +		ahw->fw_dump.use_pex_dma = false;
> 
> You know what's wrong with the above....

Yes. Got it.  Masking is not done properly. It should be
if ((tmpl_hdr->version & 0xfffff) >= 0x20001)

Thanks for review comments.

-Shahed
> 
> 	David

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

* RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump
  2013-06-26 23:43     ` Shahed Shaikh
@ 2013-06-27  8:56       ` David Laight
  2013-06-27 14:29         ` Shahed Shaikh
  0 siblings, 1 reply; 15+ messages in thread
From: David Laight @ 2013-06-27  8:56 UTC (permalink / raw)
  To: Shahed Shaikh, Jitendra Kalsaria, David Miller
  Cc: netdev, Sony Chacko, Dept-NX Linux NIC Driver

> > > +	if ((tmpl_hdr->version & 0xffffff) >= 0x20001)
> > > +		ahw->fw_dump.use_pex_dma = true;
> > > +	else
> > > +		ahw->fw_dump.use_pex_dma = false;
> >
> > You know what's wrong with the above....
> 
> Yes. Got it.  Masking is not done properly. It should be
> if ((tmpl_hdr->version & 0xfffff) >= 0x20001)

Try:
	ahw->fw_dump.use_pex_dma = (tmpl_hdr->version & 0xfffff) >= 0x20001;

	David

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

* RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump
  2013-06-27  8:56       ` David Laight
@ 2013-06-27 14:29         ` Shahed Shaikh
  0 siblings, 0 replies; 15+ messages in thread
From: Shahed Shaikh @ 2013-06-27 14:29 UTC (permalink / raw)
  To: David Laight, Jitendra Kalsaria, David Miller
  Cc: netdev, Sony Chacko, Dept-NX Linux NIC Driver



> -----Original Message-----
> From: David Laight [mailto:David.Laight@ACULAB.COM]
> Sent: Thursday, June 27, 2013 1:56 AM
> To: Shahed Shaikh; Jitendra Kalsaria; David Miller
> Cc: netdev; Sony Chacko; Dept-NX Linux NIC Driver
> Subject: RE: [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method
> to read memory section of adapter dump
> 
> > > > +	if ((tmpl_hdr->version & 0xffffff) >= 0x20001)
> > > > +		ahw->fw_dump.use_pex_dma = true;
> > > > +	else
> > > > +		ahw->fw_dump.use_pex_dma = false;
> > >
> > > You know what's wrong with the above....
> >
> > Yes. Got it.  Masking is not done properly. It should be if
> > ((tmpl_hdr->version & 0xfffff) >= 0x20001)
> 
> Try:
> 	ahw->fw_dump.use_pex_dma = (tmpl_hdr->version & 0xfffff) >=
> 0x20001;
> 
Ok. Thanks David.

-Shahed

> 	David
> 
> 
> 

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

end of thread, other threads:[~2013-06-27 14:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-21 16:30 [PATCH net-next 0/8] qlcnic: Driver updates Jitendra Kalsaria
2013-06-21 16:30 ` [PATCH net-next 1/8] qlcnic: Handle qlcnic_alloc_mbx_args() failure Jitendra Kalsaria
2013-06-21 16:30 ` [PATCH net-next 2/8] qlcnic: Secondary unicast MAC address support Jitendra Kalsaria
2013-06-21 17:10   ` Joe Perches
2013-06-21 17:45     ` Jitendra Kalsaria
2013-06-21 16:30 ` [PATCH net-next 3/8] qlcnic: Minimize sleep duration within loopback diagnostic test Jitendra Kalsaria
2013-06-21 16:30 ` [PATCH net-next 4/8] qlcnic: Add support for PEX DMA method to read memory section of adapter dump Jitendra Kalsaria
2013-06-24  8:56   ` David Laight
2013-06-26 23:43     ` Shahed Shaikh
2013-06-27  8:56       ` David Laight
2013-06-27 14:29         ` Shahed Shaikh
2013-06-21 16:30 ` [PATCH net-next 5/8] qlcnic: Cleanup of structure qlcnic_hardware_context Jitendra Kalsaria
2013-06-21 16:30 ` [PATCH net-next 6/8] qlcnic: Add support for 'set driver version' in 83XX Jitendra Kalsaria
2013-06-21 16:31 ` [PATCH net-next 7/8] qlcnic: Add support for 83xx suspend and resume Jitendra Kalsaria
2013-06-21 16:31 ` [PATCH net-next 8/8] qlcnic: Update version to 5.2.44 Jitendra Kalsaria

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).