Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e2842f4 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qlcnic'



Shahed Shaikh says:

====================
This patch series includes following changes:
* Support for spoof check configuration per VF using
  iproute2 tool.
* Set HW mask for 8300 adapter in INT-x mode to stop generating
  interrupts.
* Updated IRQ name for 8200 and 8300 Series adapter as per
  format used by other multiqueue drivers.
* Remove qlcnic_config_npars module parameter.
* Initialize trans_work and idc_aen_work at VF probe.
* Convert netsted if-else into switch-case statement.
* Change in diagnostics routine.
* Modify reset recovery path in diag mode by providing diagnostics
  routines enough time to unwind before proceeding with reset recovery.
* Implement GET_LED_STATUS command for 82xx adapter and refactor
  qlcnic_store_beacon() to split 8200 and 8300 specific calls.
* Some cleanup and log enhancements
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f2068b80 6a531b7b
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@

#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 2
#define _QLCNIC_LINUX_SUBVERSION 42
#define QLCNIC_LINUX_VERSIONID  "5.2.42"
#define _QLCNIC_LINUX_SUBVERSION 43
#define QLCNIC_LINUX_VERSIONID  "5.2.43"
#define QLCNIC_DRV_IDC_VER  0x01
#define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -303,7 +303,6 @@ extern int qlcnic_use_msi;
extern int qlcnic_use_msi_x;
extern int qlcnic_auto_fw_reset;
extern int qlcnic_load_fw_file;
extern int qlcnic_config_npars;

/* Number of status descriptors to handle per interrupt */
#define MAX_STATUS_HANDLE	(64)
@@ -443,6 +442,7 @@ struct qlcnic_hardware_context {
	u16 max_mtu;
	u32 msg_enable;
	u16 act_pci_func;
	u16 max_pci_func;

	u32 capabilities;
	u32 capabilities2;
@@ -816,6 +816,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_2_BEACON		BIT_7

/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT			1
@@ -913,6 +914,9 @@ struct qlcnic_ipaddr {
#define QLCNIC_IS_TSO_CAPABLE(adapter)  \
	((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)

#define QLCNIC_BEACON_EANBLE		0xC
#define QLCNIC_BEACON_DISABLE		0xD

#define QLCNIC_DEF_NUM_STS_DESC_RINGS	4
#define QLCNIC_MSIX_TBL_SPACE		8192
#define QLCNIC_PCI_REG_MSIX_TBL 	0x44
@@ -932,6 +936,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_SRIOV_ENABLE		10
#define __QLCNIC_SRIOV_CAPABLE		11
#define __QLCNIC_MBX_POLL_ENABLE	12
#define __QLCNIC_DIAG_MODE		13

#define QLCNIC_INTERRUPT_TEST		1
#define QLCNIC_LOOPBACK_TEST		2
@@ -1543,6 +1548,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *);
int qlcnic_reset_npar_config(struct qlcnic_adapter *);
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *);
void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *);
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
@@ -1886,6 +1892,21 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
		writel(0xfbff, adapter->tgt_mask_reg);
}

static inline int qlcnic_get_diag_lock(struct qlcnic_adapter *adapter)
{
	return test_and_set_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}

static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter)
{
	clear_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}

static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter)
{
	return test_bit(__QLCNIC_DIAG_MODE, &adapter->state);
}

extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
+47 −30
Original line number Diff line number Diff line
@@ -312,6 +312,11 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
	writel(0, adapter->tgt_mask_reg);
}

inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
{
	writel(1, adapter->tgt_mask_reg);
}

/* Enable MSI-x and INT-x interrupts */
void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter,
			     struct qlcnic_host_sds_ring *sds_ring)
