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

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

Merge branch 'qlcnic'



Shahed Shaikh says:

====================
This patch series contains -
* Enhanced PVID handling for 84xx adapters by
  not indicating PVID configuration to VF driver and
  keeping VF driver in no VLAN configuration mode becasue
  adapter supports VLAN stripping.
* Removed inappropriate usage of inline keyword.
* Enhanced minidump feature by using firmware recommended
  dump capture mask and using CAMRAM register to store
  firmware dump state.
* AER handling support for 83xx adapter.
* Added support for per port eswitch configuration.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eb3c0d83 693dcd2f
Loading
Loading
Loading
Loading
+24 −5
Original line number Diff line number Diff line
@@ -38,8 +38,8 @@

#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 3
#define _QLCNIC_LINUX_SUBVERSION 49
#define QLCNIC_LINUX_VERSIONID  "5.3.49"
#define _QLCNIC_LINUX_SUBVERSION 50
#define QLCNIC_LINUX_VERSIONID  "5.3.50"
#define QLCNIC_DRV_IDC_VER  0x01
#define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr {

struct qlcnic_fw_dump {
	u8	clr;	/* flag to indicate if dump is cleared */
	u8	enable; /* enable/disable dump */
	bool	enable; /* enable/disable dump */
	u32	size;	/* total size of the dump */
	void	*data;	/* dump data area */
	struct	qlcnic_dump_template_hdr *tmpl_hdr;
@@ -463,7 +463,7 @@ struct qlcnic_hardware_context {
	struct qlcnic_fdt fdt;
	struct qlc_83xx_reset reset;
	struct qlc_83xx_idc idc;
	struct qlc_83xx_fw_info fw_info;
	struct qlc_83xx_fw_info *fw_info;
	struct qlcnic_intrpt_config *intr_tbl;
	struct qlcnic_sriov *sriov;
	u32 *reg_tbl;
@@ -837,6 +837,7 @@ struct qlcnic_mac_list_s {
#define QLCNIC_FW_CAP2_HW_LRO_IPV6		BIT_3
#define QLCNIC_FW_CAPABILITY_SET_DRV_VER	BIT_5
#define QLCNIC_FW_CAPABILITY_2_BEACON		BIT_7
#define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG	BIT_8

/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT			1
@@ -1184,6 +1185,7 @@ struct qlcnic_pci_info {
};

struct qlcnic_npar_info {
	bool	eswitch_status;
	u16	pvid;
	u16	min_bw;
	u16	max_bw;
@@ -1403,7 +1405,6 @@ struct qlcnic_esw_statistics {
	struct __qlcnic_esw_statistics tx;
};

#define QLCNIC_DUMP_MASK_DEF		0x1f
#define QLCNIC_FORCE_FW_DUMP_KEY	0xdeadfeed
#define QLCNIC_ENABLE_FW_DUMP		0xaddfeed
#define QLCNIC_DISABLE_FW_DUMP		0xbadfeed
@@ -1478,6 +1479,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
int qlcnic_dump_fw(struct qlcnic_adapter *);
int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *);
bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *);
pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *,
					       pci_channel_state_t);
pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *);
void qlcnic_82xx_io_resume(struct pci_dev *);

/* Functions from qlcnic_init.c */
void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int);
@@ -1723,6 +1730,10 @@ struct qlcnic_hardware_ops {
	void (*set_mac_filter_count) (struct qlcnic_adapter *);
	void (*free_mac_list) (struct qlcnic_adapter *);
	int (*read_phys_port_id) (struct qlcnic_adapter *);
	pci_ers_result_t (*io_error_detected) (struct pci_dev *,
					       pci_channel_state_t);
	pci_ers_result_t (*io_slot_reset) (struct pci_dev *);
	void (*io_resume) (struct pci_dev *);
};

extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -2069,6 +2080,14 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
	return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false;
}

static inline bool qlcnic_84xx_check(struct qlcnic_adapter *adapter)
{
	unsigned short device = adapter->pdev->device;

	return ((device == PCI_DEVICE_ID_QLOGIC_QLE844X) ||
		(device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X)) ? true : false;
}

static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter)
{
	unsigned short device = adapter->pdev->device;
+71 −13
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/ipv6.h>
#include <linux/ethtool.h>
#include <linux/interrupt.h>
#include <linux/aer.h>

#define QLCNIC_MAX_TX_QUEUES		1
#define RSS_HASHTYPE_IP_TCP		0x3
@@ -177,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
	.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,
	.io_error_detected		= qlcnic_83xx_io_error_detected,
	.io_slot_reset			= qlcnic_83xx_io_slot_reset,
	.io_resume			= qlcnic_83xx_io_resume,

};

static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -723,8 +728,7 @@ void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
	pr_info("\n");
}

static inline void
qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
						struct qlcnic_cmd_args *cmd)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -2327,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
					 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",
			dev_info(dev, "Max functions = %d, active functions = %d\n",
				 ahw->max_pci_func, ahw->act_pci_func);

	} else {
@@ -3544,7 +3548,7 @@ qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter,
	complete(&cmd->completion);
}

static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
	struct list_head *head = &mbx->cmd_q;
@@ -3564,7 +3568,7 @@ static inline void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
	spin_unlock(&mbx->queue_lock);
}

static inline int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter)
static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_mailbox *mbx = ahw->mailbox;
@@ -3592,7 +3596,7 @@ static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter,
		QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
}

static inline void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter,
static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter,
					struct qlcnic_cmd_args *cmd)
{
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
@@ -3653,7 +3657,7 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
	qlcnic_83xx_flush_mbx_queue(adapter);
}

static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
				       struct qlcnic_cmd_args *cmd,
				       unsigned long *timeout)
{
@@ -3680,7 +3684,7 @@ static inline int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
	return -EBUSY;
}

static inline int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter,
static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter,
				       struct qlcnic_cmd_args *cmd)
{
	u8 mac_cmd_rcode;
@@ -3820,3 +3824,57 @@ int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter)
	set_bit(QLC_83XX_MBX_READY, &mbx->status);
	return 0;
}

pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev,
					       pci_channel_state_t state)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);

	if (state == pci_channel_io_perm_failure)
		return PCI_ERS_RESULT_DISCONNECT;

	if (state == pci_channel_io_normal)
		return PCI_ERS_RESULT_RECOVERED;

	set_bit(__QLCNIC_AER, &adapter->state);
	set_bit(__QLCNIC_RESETTING, &adapter->state);

	qlcnic_83xx_aer_stop_poll_work(adapter);

	pci_save_state(pdev);
	pci_disable_device(pdev);

	return PCI_ERS_RESULT_NEED_RESET;
}

pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
	int err = 0;

	pdev->error_state = pci_channel_io_normal;
	err = pci_enable_device(pdev);
	if (err)
		goto disconnect;

	pci_set_power_state(pdev, PCI_D0);
	pci_set_master(pdev);
	pci_restore_state(pdev);

	err = qlcnic_83xx_aer_reset(adapter);
	if (err == 0)
		return PCI_ERS_RESULT_RECOVERED;
disconnect:
	clear_bit(__QLCNIC_AER, &adapter->state);
	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	return PCI_ERS_RESULT_DISCONNECT;
}