@@ -458,6 +463,9 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
{
	u32 num_msix;

	if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
		qlcnic_83xx_set_legacy_intr_mask(adapter);

	qlcnic_83xx_disable_mbx_intr(adapter);

	if (adapter->flags & QLCNIC_MSIX_ENABLED)
@@ -474,7 +482,6 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
{
	irq_handler_t handler;
	u32 val;
	char name[32];
	int err = 0;
	unsigned long flags = 0;

@@ -485,9 +492,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
		handler = qlcnic_83xx_handle_aen;
		val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
		snprintf(name, (IFNAMSIZ + 4),
			 "%s[%s]", "qlcnic", "aen");
		err = request_irq(val, handler, flags, name, adapter);
		err = request_irq(val, handler, flags, "qlcnic-MB", adapter);
		if (err) {
			dev_err(&adapter->pdev->dev,
				"failed to register MBX interrupt\n");
@@ -1588,16 +1593,24 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings;

	QLCDB(adapter, DRV, "%s loopback test in progress\n",
	      mode == QLCNIC_ILB_MODE ? "internal" : "external");
	if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
		dev_warn(&adapter->pdev->dev,
			 "Loopback test not supported for non privilege function\n");
		netdev_warn(netdev,
			    "Loopback test not supported in non privileged mode\n");
		return ret;
	}

	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
		netdev_info(netdev, "Device is resetting\n");
		return -EBUSY;
	}

	if (qlcnic_get_diag_lock(adapter)) {
		netdev_info(netdev, "Device is in diagnostics mode\n");
		return -EBUSY;
	}

	netdev_info(netdev, "%s loopback test in progress\n",
		    mode == QLCNIC_ILB_MODE ? "internal" : "external");

	ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
					 max_sds_rings);
@@ -1638,7 +1651,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)

fail_diag_alloc:
	adapter->max_sds_rings = max_sds_rings;
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	qlcnic_release_diag_lock(adapter);
	return ret;
}

@@ -2121,26 +2134,25 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
			     struct qlcnic_pci_info *pci_info)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct device *dev = &adapter->pdev->dev;
	struct qlcnic_cmd_args cmd;
	int i, err = 0, j = 0;
	u32 temp;
	struct qlcnic_cmd_args cmd;

	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
	err = qlcnic_issue_cmd(adapter, &cmd);

	adapter->ahw->act_pci_func = 0;
	ahw->act_pci_func = 0;
	if (err == QLCNIC_RCODE_SUCCESS) {
		pci_info->func_count = cmd.rsp.arg[1] & 0xFF;
		dev_info(&adapter->pdev->dev,
			 "%s: total functions = %d\n",
			 __func__, pci_info->func_count);
		ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
		for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) {
			pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
			pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
			i++;
			pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
			if (pci_info->type == QLCNIC_TYPE_NIC)
				adapter->ahw->act_pci_func++;
				ahw->act_pci_func++;
			temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
			pci_info->default_port = temp;
			i++;
@@ -2152,18 +2164,21 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
			i++;
			memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
			i = i + 3;

			dev_info(&adapter->pdev->dev, "%s:\n"
				 "\tid = %d active = %d type = %d\n"
			if (ahw->op_mode == QLCNIC_MGMT_FUNC)
				dev_info(dev, "id = %d active = %d type = %d\n"
					 "\tport = %d min bw = %d max bw = %d\n"
				 "\tmac_addr =  %pM\n", __func__,
				 pci_info->id, pci_info->active, pci_info->type,
				 pci_info->default_port, pci_info->tx_min_bw,
					 "\tmac_addr =  %pM\n", pci_info->id,
					 pci_info->active, pci_info->type,
					 pci_info->default_port,
					 pci_info->tx_min_bw,
					 pci_info->tx_max_bw, pci_info->mac);
		}
		if (ahw->op_mode == QLCNIC_MGMT_FUNC)
			dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n",
				 ahw->max_pci_func, ahw->act_pci_func);

	} else {
		dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n",
			err);
		dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
		err = -EIO;
	}