void qlcnic_83xx_io_resume(struct pci_dev *pdev)
{
	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);

	pci_cleanup_aer_uncorrect_error_status(pdev);
	if (test_and_clear_bit(__QLCNIC_AER, &adapter->state))
		qlcnic_83xx_aer_start_poll_work(adapter);
}
+11 −5
Original line number Diff line number Diff line
@@ -274,11 +274,7 @@ struct qlcnic_macvlan_mbx {

struct qlc_83xx_fw_info {
	const struct firmware	*fw;
	u16	major_fw_version;
	u8	minor_fw_version;
	u8	sub_fw_version;
	u8	fw_build_num;
	u8	load_from_file;
	char	fw_file_name[QLC_FW_FILE_NAME_LEN];
};

struct qlc_83xx_reset {
@@ -297,6 +293,7 @@ struct qlc_83xx_reset {

#define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY		0x1
#define QLC_83XX_IDC_GRACEFULL_RESET			0x2
#define QLC_83XX_IDC_DISABLE_FW_DUMP			0x4
#define QLC_83XX_IDC_TIMESTAMP				0
#define QLC_83XX_IDC_DURATION				1
#define QLC_83XX_IDC_INIT_TIMEOUT_SECS			30
@@ -414,6 +411,7 @@ enum qlcnic_83xx_states {
#define QLC_83XX_GET_HW_LRO_CAPABILITY(val)		(val & 0x400)
#define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val)	(val & 0x4000)
#define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val)	(val & 0x20000)
#define QLC_83XX_ESWITCH_CAPABILITY			BIT_23
#define QLC_83XX_VIRTUAL_NIC_MODE			0xFF
#define QLC_83XX_DEFAULT_MODE				0x0
#define QLC_83XX_SRIOV_MODE				0x1
@@ -628,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *);
int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *,
				    struct qlcnic_info *, u8);
int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *);
int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *, int);

void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *);
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data);
@@ -656,4 +655,11 @@ 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 *);
void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *);
int qlcnic_83xx_aer_reset(struct qlcnic_adapter *);
void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *);
pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
					       pci_channel_state_t);
pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
void qlcnic_83xx_io_resume(struct pci_dev *);
#endif
+134 −86
Original line number Diff line number Diff line
@@ -797,7 +797,6 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
			ret = qlcnic_83xx_idc_restart_hw(adapter, 1);
	} else {
		ret = qlcnic_83xx_idc_check_timeout(adapter, timeout);
		return ret;
	}

	return ret;
@@ -1268,31 +1267,33 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter)

static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
{
	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
	const struct firmware *fw = fw_info->fw;
	u32 dest, *p_cache;
	u64 addr;
	int i, ret = -EIO;
	u8 data[16];
	size_t size;
	int i, ret = -EIO;
	u64 addr;

	dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
	size = (adapter->ahw->fw_info.fw->size & ~0xF);
	p_cache = (u32 *)adapter->ahw->fw_info.fw->data;
	size = (fw->size & ~0xF);
	p_cache = (u32 *)fw->data;
	addr = (u64)dest;

	ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
					  (u32 *)p_cache, size / 16);
	if (ret) {
		dev_err(&adapter->pdev->dev, "MS memory write failed\n");
		release_firmware(adapter->ahw->fw_info.fw);
		adapter->ahw->fw_info.fw = NULL;
		release_firmware(fw);
		fw_info->fw = NULL;
		return -EIO;
	}

	/* alignment check */
	if (adapter->ahw->fw_info.fw->size & 0xF) {
	if (fw->size & 0xF) {
		addr = dest + size;
		for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++)
			data[i] = adapter->ahw->fw_info.fw->data[size + i];
		for (i = 0; i < (fw->size & 0xF); i++)
			data[i] = fw->data[size + i];
		for (; i < 16; i++)
			data[i] = 0;
		ret = qlcnic_83xx_ms_mem_write128(adapter, addr,
@@ -1300,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
		if (ret) {
			dev_err(&adapter->pdev->dev,
				"MS memory write failed\n");
			release_firmware(adapter->ahw->fw_info.fw);
			adapter->ahw->fw_info.fw = NULL;
			release_firmware(fw);
			fw_info->fw = NULL;
			return -EIO;
		}
	}
	release_firmware(adapter->ahw->fw_info.fw);
	adapter->ahw->fw_info.fw = NULL;
	release_firmware(fw);
	fw_info->fw = NULL;

	return 0;
}
@@ -1950,35 +1951,12 @@ static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev)
		dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__);
}

static inline void qlcnic_83xx_get_fw_file_name(struct qlcnic_adapter *adapter,
						char *file_name)
{
	struct pci_dev *pdev = adapter->pdev;

	memset(file_name, 0, QLC_FW_FILE_NAME_LEN);

	switch (pdev->device) {
	case PCI_DEVICE_ID_QLOGIC_QLE834X:
		strncpy(file_name, QLC_83XX_FW_FILE_NAME,
			QLC_FW_FILE_NAME_LEN);
		break;
	case PCI_DEVICE_ID_QLOGIC_QLE844X:
		strncpy(file_name, QLC_84XX_FW_FILE_NAME,
			QLC_FW_FILE_NAME_LEN);
		break;
	default:
		dev_err(&pdev->dev, "%s: Invalid device id\n",
			__func__);
	}
}

static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter)
{
	char fw_file_name[QLC_FW_FILE_NAME_LEN];
	struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
	int err = -EIO;

	qlcnic_83xx_get_fw_file_name(adapter, fw_file_name);
	if (request_firmware(&adapter->ahw->fw_info.fw, fw_file_name,
	if (request_firmware(&fw_info->fw, fw_info->fw_file_name,
			     &(adapter->pdev->dev))) {
		dev_err(&adapter->pdev->dev,
			"No file FW image, loading flash FW image.\n");
@@ -2025,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter)
	return 0;
}

/**
* qlcnic_83xx_config_default_opmode
*
* @adapter: adapter structure
*
* Configure default driver operating mode
*
* Returns: Error code or Success(0)
* */
int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter)
{
	u32 op_mode;
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	qlcnic_get_func_no(adapter);
	op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE);

	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))
		op_mode = QLC_83XX_DEFAULT_OPMODE;

	if (op_mode == QLC_83XX_DEFAULT_OPMODE) {
		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
	} else {
		return -EIO;
	}

	return 0;
}

int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
{
	int err;
@@ -2074,26 +2022,26 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter)
	ahw->max_mac_filters = nic_info.max_mac_filters;
	ahw->max_mtu = nic_info.max_mtu;

	/* VNIC mode is detected by BIT_23 in capabilities. This bit is also
	 * set in case device is SRIOV capable. VNIC and SRIOV are mutually
	 * exclusive. So in case of sriov capable device load driver in
	 * default mode
	/* eSwitch capability indicates vNIC mode.
	 * vNIC and SRIOV are mutually exclusive operational modes.
	 * If SR-IOV capability is detected, SR-IOV physical function
	 * will get initialized in default mode.
	 * SR-IOV virtual function initialization follows a
	 * different code path and opmode.
	 * SRIOV mode has precedence over vNIC mode.
	 */
	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) {
		ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
		return ahw->nic_mode;
	}
	if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state))
		return QLC_83XX_DEFAULT_OPMODE;

	if (ahw->capabilities & BIT_23)
		ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
	else
		ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
	if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
		return QLC_83XX_VIRTUAL_NIC_MODE;

	return ahw->nic_mode;
	return QLC_83XX_DEFAULT_OPMODE;
}

int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int ret;

	ret = qlcnic_83xx_get_nic_configuration(adapter);
@@ -2101,10 +2049,15 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter)
		return -EIO;

	if (ret == QLC_83XX_VIRTUAL_NIC_MODE) {
		ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE;
		if (qlcnic_83xx_config_vnic_opmode(adapter))
			return -EIO;
	} else if (ret == QLC_83XX_DEFAULT_MODE) {
		if (qlcnic_83xx_config_default_opmode(adapter))

	} else if (ret == QLC_83XX_DEFAULT_OPMODE) {
		ahw->nic_mode = QLC_83XX_DEFAULT_MODE;
		adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver;
		ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
	} else {
		return -EIO;
	}

@@ -2174,6 +2127,39 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
	}
}