@@ -3113,8 +3128,10 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)
	u8 val;
	int ret, max_sds_rings = adapter->max_sds_rings;

	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
		return -EIO;
	if (qlcnic_get_diag_lock(adapter)) {
		netdev_info(netdev, "Device in diagnostics mode\n");
		return -EBUSY;
	}

	ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
					 max_sds_rings);
@@ -3156,7 +3173,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev)

fail_diag_irq:
	adapter->max_sds_rings = max_sds_rings;
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	qlcnic_release_diag_lock(adapter);
	return ret;
}

+1 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ struct qlc_83xx_idc {
	u8		vnic_state;
	u8		vnic_wait_limit;
	u8		quiesce_req;
	u8		delay_reset;
	char		**name;
};

+28 −7
Original line number Diff line number Diff line
@@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
	ahw->idc.collect_dump = 0;
	ahw->reset_context = 0;
	adapter->tx_timeo_cnt = 0;
	ahw->idc.delay_reset = 0;

	clear_bit(__QLCNIC_RESETTING, &adapter->state);
}
@@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
	int ret = 0;

	if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
		qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
		qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
		set_bit(__QLCNIC_RESETTING, &adapter->state);
		clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
		if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
			qlcnic_83xx_disable_vnic_mode(adapter, 1);

		if (qlcnic_check_diag_status(adapter)) {
			dev_info(&adapter->pdev->dev,
				 "%s: Wait for diag completion\n", __func__);
			adapter->ahw->idc.delay_reset = 1;
			return 0;
		} else {
			qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
			qlcnic_83xx_idc_detach_driver(adapter);
		}
	}

	/* Check ACK from other functions */
	if (qlcnic_check_diag_status(adapter)) {
		dev_info(&adapter->pdev->dev,
			 "%s: Wait for diag completion\n", __func__);
		return  -1;
	} else {
		if (adapter->ahw->idc.delay_reset) {
			qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1);
			qlcnic_83xx_idc_detach_driver(adapter);
			adapter->ahw->idc.delay_reset = 0;
		}

		/* Check for ACK from other functions */
		ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter);
		if (ret) {
			dev_info(&adapter->pdev->dev,
				 "%s: Waiting for reset ACK\n", __func__);
		return 0;
			return -1;
		}
	}

	/* Transit to INIT state and restart the HW */
+17 −22
Original line number Diff line number Diff line
@@ -42,27 +42,18 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
{
	u8 id;
	int i, ret = -EBUSY;
	int ret = -EBUSY;
	u32 data = QLCNIC_MGMT_FUNC;
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (qlcnic_83xx_lock_driver(adapter))
		return ret;

	if (qlcnic_config_npars) {
		for (i = 0; i < ahw->act_pci_func; i++) {
			id = adapter->npars[i].pci_func;
			if (id == ahw->pci_func)
				continue;
			data |= qlcnic_config_npars &
				QLC_83XX_SET_FUNC_OPMODE(0x3, id);
		}
	} else {
	id = ahw->pci_func;
	data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
		data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) |
		       QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC,
						ahw->pci_func);
	}
	data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) |
	       QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id);

	QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);

	qlcnic_83xx_unlock_driver(adapter);
@@ -196,20 +187,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
	else
		priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
							 ahw->pci_func);

	if (priv_level == QLCNIC_NON_PRIV_FUNC) {
	switch (priv_level) {
	case QLCNIC_NON_PRIV_FUNC:
		ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
		nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
	} else if (priv_level == QLCNIC_PRIV_FUNC) {
		break;
	case QLCNIC_PRIV_FUNC:
		ahw->op_mode = QLCNIC_PRIV_FUNC;
		ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
		nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
	} else if (priv_level == QLCNIC_MGMT_FUNC) {
		break;
	case QLCNIC_MGMT_FUNC:
		ahw->op_mode = QLCNIC_MGMT_FUNC;
		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
		nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
	} else {
		break;
	default:
		dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n");
		return -EIO;
	}

@@ -218,8 +213,8 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
	else
		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;

	adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
	adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
	ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
	ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;

	return 0;
}
Loading