static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct pci_dev *pdev = adapter->pdev;
	struct qlc_83xx_fw_info *fw_info;
	int err = 0;

	ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL);
	if (!ahw->fw_info) {
		err = -ENOMEM;
	} else {
		fw_info = ahw->fw_info;
		switch (pdev->device) {
		case PCI_DEVICE_ID_QLOGIC_QLE834X:
			strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME,
				QLC_FW_FILE_NAME_LEN);
			break;
		case PCI_DEVICE_ID_QLOGIC_QLE844X:
			strncpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME,
				QLC_FW_FILE_NAME_LEN);
			break;
		default:
			dev_err(&pdev->dev, "%s: Invalid device id\n",
				__func__);
			err = -EINVAL;
			break;
		}
	}

	return err;
}


int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -2199,10 +2185,14 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
	if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
		qlcnic_83xx_read_flash_mfg_id(adapter);

	err = qlcnic_83xx_idc_init(adapter);
	err = qlcnic_83xx_get_fw_info(adapter);
	if (err)
		goto detach_mbx;

	err = qlcnic_83xx_idc_init(adapter);
	if (err)
		goto clear_fw_info;

	err = qlcnic_setup_intr(adapter, 0, 0);
	if (err) {
		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
@@ -2243,9 +2233,67 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
disable_intr:
	qlcnic_teardown_intr(adapter);

clear_fw_info:
	kfree(ahw->fw_info);

detach_mbx:
	qlcnic_83xx_detach_mailbox_work(adapter);
	qlcnic_83xx_free_mailbox(ahw->mailbox);
exit:
	return err;
}

void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlc_83xx_idc *idc = &ahw->idc;

	clear_bit(QLC_83XX_MBX_READY, &idc->status);
	cancel_delayed_work_sync(&adapter->fw_work);

	if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
		qlcnic_83xx_disable_vnic_mode(adapter, 1);

	qlcnic_83xx_idc_detach_driver(adapter);
	qlcnic_83xx_register_nic_idc_func(adapter, 0);

	cancel_delayed_work_sync(&adapter->idc_aen_work);
}

int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlc_83xx_idc *idc = &ahw->idc;
	int ret = 0;
	u32 owner;

	/* Mark the previous IDC state as NEED_RESET so
	 * that state_entry() will perform the reattachment
	 * and bringup the device
	 */
	idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET;
	owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
	if (ahw->pci_func == owner) {
		ret = qlcnic_83xx_restart_hw(adapter);
		if (ret < 0)
			return ret;
		qlcnic_83xx_idc_clear_registers(adapter, 0);
	}

	ret = idc->state_entry(adapter);
	return ret;
}

void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlc_83xx_idc *idc = &ahw->idc;
	u32 owner;

	idc->prev_state = QLC_83XX_IDC_DEV_READY;
	owner = qlcnic_83xx_idc_find_reset_owner_id(adapter);
	if (ahw->pci_func == owner)
		qlcnic_83xx_idc_enter_ready_state(adapter, 0);

	qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0);
}
+39 −1
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
		return -EIO;
	}

	if (ahw->capabilities & BIT_23)
	if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
		adapter->flags |= QLCNIC_ESWITCH_ENABLED;
	else
		adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
@@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)

	return 0;
}

static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter,
					     int func, int *port_id)
{
	struct qlcnic_info nic_info;
	int err = 0;

	memset(&nic_info, 0, sizeof(struct qlcnic_info));

	err = qlcnic_get_nic_info(adapter, &nic_info, func);
	if (err)
		return err;

	if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY)
		*port_id = nic_info.phys_port;
	else
		err = -EIO;

	return err;
}

int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *adapter, int func)
{
	int id, err = 0;

	err = qlcnic_83xx_get_eswitch_port_info(adapter, func, &id);
	if (err)
		return err;

	if (!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) {
		if (!qlcnic_enable_eswitch(adapter, id, 1))
			adapter->eswitch[id].flags |= QLCNIC_SWITCH_ENABLE;
		else
			err = -EIO;
	}

	return err;
}
Loading