cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qlcnic_83xx_hw.c (116062B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * QLogic qlcnic NIC Driver
      4 * Copyright (c) 2009-2013 QLogic Corporation
      5 */
      6
      7#include <linux/if_vlan.h>
      8#include <linux/ipv6.h>
      9#include <linux/ethtool.h>
     10#include <linux/interrupt.h>
     11#include <linux/aer.h>
     12
     13#include "qlcnic.h"
     14#include "qlcnic_sriov.h"
     15
     16static void __qlcnic_83xx_process_aen(struct qlcnic_adapter *);
     17static int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8);
     18static void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8,
     19				      struct qlcnic_cmd_args *);
     20static int qlcnic_83xx_get_port_config(struct qlcnic_adapter *);
     21static irqreturn_t qlcnic_83xx_handle_aen(int, void *);
     22static pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *,
     23						      pci_channel_state_t);
     24static int qlcnic_83xx_set_port_config(struct qlcnic_adapter *);
     25static pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *);
     26static void qlcnic_83xx_io_resume(struct pci_dev *);
     27static int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8);
     28static void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
     29static int qlcnic_83xx_resume(struct qlcnic_adapter *);
     30static int qlcnic_83xx_shutdown(struct pci_dev *);
     31static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *);
     32
     33#define RSS_HASHTYPE_IP_TCP		0x3
     34#define QLC_83XX_FW_MBX_CMD		0
     35#define QLC_SKIP_INACTIVE_PCI_REGS	7
     36#define QLC_MAX_LEGACY_FUNC_SUPP	8
     37
     38/* 83xx Module type */
     39#define QLC_83XX_MODULE_FIBRE_10GBASE_LRM	0x1 /* 10GBase-LRM */
     40#define QLC_83XX_MODULE_FIBRE_10GBASE_LR	0x2 /* 10GBase-LR */
     41#define QLC_83XX_MODULE_FIBRE_10GBASE_SR	0x3 /* 10GBase-SR */
     42#define QLC_83XX_MODULE_DA_10GE_PASSIVE_CP	0x4 /* 10GE passive
     43						     * copper(compliant)
     44						     */
     45#define QLC_83XX_MODULE_DA_10GE_ACTIVE_CP	0x5 /* 10GE active limiting
     46						     * copper(compliant)
     47						     */
     48#define QLC_83XX_MODULE_DA_10GE_LEGACY_CP	0x6 /* 10GE passive copper
     49						     * (legacy, best effort)
     50						     */
     51#define QLC_83XX_MODULE_FIBRE_1000BASE_SX	0x7 /* 1000Base-SX */
     52#define QLC_83XX_MODULE_FIBRE_1000BASE_LX	0x8 /* 1000Base-LX */
     53#define QLC_83XX_MODULE_FIBRE_1000BASE_CX	0x9 /* 1000Base-CX */
     54#define QLC_83XX_MODULE_TP_1000BASE_T		0xa /* 1000Base-T*/
     55#define QLC_83XX_MODULE_DA_1GE_PASSIVE_CP	0xb /* 1GE passive copper
     56						     * (legacy, best effort)
     57						     */
     58#define QLC_83XX_MODULE_UNKNOWN			0xf /* Unknown module type */
     59
     60/* Port types */
     61#define QLC_83XX_10_CAPABLE	 BIT_8
     62#define QLC_83XX_100_CAPABLE	 BIT_9
     63#define QLC_83XX_1G_CAPABLE	 BIT_10
     64#define QLC_83XX_10G_CAPABLE	 BIT_11
     65#define QLC_83XX_AUTONEG_ENABLE	 BIT_15
     66
     67static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = {
     68	{QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1},
     69	{QLCNIC_CMD_CONFIG_INTRPT, 18, 34},
     70	{QLCNIC_CMD_CREATE_RX_CTX, 136, 27},
     71	{QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
     72	{QLCNIC_CMD_CREATE_TX_CTX, 54, 18},
     73	{QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
     74	{QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1},
     75	{QLCNIC_CMD_INTRPT_TEST, 22, 12},
     76	{QLCNIC_CMD_SET_MTU, 3, 1},
     77	{QLCNIC_CMD_READ_PHY, 4, 2},
     78	{QLCNIC_CMD_WRITE_PHY, 5, 1},
     79	{QLCNIC_CMD_READ_HW_REG, 4, 1},
     80	{QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
     81	{QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
     82	{QLCNIC_CMD_READ_MAX_MTU, 4, 2},
     83	{QLCNIC_CMD_READ_MAX_LRO, 4, 2},
     84	{QLCNIC_CMD_MAC_ADDRESS, 4, 3},
     85	{QLCNIC_CMD_GET_PCI_INFO, 1, 129},
     86	{QLCNIC_CMD_GET_NIC_INFO, 2, 19},
     87	{QLCNIC_CMD_SET_NIC_INFO, 32, 1},
     88	{QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
     89	{QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
     90	{QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
     91	{QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
     92	{QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
     93	{QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
     94	{QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
     95	{QLCNIC_CMD_CONFIG_PORT, 4, 1},
     96	{QLCNIC_CMD_TEMP_SIZE, 1, 4},
     97	{QLCNIC_CMD_GET_TEMP_HDR, 5, 5},
     98	{QLCNIC_CMD_GET_LINK_EVENT, 2, 1},
     99	{QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3},
    100	{QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1},
    101	{QLCNIC_CMD_CONFIGURE_RSS, 14, 1},
    102	{QLCNIC_CMD_CONFIGURE_LED, 2, 1},
    103	{QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1},
    104	{QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1},
    105	{QLCNIC_CMD_GET_STATISTICS, 2, 80},
    106	{QLCNIC_CMD_SET_PORT_CONFIG, 2, 1},
    107	{QLCNIC_CMD_GET_PORT_CONFIG, 2, 2},
    108	{QLCNIC_CMD_GET_LINK_STATUS, 2, 4},
    109	{QLCNIC_CMD_IDC_ACK, 5, 1},
    110	{QLCNIC_CMD_INIT_NIC_FUNC, 3, 1},
    111	{QLCNIC_CMD_STOP_NIC_FUNC, 2, 1},
    112	{QLCNIC_CMD_SET_LED_CONFIG, 5, 1},
    113	{QLCNIC_CMD_GET_LED_CONFIG, 1, 5},
    114	{QLCNIC_CMD_83XX_SET_DRV_VER, 4, 1},
    115	{QLCNIC_CMD_ADD_RCV_RINGS, 130, 26},
    116	{QLCNIC_CMD_CONFIG_VPORT, 4, 4},
    117	{QLCNIC_CMD_BC_EVENT_SETUP, 2, 1},
    118	{QLCNIC_CMD_DCB_QUERY_CAP, 1, 2},
    119	{QLCNIC_CMD_DCB_QUERY_PARAM, 1, 50},
    120	{QLCNIC_CMD_SET_INGRESS_ENCAP, 2, 1},
    121	{QLCNIC_CMD_83XX_EXTEND_ISCSI_DUMP_CAP, 4, 1},
    122};
    123
    124const u32 qlcnic_83xx_ext_reg_tbl[] = {
    125	0x38CC,		/* Global Reset */
    126	0x38F0,		/* Wildcard */
    127	0x38FC,		/* Informant */
    128	0x3038,		/* Host MBX ctrl */
    129	0x303C,		/* FW MBX ctrl */
    130	0x355C,		/* BOOT LOADER ADDRESS REG */
    131	0x3560,		/* BOOT LOADER SIZE REG */
    132	0x3564,		/* FW IMAGE ADDR REG */
    133	0x1000,		/* MBX intr enable */
    134	0x1200,		/* Default Intr mask */
    135	0x1204,		/* Default Interrupt ID */
    136	0x3780,		/* QLC_83XX_IDC_MAJ_VERSION */
    137	0x3784,		/* QLC_83XX_IDC_DEV_STATE */
    138	0x3788,		/* QLC_83XX_IDC_DRV_PRESENCE */
    139	0x378C,		/* QLC_83XX_IDC_DRV_ACK */
    140	0x3790,		/* QLC_83XX_IDC_CTRL */
    141	0x3794,		/* QLC_83XX_IDC_DRV_AUDIT */
    142	0x3798,		/* QLC_83XX_IDC_MIN_VERSION */
    143	0x379C,		/* QLC_83XX_RECOVER_DRV_LOCK */
    144	0x37A0,		/* QLC_83XX_IDC_PF_0 */
    145	0x37A4,		/* QLC_83XX_IDC_PF_1 */
    146	0x37A8,		/* QLC_83XX_IDC_PF_2 */
    147	0x37AC,		/* QLC_83XX_IDC_PF_3 */
    148	0x37B0,		/* QLC_83XX_IDC_PF_4 */
    149	0x37B4,		/* QLC_83XX_IDC_PF_5 */
    150	0x37B8,		/* QLC_83XX_IDC_PF_6 */
    151	0x37BC,		/* QLC_83XX_IDC_PF_7 */
    152	0x37C0,		/* QLC_83XX_IDC_PF_8 */
    153	0x37C4,		/* QLC_83XX_IDC_PF_9 */
    154	0x37C8,		/* QLC_83XX_IDC_PF_10 */
    155	0x37CC,		/* QLC_83XX_IDC_PF_11 */
    156	0x37D0,		/* QLC_83XX_IDC_PF_12 */
    157	0x37D4,		/* QLC_83XX_IDC_PF_13 */
    158	0x37D8,		/* QLC_83XX_IDC_PF_14 */
    159	0x37DC,		/* QLC_83XX_IDC_PF_15 */
    160	0x37E0,		/* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */
    161	0x37E4,		/* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */
    162	0x37F0,		/* QLC_83XX_DRV_OP_MODE */
    163	0x37F4,		/* QLC_83XX_VNIC_STATE */
    164	0x3868,		/* QLC_83XX_DRV_LOCK */
    165	0x386C,		/* QLC_83XX_DRV_UNLOCK */
    166	0x3504,		/* QLC_83XX_DRV_LOCK_ID */
    167	0x34A4,		/* QLC_83XX_ASIC_TEMP */
    168};
    169
    170const u32 qlcnic_83xx_reg_tbl[] = {
    171	0x34A8,		/* PEG_HALT_STAT1 */
    172	0x34AC,		/* PEG_HALT_STAT2 */
    173	0x34B0,		/* FW_HEARTBEAT */
    174	0x3500,		/* FLASH LOCK_ID */
    175	0x3528,		/* FW_CAPABILITIES */
    176	0x3538,		/* Driver active, DRV_REG0 */
    177	0x3540,		/* Device state, DRV_REG1 */
    178	0x3544,		/* Driver state, DRV_REG2 */
    179	0x3548,		/* Driver scratch, DRV_REG3 */
    180	0x354C,		/* Device partition info, DRV_REG4 */
    181	0x3524,		/* Driver IDC ver, DRV_REG5 */
    182	0x3550,		/* FW_VER_MAJOR */
    183	0x3554,		/* FW_VER_MINOR */
    184	0x3558,		/* FW_VER_SUB */
    185	0x359C,		/* NPAR STATE */
    186	0x35FC,		/* FW_IMG_VALID */
    187	0x3650,		/* CMD_PEG_STATE */
    188	0x373C,		/* RCV_PEG_STATE */
    189	0x37B4,		/* ASIC TEMP */
    190	0x356C,		/* FW API */
    191	0x3570,		/* DRV OP MODE */
    192	0x3850,		/* FLASH LOCK */
    193	0x3854,		/* FLASH UNLOCK */
    194};
    195
    196static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
    197	.read_crb			= qlcnic_83xx_read_crb,
    198	.write_crb			= qlcnic_83xx_write_crb,
    199	.read_reg			= qlcnic_83xx_rd_reg_indirect,
    200	.write_reg			= qlcnic_83xx_wrt_reg_indirect,
    201	.get_mac_address		= qlcnic_83xx_get_mac_address,
    202	.setup_intr			= qlcnic_83xx_setup_intr,
    203	.alloc_mbx_args			= qlcnic_83xx_alloc_mbx_args,
    204	.mbx_cmd			= qlcnic_83xx_issue_cmd,
    205	.get_func_no			= qlcnic_83xx_get_func_no,
    206	.api_lock			= qlcnic_83xx_cam_lock,
    207	.api_unlock			= qlcnic_83xx_cam_unlock,
    208	.add_sysfs			= qlcnic_83xx_add_sysfs,
    209	.remove_sysfs			= qlcnic_83xx_remove_sysfs,
    210	.process_lb_rcv_ring_diag	= qlcnic_83xx_process_rcv_ring_diag,
    211	.create_rx_ctx			= qlcnic_83xx_create_rx_ctx,
    212	.create_tx_ctx			= qlcnic_83xx_create_tx_ctx,
    213	.del_rx_ctx			= qlcnic_83xx_del_rx_ctx,
    214	.del_tx_ctx			= qlcnic_83xx_del_tx_ctx,
    215	.setup_link_event		= qlcnic_83xx_setup_link_event,
    216	.get_nic_info			= qlcnic_83xx_get_nic_info,
    217	.get_pci_info			= qlcnic_83xx_get_pci_info,
    218	.set_nic_info			= qlcnic_83xx_set_nic_info,
    219	.change_macvlan			= qlcnic_83xx_sre_macaddr_change,
    220	.napi_enable			= qlcnic_83xx_napi_enable,
    221	.napi_disable			= qlcnic_83xx_napi_disable,
    222	.config_intr_coal		= qlcnic_83xx_config_intr_coal,
    223	.config_rss			= qlcnic_83xx_config_rss,
    224	.config_hw_lro			= qlcnic_83xx_config_hw_lro,
    225	.config_promisc_mode		= qlcnic_83xx_nic_set_promisc,
    226	.change_l2_filter		= qlcnic_83xx_change_l2_filter,
    227	.get_board_info			= qlcnic_83xx_get_port_info,
    228	.set_mac_filter_count		= qlcnic_83xx_set_mac_filter_count,
    229	.free_mac_list			= qlcnic_82xx_free_mac_list,
    230	.io_error_detected		= qlcnic_83xx_io_error_detected,
    231	.io_slot_reset			= qlcnic_83xx_io_slot_reset,
    232	.io_resume			= qlcnic_83xx_io_resume,
    233	.get_beacon_state		= qlcnic_83xx_get_beacon_state,
    234	.enable_sds_intr		= qlcnic_83xx_enable_sds_intr,
    235	.disable_sds_intr		= qlcnic_83xx_disable_sds_intr,
    236	.enable_tx_intr			= qlcnic_83xx_enable_tx_intr,
    237	.disable_tx_intr		= qlcnic_83xx_disable_tx_intr,
    238	.get_saved_state		= qlcnic_83xx_get_saved_state,
    239	.set_saved_state		= qlcnic_83xx_set_saved_state,
    240	.cache_tmpl_hdr_values		= qlcnic_83xx_cache_tmpl_hdr_values,
    241	.get_cap_size			= qlcnic_83xx_get_cap_size,
    242	.set_sys_info			= qlcnic_83xx_set_sys_info,
    243	.store_cap_mask			= qlcnic_83xx_store_cap_mask,
    244	.encap_rx_offload		= qlcnic_83xx_encap_rx_offload,
    245	.encap_tx_offload		= qlcnic_83xx_encap_tx_offload,
    246};
    247
    248static struct qlcnic_nic_template qlcnic_83xx_ops = {
    249	.config_bridged_mode	= qlcnic_config_bridged_mode,
    250	.config_led		= qlcnic_config_led,
    251	.request_reset          = qlcnic_83xx_idc_request_reset,
    252	.cancel_idc_work        = qlcnic_83xx_idc_exit,
    253	.napi_add		= qlcnic_83xx_napi_add,
    254	.napi_del		= qlcnic_83xx_napi_del,
    255	.config_ipaddr		= qlcnic_83xx_config_ipaddr,
    256	.clear_legacy_intr	= qlcnic_83xx_clear_legacy_intr,
    257	.shutdown		= qlcnic_83xx_shutdown,
    258	.resume			= qlcnic_83xx_resume,
    259};
    260
    261void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
    262{
    263	ahw->hw_ops		= &qlcnic_83xx_hw_ops;
    264	ahw->reg_tbl		= (u32 *)qlcnic_83xx_reg_tbl;
    265	ahw->ext_reg_tbl	= (u32 *)qlcnic_83xx_ext_reg_tbl;
    266}
    267
    268int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter)
    269{
    270	u32 fw_major, fw_minor, fw_build;
    271	struct pci_dev *pdev = adapter->pdev;
    272
    273	fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
    274	fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
    275	fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
    276	adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
    277
    278	dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n",
    279		 QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build);
    280
    281	return adapter->fw_version;
    282}
    283
    284static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
    285{
    286	void __iomem *base;
    287	u32 val;
    288
    289	base = adapter->ahw->pci_base0 +
    290	       QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func);
    291	writel(addr, base);
    292	val = readl(base);
    293	if (val != addr)
    294		return -EIO;
    295
    296	return 0;
    297}
    298
    299int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
    300				int *err)
    301{
    302	struct qlcnic_hardware_context *ahw = adapter->ahw;
    303
    304	*err = __qlcnic_set_win_base(adapter, (u32) addr);
    305	if (!*err) {
    306		return QLCRDX(ahw, QLCNIC_WILDCARD);
    307	} else {
    308		dev_err(&adapter->pdev->dev,
    309			"%s failed, addr = 0x%lx\n", __func__, addr);
    310		return -EIO;
    311	}
    312}
    313
    314int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
    315				 u32 data)
    316{
    317	int err;
    318	struct qlcnic_hardware_context *ahw = adapter->ahw;
    319
    320	err = __qlcnic_set_win_base(adapter, (u32) addr);
    321	if (!err) {
    322		QLCWRX(ahw, QLCNIC_WILDCARD, data);
    323		return 0;
    324	} else {
    325		dev_err(&adapter->pdev->dev,
    326			"%s failed, addr = 0x%x data = 0x%x\n",
    327			__func__, (int)addr, data);
    328		return err;
    329	}
    330}
    331
    332static void qlcnic_83xx_enable_legacy(struct qlcnic_adapter *adapter)
    333{
    334	struct qlcnic_hardware_context *ahw = adapter->ahw;
    335
    336	/* MSI-X enablement failed, use legacy interrupt */
    337	adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR;
    338	adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK;
    339	adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR;
    340	adapter->msix_entries[0].vector = adapter->pdev->irq;
    341	dev_info(&adapter->pdev->dev, "using legacy interrupt\n");
    342}
    343
    344static int qlcnic_83xx_calculate_msix_vector(struct qlcnic_adapter *adapter)
    345{
    346	int num_msix;
    347
    348	num_msix = adapter->drv_sds_rings;
    349
    350	/* account for AEN interrupt MSI-X based interrupts */
    351	num_msix += 1;
    352
    353	if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
    354		num_msix += adapter->drv_tx_rings;
    355
    356	return num_msix;
    357}
    358
    359int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
    360{
    361	struct qlcnic_hardware_context *ahw = adapter->ahw;
    362	int err, i, num_msix;
    363
    364	if (adapter->flags & QLCNIC_TSS_RSS) {
    365		err = qlcnic_setup_tss_rss_intr(adapter);
    366		if (err < 0)
    367			return err;
    368		num_msix = ahw->num_msix;
    369	} else {
    370		num_msix = qlcnic_83xx_calculate_msix_vector(adapter);
    371
    372		err = qlcnic_enable_msix(adapter, num_msix);
    373		if (err == -ENOMEM)
    374			return err;
    375
    376		if (adapter->flags & QLCNIC_MSIX_ENABLED) {
    377			num_msix = ahw->num_msix;
    378		} else {
    379			if (qlcnic_sriov_vf_check(adapter))
    380				return -EINVAL;
    381			num_msix = 1;
    382			adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
    383			adapter->drv_tx_rings = QLCNIC_SINGLE_RING;
    384		}
    385	}
    386
    387	/* setup interrupt mapping table for fw */
    388	ahw->intr_tbl =
    389		vzalloc(array_size(num_msix,
    390				   sizeof(struct qlcnic_intrpt_config)));
    391	if (!ahw->intr_tbl)
    392		return -ENOMEM;
    393
    394	if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
    395		if (adapter->ahw->pci_func >= QLC_MAX_LEGACY_FUNC_SUPP) {
    396			dev_err(&adapter->pdev->dev, "PCI function number 8 and higher are not supported with legacy interrupt, func 0x%x\n",
    397				ahw->pci_func);
    398			return -EOPNOTSUPP;
    399		}
    400
    401		qlcnic_83xx_enable_legacy(adapter);
    402	}
    403
    404	for (i = 0; i < num_msix; i++) {
    405		if (adapter->flags & QLCNIC_MSIX_ENABLED)
    406			ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX;
    407		else
    408			ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX;
    409		ahw->intr_tbl[i].id = i;
    410		ahw->intr_tbl[i].src = 0;
    411	}
    412
    413	return 0;
    414}
    415
    416static inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
    417{
    418	writel(0, adapter->tgt_mask_reg);
    419}
    420
    421static inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
    422{
    423	if (adapter->tgt_mask_reg)
    424		writel(1, adapter->tgt_mask_reg);
    425}
    426
    427static inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter
    428						    *adapter)
    429{
    430	u32 mask;
    431
    432	/* Mailbox in MSI-x mode and Legacy Interrupt share the same
    433	 * source register. We could be here before contexts are created
    434	 * and sds_ring->crb_intr_mask has not been initialized, calculate
    435	 * BAR offset for Interrupt Source Register
    436	 */
    437	mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
    438	writel(0, adapter->ahw->pci_base0 + mask);
    439}
    440
    441void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter)
    442{
    443	u32 mask;
    444
    445	mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
    446	writel(1, adapter->ahw->pci_base0 + mask);
    447	QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0);
    448}
    449
    450static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
    451				     struct qlcnic_cmd_args *cmd)
    452{
    453	int i;
    454
    455	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
    456		return;
    457
    458	for (i = 0; i < cmd->rsp.num; i++)
    459		cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
    460}
    461
    462irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
    463{
    464	u32 intr_val;
    465	struct qlcnic_hardware_context *ahw = adapter->ahw;
    466	int retries = 0;
    467
    468	intr_val = readl(adapter->tgt_status_reg);
    469
    470	if (!QLC_83XX_VALID_INTX_BIT31(intr_val))
    471		return IRQ_NONE;
    472
    473	if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) {
    474		adapter->stats.spurious_intr++;
    475		return IRQ_NONE;
    476	}
    477	/* The barrier is required to ensure writes to the registers */
    478	wmb();
    479
    480	/* clear the interrupt trigger control register */
    481	writel_relaxed(0, adapter->isr_int_vec);
    482	intr_val = readl(adapter->isr_int_vec);
    483	do {
    484		intr_val = readl(adapter->tgt_status_reg);
    485		if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func)
    486			break;
    487		retries++;
    488	} while (QLC_83XX_VALID_INTX_BIT30(intr_val) &&
    489		 (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY));
    490
    491	return IRQ_HANDLED;
    492}
    493
    494static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx)
    495{
    496	mbx->rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
    497	complete(&mbx->completion);
    498}
    499
    500static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
    501{
    502	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
    503	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
    504	unsigned long flags;
    505
    506	spin_lock_irqsave(&mbx->aen_lock, flags);
    507	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
    508	if (!(resp & QLCNIC_SET_OWNER))
    509		goto out;
    510
    511	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
    512	if (event &  QLCNIC_MBX_ASYNC_EVENT) {
    513		__qlcnic_83xx_process_aen(adapter);
    514	} else {
    515		if (mbx->rsp_status != rsp_status)
    516			qlcnic_83xx_notify_mbx_response(mbx);
    517	}
    518out:
    519	qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
    520	spin_unlock_irqrestore(&mbx->aen_lock, flags);
    521}
    522
    523irqreturn_t qlcnic_83xx_intr(int irq, void *data)
    524{
    525	struct qlcnic_adapter *adapter = data;
    526	struct qlcnic_host_sds_ring *sds_ring;
    527	struct qlcnic_hardware_context *ahw = adapter->ahw;
    528
    529	if (qlcnic_83xx_clear_legacy_intr(adapter) == IRQ_NONE)
    530		return IRQ_NONE;
    531
    532	qlcnic_83xx_poll_process_aen(adapter);
    533
    534	if (ahw->diag_test) {
    535		if (ahw->diag_test == QLCNIC_INTERRUPT_TEST)
    536			ahw->diag_cnt++;
    537		qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
    538		return IRQ_HANDLED;
    539	}
    540
    541	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
    542		qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
    543	} else {
    544		sds_ring = &adapter->recv_ctx->sds_rings[0];
    545		napi_schedule(&sds_ring->napi);
    546	}
    547
    548	return IRQ_HANDLED;
    549}
    550
    551irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data)
    552{
    553	struct qlcnic_host_sds_ring *sds_ring = data;
    554	struct qlcnic_adapter *adapter = sds_ring->adapter;
    555
    556	if (adapter->flags & QLCNIC_MSIX_ENABLED)
    557		goto done;
    558
    559	if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE)
    560		return IRQ_NONE;
    561
    562done:
    563	adapter->ahw->diag_cnt++;
    564	qlcnic_enable_sds_intr(adapter, sds_ring);
    565
    566	return IRQ_HANDLED;
    567}
    568
    569void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
    570{
    571	u32 num_msix;
    572
    573	if (!(adapter->flags & QLCNIC_MSIX_ENABLED))
    574		qlcnic_83xx_set_legacy_intr_mask(adapter);
    575
    576	qlcnic_83xx_disable_mbx_intr(adapter);
    577
    578	if (adapter->flags & QLCNIC_MSIX_ENABLED)
    579		num_msix = adapter->ahw->num_msix - 1;
    580	else
    581		num_msix = 0;
    582
    583	msleep(20);
    584
    585	if (adapter->msix_entries) {
    586		synchronize_irq(adapter->msix_entries[num_msix].vector);
    587		free_irq(adapter->msix_entries[num_msix].vector, adapter);
    588	}
    589}
    590
    591int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
    592{
    593	irq_handler_t handler;
    594	u32 val;
    595	int err = 0;
    596	unsigned long flags = 0;
    597
    598	if (!(adapter->flags & QLCNIC_MSI_ENABLED) &&
    599	    !(adapter->flags & QLCNIC_MSIX_ENABLED))
    600		flags |= IRQF_SHARED;
    601
    602	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
    603		handler = qlcnic_83xx_handle_aen;
    604		val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector;
    605		err = request_irq(val, handler, flags, "qlcnic-MB", adapter);
    606		if (err) {
    607			dev_err(&adapter->pdev->dev,
    608				"failed to register MBX interrupt\n");
    609			return err;
    610		}
    611	} else {
    612		handler = qlcnic_83xx_intr;
    613		val = adapter->msix_entries[0].vector;
    614		err = request_irq(val, handler, flags, "qlcnic", adapter);
    615		if (err) {
    616			dev_err(&adapter->pdev->dev,
    617				"failed to register INTx interrupt\n");
    618			return err;
    619		}
    620		qlcnic_83xx_clear_legacy_intr_mask(adapter);
    621	}
    622
    623	/* Enable mailbox interrupt */
    624	qlcnic_83xx_enable_mbx_interrupt(adapter);
    625
    626	return err;
    627}
    628
    629void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter)
    630{
    631	u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT);
    632	adapter->ahw->pci_func = (val >> 24) & 0xff;
    633}
    634
    635int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter)
    636{
    637	void __iomem *addr;
    638	u32 val, limit = 0;
    639
    640	struct qlcnic_hardware_context *ahw = adapter->ahw;
    641
    642	addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func);
    643	do {
    644		val = readl(addr);
    645		if (val) {
    646			/* write the function number to register */
    647			QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER,
    648					    ahw->pci_func);
    649			return 0;
    650		}
    651		usleep_range(1000, 2000);
    652	} while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT);
    653
    654	return -EIO;
    655}
    656
    657void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
    658{
    659	void __iomem *addr;
    660	struct qlcnic_hardware_context *ahw = adapter->ahw;
    661
    662	addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func);
    663	readl(addr);
    664}
    665
    666void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
    667			  loff_t offset, size_t size)
    668{
    669	int ret = 0;
    670	u32 data;
    671
    672	if (qlcnic_api_lock(adapter)) {
    673		dev_err(&adapter->pdev->dev,
    674			"%s: failed to acquire lock. addr offset 0x%x\n",
    675			__func__, (u32)offset);
    676		return;
    677	}
    678
    679	data = QLCRD32(adapter, (u32) offset, &ret);
    680	qlcnic_api_unlock(adapter);
    681
    682	if (ret == -EIO) {
    683		dev_err(&adapter->pdev->dev,
    684			"%s: failed. addr offset 0x%x\n",
    685			__func__, (u32)offset);
    686		return;
    687	}
    688	memcpy(buf, &data, size);
    689}
    690
    691void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
    692			   loff_t offset, size_t size)
    693{
    694	u32 data;
    695
    696	memcpy(&data, buf, size);
    697	qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data);
    698}
    699
    700int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter)
    701{
    702	struct qlcnic_hardware_context *ahw = adapter->ahw;
    703	int status;
    704
    705	status = qlcnic_83xx_get_port_config(adapter);
    706	if (status) {
    707		dev_err(&adapter->pdev->dev,
    708			"Get Port Info failed\n");
    709	} else {
    710
    711		if (ahw->port_config & QLC_83XX_10G_CAPABLE) {
    712			ahw->port_type = QLCNIC_XGBE;
    713		} else if (ahw->port_config & QLC_83XX_10_CAPABLE ||
    714			   ahw->port_config & QLC_83XX_100_CAPABLE ||
    715			   ahw->port_config & QLC_83XX_1G_CAPABLE) {
    716			ahw->port_type = QLCNIC_GBE;
    717		} else {
    718			ahw->port_type = QLCNIC_XGBE;
    719		}
    720
    721		if (QLC_83XX_AUTONEG(ahw->port_config))
    722			ahw->link_autoneg = AUTONEG_ENABLE;
    723
    724	}
    725	return status;
    726}
    727
    728static void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
    729{
    730	struct qlcnic_hardware_context *ahw = adapter->ahw;
    731	u16 act_pci_fn = ahw->total_nic_func;
    732	u16 count;
    733
    734	ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT;
    735	if (act_pci_fn <= 2)
    736		count = (QLC_83XX_MAX_UC_COUNT - QLC_83XX_MAX_MC_COUNT) /
    737			 act_pci_fn;
    738	else
    739		count = (QLC_83XX_LB_MAX_FILTERS - QLC_83XX_MAX_MC_COUNT) /
    740			 act_pci_fn;
    741	ahw->max_uc_count = count;
    742}
    743
    744void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *adapter)
    745{
    746	u32 val;
    747
    748	if (adapter->flags & QLCNIC_MSIX_ENABLED)
    749		val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8);
    750	else
    751		val = BIT_2;
    752
    753	QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val);
    754	qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
    755}
    756
    757void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter,
    758			  const struct pci_device_id *ent)
    759{
    760	u32 op_mode, priv_level;
    761	struct qlcnic_hardware_context *ahw = adapter->ahw;
    762
    763	ahw->fw_hal_version = 2;
    764	qlcnic_get_func_no(adapter);
    765
    766	if (qlcnic_sriov_vf_check(adapter)) {
    767		qlcnic_sriov_vf_set_ops(adapter);
    768		return;
    769	}
    770
    771	/* Determine function privilege level */
    772	op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
    773	if (op_mode == QLC_83XX_DEFAULT_OPMODE)
    774		priv_level = QLCNIC_MGMT_FUNC;
    775	else
    776		priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
    777							 ahw->pci_func);
    778
    779	if (priv_level == QLCNIC_NON_PRIV_FUNC) {
    780		ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
    781		dev_info(&adapter->pdev->dev,
    782			 "HAL Version: %d Non Privileged function\n",
    783			 ahw->fw_hal_version);
    784		adapter->nic_ops = &qlcnic_vf_ops;
    785	} else {
    786		if (pci_find_ext_capability(adapter->pdev,
    787					    PCI_EXT_CAP_ID_SRIOV))
    788			set_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state);
    789		adapter->nic_ops = &qlcnic_83xx_ops;
    790	}
    791}
    792
    793static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
    794					u32 data[]);
    795static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
    796					    u32 data[]);
    797
    798void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
    799		     struct qlcnic_cmd_args *cmd)
    800{
    801	int i;
    802
    803	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
    804		return;
    805
    806	dev_info(&adapter->pdev->dev,
    807		 "Host MBX regs(%d)\n", cmd->req.num);
    808	for (i = 0; i < cmd->req.num; i++) {
    809		if (i && !(i % 8))
    810			pr_info("\n");
    811		pr_info("%08x ", cmd->req.arg[i]);
    812	}
    813	pr_info("\n");
    814	dev_info(&adapter->pdev->dev,
    815		 "FW MBX regs(%d)\n", cmd->rsp.num);
    816	for (i = 0; i < cmd->rsp.num; i++) {
    817		if (i && !(i % 8))
    818			pr_info("\n");
    819		pr_info("%08x ", cmd->rsp.arg[i]);
    820	}
    821	pr_info("\n");
    822}
    823
    824static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
    825						struct qlcnic_cmd_args *cmd)
    826{
    827	struct qlcnic_hardware_context *ahw = adapter->ahw;
    828	int opcode = LSW(cmd->req.arg[0]);
    829	unsigned long max_loops;
    830
    831	max_loops = cmd->total_cmds * QLC_83XX_MBX_CMD_LOOP;
    832
    833	for (; max_loops; max_loops--) {
    834		if (atomic_read(&cmd->rsp_status) ==
    835		    QLC_83XX_MBX_RESPONSE_ARRIVED)
    836			return;
    837
    838		udelay(1);
    839	}
    840
    841	dev_err(&adapter->pdev->dev,
    842		"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
    843		__func__, opcode, cmd->type, ahw->pci_func, ahw->op_mode);
    844	flush_workqueue(ahw->mailbox->work_q);
    845	return;
    846}
    847
    848int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
    849			  struct qlcnic_cmd_args *cmd)
    850{
    851	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
    852	struct qlcnic_hardware_context *ahw = adapter->ahw;
    853	int cmd_type, err, opcode;
    854	unsigned long timeout;
    855
    856	if (!mbx)
    857		return -EIO;
    858
    859	opcode = LSW(cmd->req.arg[0]);
    860	cmd_type = cmd->type;
    861	err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
    862	if (err) {
    863		dev_err(&adapter->pdev->dev,
    864			"%s: Mailbox not available, cmd_op=0x%x, cmd_context=0x%x, pci_func=0x%x, op_mode=0x%x\n",
    865			__func__, opcode, cmd->type, ahw->pci_func,
    866			ahw->op_mode);
    867		return err;
    868	}
    869
    870	switch (cmd_type) {
    871	case QLC_83XX_MBX_CMD_WAIT:
    872		if (!wait_for_completion_timeout(&cmd->completion, timeout)) {
    873			dev_err(&adapter->pdev->dev,
    874				"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
    875				__func__, opcode, cmd_type, ahw->pci_func,
    876				ahw->op_mode);
    877			flush_workqueue(mbx->work_q);
    878		}
    879		break;
    880	case QLC_83XX_MBX_CMD_NO_WAIT:
    881		return 0;
    882	case QLC_83XX_MBX_CMD_BUSY_WAIT:
    883		qlcnic_83xx_poll_for_mbx_completion(adapter, cmd);
    884		break;
    885	default:
    886		dev_err(&adapter->pdev->dev,
    887			"%s: Invalid mailbox command, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
    888			__func__, opcode, cmd_type, ahw->pci_func,
    889			ahw->op_mode);
    890		qlcnic_83xx_detach_mailbox_work(adapter);
    891	}
    892
    893	return cmd->rsp_opcode;
    894}
    895
    896int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
    897			       struct qlcnic_adapter *adapter, u32 type)
    898{
    899	int i, size;
    900	u32 temp;
    901	const struct qlcnic_mailbox_metadata *mbx_tbl;
    902
    903	memset(mbx, 0, sizeof(struct qlcnic_cmd_args));
    904	mbx_tbl = qlcnic_83xx_mbx_tbl;
    905	size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl);
    906	for (i = 0; i < size; i++) {
    907		if (type == mbx_tbl[i].cmd) {
    908			mbx->op_type = QLC_83XX_FW_MBX_CMD;
    909			mbx->req.num = mbx_tbl[i].in_args;
    910			mbx->rsp.num = mbx_tbl[i].out_args;
    911			mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32),
    912					       GFP_ATOMIC);
    913			if (!mbx->req.arg)
    914				return -ENOMEM;
    915			mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32),
    916					       GFP_ATOMIC);
    917			if (!mbx->rsp.arg) {
    918				kfree(mbx->req.arg);
    919				mbx->req.arg = NULL;
    920				return -ENOMEM;
    921			}
    922			temp = adapter->ahw->fw_hal_version << 29;
    923			mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
    924			mbx->cmd_op = type;
    925			return 0;
    926		}
    927	}
    928
    929	dev_err(&adapter->pdev->dev, "%s: Invalid mailbox command opcode 0x%x\n",
    930		__func__, type);
    931	return -EINVAL;
    932}
    933
    934void qlcnic_83xx_idc_aen_work(struct work_struct *work)
    935{
    936	struct qlcnic_adapter *adapter;
    937	struct qlcnic_cmd_args cmd;
    938	int i, err = 0;
    939
    940	adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work);
    941	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK);
    942	if (err)
    943		return;
    944
    945	for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++)
    946		cmd.req.arg[i] = adapter->ahw->mbox_aen[i];
    947
    948	err = qlcnic_issue_cmd(adapter, &cmd);
    949	if (err)
    950		dev_info(&adapter->pdev->dev,
    951			 "%s: Mailbox IDC ACK failed.\n", __func__);
    952	qlcnic_free_mbx_args(&cmd);
    953}
    954
    955static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter,
    956					    u32 data[])
    957{
    958	dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n",
    959		QLCNIC_MBX_RSP(data[0]));
    960	clear_bit(QLC_83XX_IDC_COMP_AEN, &adapter->ahw->idc.status);
    961	return;
    962}
    963
    964static void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
    965{
    966	struct qlcnic_hardware_context *ahw = adapter->ahw;
    967	u32 event[QLC_83XX_MBX_AEN_CNT];
    968	int i;
    969
    970	for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
    971		event[i] = readl(QLCNIC_MBX_FW(ahw, i));
    972
    973	switch (QLCNIC_MBX_RSP(event[0])) {
    974
    975	case QLCNIC_MBX_LINK_EVENT:
    976		qlcnic_83xx_handle_link_aen(adapter, event);
    977		break;
    978	case QLCNIC_MBX_COMP_EVENT:
    979		qlcnic_83xx_handle_idc_comp_aen(adapter, event);
    980		break;
    981	case QLCNIC_MBX_REQUEST_EVENT:
    982		for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++)
    983			adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]);
    984		queue_delayed_work(adapter->qlcnic_wq,
    985				   &adapter->idc_aen_work, 0);
    986		break;
    987	case QLCNIC_MBX_TIME_EXTEND_EVENT:
    988		ahw->extend_lb_time = event[1] >> 8 & 0xf;
    989		break;
    990	case QLCNIC_MBX_BC_EVENT:
    991		qlcnic_sriov_handle_bc_event(adapter, event[1]);
    992		break;
    993	case QLCNIC_MBX_SFP_INSERT_EVENT:
    994		dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n",
    995			 QLCNIC_MBX_RSP(event[0]));
    996		break;
    997	case QLCNIC_MBX_SFP_REMOVE_EVENT:
    998		dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n",
    999			 QLCNIC_MBX_RSP(event[0]));
   1000		break;
   1001	case QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT:
   1002		qlcnic_dcb_aen_handler(adapter->dcb, (void *)&event[1]);
   1003		break;
   1004	default:
   1005		dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n",
   1006			QLCNIC_MBX_RSP(event[0]));
   1007		break;
   1008	}
   1009
   1010	QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
   1011}
   1012
   1013static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
   1014{
   1015	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
   1016	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1017	struct qlcnic_mailbox *mbx = ahw->mailbox;
   1018	unsigned long flags;
   1019
   1020	spin_lock_irqsave(&mbx->aen_lock, flags);
   1021	resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
   1022	if (resp & QLCNIC_SET_OWNER) {
   1023		event = readl(QLCNIC_MBX_FW(ahw, 0));
   1024		if (event &  QLCNIC_MBX_ASYNC_EVENT) {
   1025			__qlcnic_83xx_process_aen(adapter);
   1026		} else {
   1027			if (mbx->rsp_status != rsp_status)
   1028				qlcnic_83xx_notify_mbx_response(mbx);
   1029		}
   1030	}
   1031	spin_unlock_irqrestore(&mbx->aen_lock, flags);
   1032}
   1033
   1034static void qlcnic_83xx_mbx_poll_work(struct work_struct *work)
   1035{
   1036	struct qlcnic_adapter *adapter;
   1037
   1038	adapter = container_of(work, struct qlcnic_adapter, mbx_poll_work.work);
   1039
   1040	if (!test_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
   1041		return;
   1042
   1043	qlcnic_83xx_process_aen(adapter);
   1044	queue_delayed_work(adapter->qlcnic_wq, &adapter->mbx_poll_work,
   1045			   (HZ / 10));
   1046}
   1047
   1048void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *adapter)
   1049{
   1050	if (test_and_set_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
   1051		return;
   1052
   1053	INIT_DELAYED_WORK(&adapter->mbx_poll_work, qlcnic_83xx_mbx_poll_work);
   1054	queue_delayed_work(adapter->qlcnic_wq, &adapter->mbx_poll_work, 0);
   1055}
   1056
   1057void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *adapter)
   1058{
   1059	if (!test_and_clear_bit(__QLCNIC_MBX_POLL_ENABLE, &adapter->state))
   1060		return;
   1061	cancel_delayed_work_sync(&adapter->mbx_poll_work);
   1062}
   1063
   1064static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)
   1065{
   1066	int index, i, err, sds_mbx_size;
   1067	u32 *buf, intrpt_id, intr_mask;
   1068	u16 context_id;
   1069	u8 num_sds;
   1070	struct qlcnic_cmd_args cmd;
   1071	struct qlcnic_host_sds_ring *sds;
   1072	struct qlcnic_sds_mbx sds_mbx;
   1073	struct qlcnic_add_rings_mbx_out *mbx_out;
   1074	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
   1075	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1076
   1077	sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
   1078	context_id = recv_ctx->context_id;
   1079	num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS;
   1080	err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
   1081					QLCNIC_CMD_ADD_RCV_RINGS);
   1082	if (err) {
   1083		dev_err(&adapter->pdev->dev,
   1084			"Failed to alloc mbx args %d\n", err);
   1085		return err;
   1086	}
   1087
   1088	cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
   1089
   1090	/* set up status rings, mbx 2-81 */
   1091	index = 2;
   1092	for (i = 8; i < adapter->drv_sds_rings; i++) {
   1093		memset(&sds_mbx, 0, sds_mbx_size);
   1094		sds = &recv_ctx->sds_rings[i];
   1095		sds->consumer = 0;
   1096		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
   1097		sds_mbx.phy_addr_low = LSD(sds->phys_addr);
   1098		sds_mbx.phy_addr_high = MSD(sds->phys_addr);
   1099		sds_mbx.sds_ring_size = sds->num_desc;
   1100
   1101		if (adapter->flags & QLCNIC_MSIX_ENABLED)
   1102			intrpt_id = ahw->intr_tbl[i].id;
   1103		else
   1104			intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
   1105
   1106		if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
   1107			sds_mbx.intrpt_id = intrpt_id;
   1108		else
   1109			sds_mbx.intrpt_id = 0xffff;
   1110		sds_mbx.intrpt_val = 0;
   1111		buf = &cmd.req.arg[index];
   1112		memcpy(buf, &sds_mbx, sds_mbx_size);
   1113		index += sds_mbx_size / sizeof(u32);
   1114	}
   1115
   1116	/* send the mailbox command */
   1117	err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
   1118	if (err) {
   1119		dev_err(&adapter->pdev->dev,
   1120			"Failed to add rings %d\n", err);
   1121		goto out;
   1122	}
   1123
   1124	mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1];
   1125	index = 0;
   1126	/* status descriptor ring */
   1127	for (i = 8; i < adapter->drv_sds_rings; i++) {
   1128		sds = &recv_ctx->sds_rings[i];
   1129		sds->crb_sts_consumer = ahw->pci_base0 +
   1130					mbx_out->host_csmr[index];
   1131		if (adapter->flags & QLCNIC_MSIX_ENABLED)
   1132			intr_mask = ahw->intr_tbl[i].src;
   1133		else
   1134			intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
   1135
   1136		sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
   1137		index++;
   1138	}
   1139out:
   1140	qlcnic_free_mbx_args(&cmd);
   1141	return err;
   1142}
   1143
   1144void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *adapter)
   1145{
   1146	int err;
   1147	u32 temp = 0;
   1148	struct qlcnic_cmd_args cmd;
   1149	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
   1150
   1151	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX))
   1152		return;
   1153
   1154	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
   1155		cmd.req.arg[0] |= (0x3 << 29);
   1156
   1157	if (qlcnic_sriov_pf_check(adapter))
   1158		qlcnic_pf_set_interface_id_del_rx_ctx(adapter, &temp);
   1159
   1160	cmd.req.arg[1] = recv_ctx->context_id | temp;
   1161	err = qlcnic_issue_cmd(adapter, &cmd);
   1162	if (err)
   1163		dev_err(&adapter->pdev->dev,
   1164			"Failed to destroy rx ctx in firmware\n");
   1165
   1166	recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
   1167	qlcnic_free_mbx_args(&cmd);
   1168}
   1169
   1170int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)
   1171{
   1172	int i, err, index, sds_mbx_size, rds_mbx_size;
   1173	u8 num_sds, num_rds;
   1174	u32 *buf, intrpt_id, intr_mask, cap = 0;
   1175	struct qlcnic_host_sds_ring *sds;
   1176	struct qlcnic_host_rds_ring *rds;
   1177	struct qlcnic_sds_mbx sds_mbx;
   1178	struct qlcnic_rds_mbx rds_mbx;
   1179	struct qlcnic_cmd_args cmd;
   1180	struct qlcnic_rcv_mbx_out *mbx_out;
   1181	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
   1182	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1183	num_rds = adapter->max_rds_rings;
   1184
   1185	if (adapter->drv_sds_rings <= QLCNIC_MAX_SDS_RINGS)
   1186		num_sds = adapter->drv_sds_rings;
   1187	else
   1188		num_sds = QLCNIC_MAX_SDS_RINGS;
   1189
   1190	sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
   1191	rds_mbx_size = sizeof(struct qlcnic_rds_mbx);
   1192	cap = QLCNIC_CAP0_LEGACY_CONTEXT;
   1193
   1194	if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
   1195		cap |= QLC_83XX_FW_CAP_LRO_MSS;
   1196
   1197	/* set mailbox hdr and capabilities */
   1198	err = qlcnic_alloc_mbx_args(&cmd, adapter,
   1199				    QLCNIC_CMD_CREATE_RX_CTX);
   1200	if (err)
   1201		return err;
   1202
   1203	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
   1204		cmd.req.arg[0] |= (0x3 << 29);
   1205
   1206	cmd.req.arg[1] = cap;
   1207	cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) |
   1208			 (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16);
   1209
   1210	if (qlcnic_sriov_pf_check(adapter))
   1211		qlcnic_pf_set_interface_id_create_rx_ctx(adapter,
   1212							 &cmd.req.arg[6]);
   1213	/* set up status rings, mbx 8-57/87 */
   1214	index = QLC_83XX_HOST_SDS_MBX_IDX;
   1215	for (i = 0; i < num_sds; i++) {
   1216		memset(&sds_mbx, 0, sds_mbx_size);
   1217		sds = &recv_ctx->sds_rings[i];
   1218		sds->consumer = 0;
   1219		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds));
   1220		sds_mbx.phy_addr_low = LSD(sds->phys_addr);
   1221		sds_mbx.phy_addr_high = MSD(sds->phys_addr);
   1222		sds_mbx.sds_ring_size = sds->num_desc;
   1223		if (adapter->flags & QLCNIC_MSIX_ENABLED)
   1224			intrpt_id = ahw->intr_tbl[i].id;
   1225		else
   1226			intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
   1227		if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
   1228			sds_mbx.intrpt_id = intrpt_id;
   1229		else
   1230			sds_mbx.intrpt_id = 0xffff;
   1231		sds_mbx.intrpt_val = 0;
   1232		buf = &cmd.req.arg[index];
   1233		memcpy(buf, &sds_mbx, sds_mbx_size);
   1234		index += sds_mbx_size / sizeof(u32);
   1235	}
   1236	/* set up receive rings, mbx 88-111/135 */
   1237	index = QLCNIC_HOST_RDS_MBX_IDX;
   1238	rds = &recv_ctx->rds_rings[0];
   1239	rds->producer = 0;
   1240	memset(&rds_mbx, 0, rds_mbx_size);
   1241	rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr);
   1242	rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);
   1243	rds_mbx.reg_ring_sz = rds->dma_size;
   1244	rds_mbx.reg_ring_len = rds->num_desc;
   1245	/* Jumbo ring */
   1246	rds = &recv_ctx->rds_rings[1];
   1247	rds->producer = 0;
   1248	rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr);
   1249	rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);
   1250	rds_mbx.jmb_ring_sz = rds->dma_size;
   1251	rds_mbx.jmb_ring_len = rds->num_desc;
   1252	buf = &cmd.req.arg[index];
   1253	memcpy(buf, &rds_mbx, rds_mbx_size);
   1254
   1255	/* send the mailbox command */
   1256	err = ahw->hw_ops->mbx_cmd(adapter, &cmd);
   1257	if (err) {
   1258		dev_err(&adapter->pdev->dev,
   1259			"Failed to create Rx ctx in firmware%d\n", err);
   1260		goto out;
   1261	}
   1262	mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1];
   1263	recv_ctx->context_id = mbx_out->ctx_id;
   1264	recv_ctx->state = mbx_out->state;
   1265	recv_ctx->virt_port = mbx_out->vport_id;
   1266	dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n",
   1267		 recv_ctx->context_id, recv_ctx->state);
   1268	/* Receive descriptor ring */
   1269	/* Standard ring */
   1270	rds = &recv_ctx->rds_rings[0];
   1271	rds->crb_rcv_producer = ahw->pci_base0 +
   1272				mbx_out->host_prod[0].reg_buf;
   1273	/* Jumbo ring */
   1274	rds = &recv_ctx->rds_rings[1];
   1275	rds->crb_rcv_producer = ahw->pci_base0 +
   1276				mbx_out->host_prod[0].jmb_buf;
   1277	/* status descriptor ring */
   1278	for (i = 0; i < num_sds; i++) {
   1279		sds = &recv_ctx->sds_rings[i];
   1280		sds->crb_sts_consumer = ahw->pci_base0 +
   1281					mbx_out->host_csmr[i];
   1282		if (adapter->flags & QLCNIC_MSIX_ENABLED)
   1283			intr_mask = ahw->intr_tbl[i].src;
   1284		else
   1285			intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
   1286		sds->crb_intr_mask = ahw->pci_base0 + intr_mask;
   1287	}
   1288
   1289	if (adapter->drv_sds_rings > QLCNIC_MAX_SDS_RINGS)
   1290		err = qlcnic_83xx_add_rings(adapter);
   1291out:
   1292	qlcnic_free_mbx_args(&cmd);
   1293	return err;
   1294}
   1295
   1296void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *adapter,
   1297			    struct qlcnic_host_tx_ring *tx_ring)
   1298{
   1299	struct qlcnic_cmd_args cmd;
   1300	u32 temp = 0;
   1301
   1302	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX))
   1303		return;
   1304
   1305	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
   1306		cmd.req.arg[0] |= (0x3 << 29);
   1307
   1308	if (qlcnic_sriov_pf_check(adapter))
   1309		qlcnic_pf_set_interface_id_del_tx_ctx(adapter, &temp);
   1310
   1311	cmd.req.arg[1] = tx_ring->ctx_id | temp;
   1312	if (qlcnic_issue_cmd(adapter, &cmd))
   1313		dev_err(&adapter->pdev->dev,
   1314			"Failed to destroy tx ctx in firmware\n");
   1315	qlcnic_free_mbx_args(&cmd);
   1316}
   1317
   1318int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
   1319			      struct qlcnic_host_tx_ring *tx, int ring)
   1320{
   1321	int err;
   1322	u16 msix_id;
   1323	u32 *buf, intr_mask, temp = 0;
   1324	struct qlcnic_cmd_args cmd;
   1325	struct qlcnic_tx_mbx mbx;
   1326	struct qlcnic_tx_mbx_out *mbx_out;
   1327	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1328	u32 msix_vector;
   1329
   1330	/* Reset host resources */
   1331	tx->producer = 0;
   1332	tx->sw_consumer = 0;
   1333	*(tx->hw_consumer) = 0;
   1334
   1335	memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));
   1336
   1337	/* setup mailbox inbox registerss */
   1338	mbx.phys_addr_low = LSD(tx->phys_addr);
   1339	mbx.phys_addr_high = MSD(tx->phys_addr);
   1340	mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
   1341	mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
   1342	mbx.size = tx->num_desc;
   1343	if (adapter->flags & QLCNIC_MSIX_ENABLED) {
   1344		if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
   1345			msix_vector = adapter->drv_sds_rings + ring;
   1346		else
   1347			msix_vector = adapter->drv_sds_rings - 1;
   1348		msix_id = ahw->intr_tbl[msix_vector].id;
   1349	} else {
   1350		msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
   1351	}
   1352
   1353	if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
   1354		mbx.intr_id = msix_id;
   1355	else
   1356		mbx.intr_id = 0xffff;
   1357	mbx.src = 0;
   1358
   1359	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
   1360	if (err)
   1361		return err;
   1362
   1363	if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter))
   1364		cmd.req.arg[0] |= (0x3 << 29);
   1365
   1366	if (qlcnic_sriov_pf_check(adapter))
   1367		qlcnic_pf_set_interface_id_create_tx_ctx(adapter, &temp);
   1368
   1369	cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT;
   1370	cmd.req.arg[5] = QLCNIC_SINGLE_RING | temp;
   1371
   1372	buf = &cmd.req.arg[6];
   1373	memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx));
   1374	/* send the mailbox command*/
   1375	err = qlcnic_issue_cmd(adapter, &cmd);
   1376	if (err) {
   1377		netdev_err(adapter->netdev,
   1378			   "Failed to create Tx ctx in firmware 0x%x\n", err);
   1379		goto out;
   1380	}
   1381	mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
   1382	tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
   1383	tx->ctx_id = mbx_out->ctx_id;
   1384	if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
   1385	    !(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
   1386		intr_mask = ahw->intr_tbl[adapter->drv_sds_rings + ring].src;
   1387		tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
   1388	}
   1389	netdev_info(adapter->netdev,
   1390		    "Tx Context[0x%x] Created, state:0x%x\n",
   1391		    tx->ctx_id, mbx_out->state);
   1392out:
   1393	qlcnic_free_mbx_args(&cmd);
   1394	return err;
   1395}
   1396
   1397static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test,
   1398				      u8 num_sds_ring)
   1399{
   1400	struct qlcnic_adapter *adapter = netdev_priv(netdev);
   1401	struct qlcnic_host_sds_ring *sds_ring;
   1402	struct qlcnic_host_rds_ring *rds_ring;
   1403	u16 adapter_state = adapter->is_up;
   1404	u8 ring;
   1405	int ret;
   1406
   1407	netif_device_detach(netdev);
   1408
   1409	if (netif_running(netdev))
   1410		__qlcnic_down(adapter, netdev);
   1411
   1412	qlcnic_detach(adapter);
   1413
   1414	adapter->drv_sds_rings = QLCNIC_SINGLE_RING;
   1415	adapter->ahw->diag_test = test;
   1416	adapter->ahw->linkup = 0;
   1417
   1418	ret = qlcnic_attach(adapter);
   1419	if (ret) {
   1420		netif_device_attach(netdev);
   1421		return ret;
   1422	}
   1423
   1424	ret = qlcnic_fw_create_ctx(adapter);
   1425	if (ret) {
   1426		qlcnic_detach(adapter);
   1427		if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) {
   1428			adapter->drv_sds_rings = num_sds_ring;
   1429			qlcnic_attach(adapter);
   1430		}
   1431		netif_device_attach(netdev);
   1432		return ret;
   1433	}
   1434
   1435	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
   1436		rds_ring = &adapter->recv_ctx->rds_rings[ring];
   1437		qlcnic_post_rx_buffers(adapter, rds_ring, ring);
   1438	}
   1439
   1440	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
   1441		for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
   1442			sds_ring = &adapter->recv_ctx->sds_rings[ring];
   1443			qlcnic_enable_sds_intr(adapter, sds_ring);
   1444		}
   1445	}
   1446
   1447	if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
   1448		adapter->ahw->loopback_state = 0;
   1449		adapter->ahw->hw_ops->setup_link_event(adapter, 1);
   1450	}
   1451
   1452	set_bit(__QLCNIC_DEV_UP, &adapter->state);
   1453	return 0;
   1454}
   1455
   1456static void qlcnic_83xx_diag_free_res(struct net_device *netdev,
   1457				      u8 drv_sds_rings)
   1458{
   1459	struct qlcnic_adapter *adapter = netdev_priv(netdev);
   1460	struct qlcnic_host_sds_ring *sds_ring;
   1461	int ring;
   1462
   1463	clear_bit(__QLCNIC_DEV_UP, &adapter->state);
   1464	if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
   1465		for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
   1466			sds_ring = &adapter->recv_ctx->sds_rings[ring];
   1467			if (adapter->flags & QLCNIC_MSIX_ENABLED)
   1468				qlcnic_disable_sds_intr(adapter, sds_ring);
   1469		}
   1470	}
   1471
   1472	qlcnic_fw_destroy_ctx(adapter);
   1473	qlcnic_detach(adapter);
   1474
   1475	adapter->ahw->diag_test = 0;
   1476	adapter->drv_sds_rings = drv_sds_rings;
   1477
   1478	if (qlcnic_attach(adapter))
   1479		goto out;
   1480
   1481	if (netif_running(netdev))
   1482		__qlcnic_up(adapter, netdev);
   1483
   1484out:
   1485	netif_device_attach(netdev);
   1486}
   1487
   1488static void qlcnic_83xx_get_beacon_state(struct qlcnic_adapter *adapter)
   1489{
   1490	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1491	struct qlcnic_cmd_args cmd;
   1492	u8 beacon_state;
   1493	int err = 0;
   1494
   1495	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_CONFIG);
   1496	if (!err) {
   1497		err = qlcnic_issue_cmd(adapter, &cmd);
   1498		if (!err) {
   1499			beacon_state = cmd.rsp.arg[4];
   1500			if (beacon_state == QLCNIC_BEACON_DISABLE)
   1501				ahw->beacon_state = QLC_83XX_BEACON_OFF;
   1502			else if (beacon_state == QLC_83XX_ENABLE_BEACON)
   1503				ahw->beacon_state = QLC_83XX_BEACON_ON;
   1504		}
   1505	} else {
   1506		netdev_err(adapter->netdev, "Get beacon state failed, err=%d\n",
   1507			   err);
   1508	}
   1509
   1510	qlcnic_free_mbx_args(&cmd);
   1511
   1512	return;
   1513}
   1514
   1515int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state,
   1516			   u32 beacon)
   1517{
   1518	struct qlcnic_cmd_args cmd;
   1519	u32 mbx_in;
   1520	int i, status = 0;
   1521
   1522	if (state) {
   1523		/* Get LED configuration */
   1524		status = qlcnic_alloc_mbx_args(&cmd, adapter,
   1525					       QLCNIC_CMD_GET_LED_CONFIG);
   1526		if (status)
   1527			return status;
   1528
   1529		status = qlcnic_issue_cmd(adapter, &cmd);
   1530		if (status) {
   1531			dev_err(&adapter->pdev->dev,
   1532				"Get led config failed.\n");
   1533			goto mbx_err;
   1534		} else {
   1535			for (i = 0; i < 4; i++)
   1536				adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1];
   1537		}
   1538		qlcnic_free_mbx_args(&cmd);
   1539		/* Set LED Configuration */
   1540		mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) |
   1541			  LSW(QLC_83XX_LED_CONFIG);
   1542		status = qlcnic_alloc_mbx_args(&cmd, adapter,
   1543					       QLCNIC_CMD_SET_LED_CONFIG);
   1544		if (status)
   1545			return status;
   1546
   1547		cmd.req.arg[1] = mbx_in;
   1548		cmd.req.arg[2] = mbx_in;
   1549		cmd.req.arg[3] = mbx_in;
   1550		if (beacon)
   1551			cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON;
   1552		status = qlcnic_issue_cmd(adapter, &cmd);
   1553		if (status) {
   1554			dev_err(&adapter->pdev->dev,
   1555				"Set led config failed.\n");
   1556		}
   1557mbx_err:
   1558		qlcnic_free_mbx_args(&cmd);
   1559		return status;
   1560
   1561	} else {
   1562		/* Restoring default LED configuration */
   1563		status = qlcnic_alloc_mbx_args(&cmd, adapter,
   1564					       QLCNIC_CMD_SET_LED_CONFIG);
   1565		if (status)
   1566			return status;
   1567
   1568		cmd.req.arg[1] = adapter->ahw->mbox_reg[0];
   1569		cmd.req.arg[2] = adapter->ahw->mbox_reg[1];
   1570		cmd.req.arg[3] = adapter->ahw->mbox_reg[2];
   1571		if (beacon)
   1572			cmd.req.arg[4] = adapter->ahw->mbox_reg[3];
   1573		status = qlcnic_issue_cmd(adapter, &cmd);
   1574		if (status)
   1575			dev_err(&adapter->pdev->dev,
   1576				"Restoring led config failed.\n");
   1577		qlcnic_free_mbx_args(&cmd);
   1578		return status;
   1579	}
   1580}
   1581
   1582int  qlcnic_83xx_set_led(struct net_device *netdev,
   1583			 enum ethtool_phys_id_state state)
   1584{
   1585	struct qlcnic_adapter *adapter = netdev_priv(netdev);
   1586	int err = -EIO, active = 1;
   1587
   1588	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
   1589		netdev_warn(netdev,
   1590			    "LED test is not supported in non-privileged mode\n");
   1591		return -EOPNOTSUPP;
   1592	}
   1593
   1594	switch (state) {
   1595	case ETHTOOL_ID_ACTIVE:
   1596		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
   1597			return -EBUSY;
   1598
   1599		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
   1600			break;
   1601
   1602		err = qlcnic_83xx_config_led(adapter, active, 0);
   1603		if (err)
   1604			netdev_err(netdev, "Failed to set LED blink state\n");
   1605		break;
   1606	case ETHTOOL_ID_INACTIVE:
   1607		active = 0;
   1608
   1609		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
   1610			break;
   1611
   1612		err = qlcnic_83xx_config_led(adapter, active, 0);
   1613		if (err)
   1614			netdev_err(netdev, "Failed to reset LED blink state\n");
   1615		break;
   1616
   1617	default:
   1618		return -EINVAL;
   1619	}
   1620
   1621	if (!active || err)
   1622		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
   1623
   1624	return err;
   1625}
   1626
   1627void qlcnic_83xx_initialize_nic(struct qlcnic_adapter *adapter, int enable)
   1628{
   1629	struct qlcnic_cmd_args cmd;
   1630	int status;
   1631
   1632	if (qlcnic_sriov_vf_check(adapter))
   1633		return;
   1634
   1635	if (enable)
   1636		status = qlcnic_alloc_mbx_args(&cmd, adapter,
   1637					       QLCNIC_CMD_INIT_NIC_FUNC);
   1638	else
   1639		status = qlcnic_alloc_mbx_args(&cmd, adapter,
   1640					       QLCNIC_CMD_STOP_NIC_FUNC);
   1641
   1642	if (status)
   1643		return;
   1644
   1645	cmd.req.arg[1] = QLC_REGISTER_LB_IDC | QLC_INIT_FW_RESOURCES;
   1646
   1647	if (adapter->dcb)
   1648		cmd.req.arg[1] |= QLC_REGISTER_DCB_AEN;
   1649
   1650	status = qlcnic_issue_cmd(adapter, &cmd);
   1651	if (status)
   1652		dev_err(&adapter->pdev->dev,
   1653			"Failed to %s in NIC IDC function event.\n",
   1654			(enable ? "register" : "unregister"));
   1655
   1656	qlcnic_free_mbx_args(&cmd);
   1657}
   1658
   1659static int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter)
   1660{
   1661	struct qlcnic_cmd_args cmd;
   1662	int err;
   1663
   1664	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG);
   1665	if (err)
   1666		return err;
   1667
   1668	cmd.req.arg[1] = adapter->ahw->port_config;
   1669	err = qlcnic_issue_cmd(adapter, &cmd);
   1670	if (err)
   1671		dev_info(&adapter->pdev->dev, "Set Port Config failed.\n");
   1672	qlcnic_free_mbx_args(&cmd);
   1673	return err;
   1674}
   1675
   1676static int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter)
   1677{
   1678	struct qlcnic_cmd_args cmd;
   1679	int err;
   1680
   1681	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG);
   1682	if (err)
   1683		return err;
   1684
   1685	err = qlcnic_issue_cmd(adapter, &cmd);
   1686	if (err)
   1687		dev_info(&adapter->pdev->dev, "Get Port config failed\n");
   1688	else
   1689		adapter->ahw->port_config = cmd.rsp.arg[1];
   1690	qlcnic_free_mbx_args(&cmd);
   1691	return err;
   1692}
   1693
   1694int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable)
   1695{
   1696	int err;
   1697	u32 temp;
   1698	struct qlcnic_cmd_args cmd;
   1699
   1700	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT);
   1701	if (err)
   1702		return err;
   1703
   1704	temp = adapter->recv_ctx->context_id << 16;
   1705	cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp;
   1706	err = qlcnic_issue_cmd(adapter, &cmd);
   1707	if (err)
   1708		dev_info(&adapter->pdev->dev,
   1709			 "Setup linkevent mailbox failed\n");
   1710	qlcnic_free_mbx_args(&cmd);
   1711	return err;
   1712}
   1713
   1714static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,
   1715						 u32 *interface_id)
   1716{
   1717	if (qlcnic_sriov_pf_check(adapter)) {
   1718		qlcnic_alloc_lb_filters_mem(adapter);
   1719		qlcnic_pf_set_interface_id_promisc(adapter, interface_id);
   1720		adapter->rx_mac_learn = true;
   1721	} else {
   1722		if (!qlcnic_sriov_vf_check(adapter))
   1723			*interface_id = adapter->recv_ctx->context_id << 16;
   1724	}
   1725}
   1726
   1727int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
   1728{
   1729	struct qlcnic_cmd_args *cmd = NULL;
   1730	u32 temp = 0;
   1731	int err;
   1732
   1733	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
   1734		return -EIO;
   1735
   1736	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
   1737	if (!cmd)
   1738		return -ENOMEM;
   1739
   1740	err = qlcnic_alloc_mbx_args(cmd, adapter,
   1741				    QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
   1742	if (err)
   1743		goto out;
   1744
   1745	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
   1746	qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
   1747
   1748	if (qlcnic_84xx_check(adapter) && qlcnic_sriov_pf_check(adapter))
   1749		mode = VPORT_MISS_MODE_ACCEPT_ALL;
   1750
   1751	cmd->req.arg[1] = mode | temp;
   1752	err = qlcnic_issue_cmd(adapter, cmd);
   1753	if (!err)
   1754		return err;
   1755
   1756	qlcnic_free_mbx_args(cmd);
   1757
   1758out:
   1759	kfree(cmd);
   1760	return err;
   1761}
   1762
   1763int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode)
   1764{
   1765	struct qlcnic_adapter *adapter = netdev_priv(netdev);
   1766	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1767	u8 drv_sds_rings = adapter->drv_sds_rings;
   1768	u8 drv_tx_rings = adapter->drv_tx_rings;
   1769	int ret = 0, loop = 0;
   1770
   1771	if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
   1772		netdev_warn(netdev,
   1773			    "Loopback test not supported in non privileged mode\n");
   1774		return -ENOTSUPP;
   1775	}
   1776
   1777	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
   1778		netdev_info(netdev, "Device is resetting\n");
   1779		return -EBUSY;
   1780	}
   1781
   1782	if (qlcnic_get_diag_lock(adapter)) {
   1783		netdev_info(netdev, "Device is in diagnostics mode\n");
   1784		return -EBUSY;
   1785	}
   1786
   1787	netdev_info(netdev, "%s loopback test in progress\n",
   1788		    mode == QLCNIC_ILB_MODE ? "internal" : "external");
   1789
   1790	ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST,
   1791					 drv_sds_rings);
   1792	if (ret)
   1793		goto fail_diag_alloc;
   1794
   1795	ret = qlcnic_83xx_set_lb_mode(adapter, mode);
   1796	if (ret)
   1797		goto free_diag_res;
   1798
   1799	/* Poll for link up event before running traffic */
   1800	do {
   1801		msleep(QLC_83XX_LB_MSLEEP_COUNT);
   1802
   1803		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
   1804			netdev_info(netdev,
   1805				    "Device is resetting, free LB test resources\n");
   1806			ret = -EBUSY;
   1807			goto free_diag_res;
   1808		}
   1809		if (loop++ > QLC_83XX_LB_WAIT_COUNT) {
   1810			netdev_info(netdev,
   1811				    "Firmware didn't sent link up event to loopback request\n");
   1812			ret = -ETIMEDOUT;
   1813			qlcnic_83xx_clear_lb_mode(adapter, mode);
   1814			goto free_diag_res;
   1815		}
   1816	} while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
   1817
   1818	ret = qlcnic_do_lb_test(adapter, mode);
   1819
   1820	qlcnic_83xx_clear_lb_mode(adapter, mode);
   1821
   1822free_diag_res:
   1823	qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
   1824
   1825fail_diag_alloc:
   1826	adapter->drv_sds_rings = drv_sds_rings;
   1827	adapter->drv_tx_rings = drv_tx_rings;
   1828	qlcnic_release_diag_lock(adapter);
   1829	return ret;
   1830}
   1831
   1832static void qlcnic_extend_lb_idc_cmpltn_wait(struct qlcnic_adapter *adapter,
   1833					     u32 *max_wait_count)
   1834{
   1835	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1836	int temp;
   1837
   1838	netdev_info(adapter->netdev, "Received loopback IDC time extend event for 0x%x seconds\n",
   1839		    ahw->extend_lb_time);
   1840	temp = ahw->extend_lb_time * 1000;
   1841	*max_wait_count += temp / QLC_83XX_LB_MSLEEP_COUNT;
   1842	ahw->extend_lb_time = 0;
   1843}
   1844
   1845static int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
   1846{
   1847	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1848	struct net_device *netdev = adapter->netdev;
   1849	u32 config, max_wait_count;
   1850	int status = 0, loop = 0;
   1851
   1852	ahw->extend_lb_time = 0;
   1853	max_wait_count = QLC_83XX_LB_WAIT_COUNT;
   1854	status = qlcnic_83xx_get_port_config(adapter);
   1855	if (status)
   1856		return status;
   1857
   1858	config = ahw->port_config;
   1859
   1860	/* Check if port is already in loopback mode */
   1861	if ((config & QLC_83XX_CFG_LOOPBACK_HSS) ||
   1862	    (config & QLC_83XX_CFG_LOOPBACK_EXT)) {
   1863		netdev_err(netdev,
   1864			   "Port already in Loopback mode.\n");
   1865		return -EINPROGRESS;
   1866	}
   1867
   1868	set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1869
   1870	if (mode == QLCNIC_ILB_MODE)
   1871		ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS;
   1872	if (mode == QLCNIC_ELB_MODE)
   1873		ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT;
   1874
   1875	status = qlcnic_83xx_set_port_config(adapter);
   1876	if (status) {
   1877		netdev_err(netdev,
   1878			   "Failed to Set Loopback Mode = 0x%x.\n",
   1879			   ahw->port_config);
   1880		ahw->port_config = config;
   1881		clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1882		return status;
   1883	}
   1884
   1885	/* Wait for Link and IDC Completion AEN */
   1886	do {
   1887		msleep(QLC_83XX_LB_MSLEEP_COUNT);
   1888
   1889		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
   1890			netdev_info(netdev,
   1891				    "Device is resetting, free LB test resources\n");
   1892			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1893			return -EBUSY;
   1894		}
   1895
   1896		if (ahw->extend_lb_time)
   1897			qlcnic_extend_lb_idc_cmpltn_wait(adapter,
   1898							 &max_wait_count);
   1899
   1900		if (loop++ > max_wait_count) {
   1901			netdev_err(netdev, "%s: Did not receive loopback IDC completion AEN\n",
   1902				   __func__);
   1903			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1904			qlcnic_83xx_clear_lb_mode(adapter, mode);
   1905			return -ETIMEDOUT;
   1906		}
   1907	} while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
   1908
   1909	qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
   1910				  QLCNIC_MAC_ADD);
   1911	return status;
   1912}
   1913
   1914static int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
   1915{
   1916	struct qlcnic_hardware_context *ahw = adapter->ahw;
   1917	u32 config = ahw->port_config, max_wait_count;
   1918	struct net_device *netdev = adapter->netdev;
   1919	int status = 0, loop = 0;
   1920
   1921	ahw->extend_lb_time = 0;
   1922	max_wait_count = QLC_83XX_LB_WAIT_COUNT;
   1923	set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1924	if (mode == QLCNIC_ILB_MODE)
   1925		ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS;
   1926	if (mode == QLCNIC_ELB_MODE)
   1927		ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT;
   1928
   1929	status = qlcnic_83xx_set_port_config(adapter);
   1930	if (status) {
   1931		netdev_err(netdev,
   1932			   "Failed to Clear Loopback Mode = 0x%x.\n",
   1933			   ahw->port_config);
   1934		ahw->port_config = config;
   1935		clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1936		return status;
   1937	}
   1938
   1939	/* Wait for Link and IDC Completion AEN */
   1940	do {
   1941		msleep(QLC_83XX_LB_MSLEEP_COUNT);
   1942
   1943		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
   1944			netdev_info(netdev,
   1945				    "Device is resetting, free LB test resources\n");
   1946			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1947			return -EBUSY;
   1948		}
   1949
   1950		if (ahw->extend_lb_time)
   1951			qlcnic_extend_lb_idc_cmpltn_wait(adapter,
   1952							 &max_wait_count);
   1953
   1954		if (loop++ > max_wait_count) {
   1955			netdev_err(netdev, "%s: Did not receive loopback IDC completion AEN\n",
   1956				   __func__);
   1957			clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status);
   1958			return -ETIMEDOUT;
   1959		}
   1960	} while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status));
   1961
   1962	qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0,
   1963				  QLCNIC_MAC_DEL);
   1964	return status;
   1965}
   1966
   1967static void qlcnic_83xx_set_interface_id_ipaddr(struct qlcnic_adapter *adapter,
   1968						u32 *interface_id)
   1969{
   1970	if (qlcnic_sriov_pf_check(adapter)) {
   1971		qlcnic_pf_set_interface_id_ipaddr(adapter, interface_id);
   1972	} else {
   1973		if (!qlcnic_sriov_vf_check(adapter))
   1974			*interface_id = adapter->recv_ctx->context_id << 16;
   1975	}
   1976}
   1977
   1978void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip,
   1979			       int mode)
   1980{
   1981	int err;
   1982	u32 temp = 0, temp_ip;
   1983	struct qlcnic_cmd_args cmd;
   1984
   1985	err = qlcnic_alloc_mbx_args(&cmd, adapter,
   1986				    QLCNIC_CMD_CONFIGURE_IP_ADDR);
   1987	if (err)
   1988		return;
   1989
   1990	qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp);
   1991
   1992	if (mode == QLCNIC_IP_UP)
   1993		cmd.req.arg[1] = 1 | temp;
   1994	else
   1995		cmd.req.arg[1] = 2 | temp;
   1996
   1997	/*
   1998	 * Adapter needs IP address in network byte order.
   1999	 * But hardware mailbox registers go through writel(), hence IP address
   2000	 * gets swapped on big endian architecture.
   2001	 * To negate swapping of writel() on big endian architecture
   2002	 * use swab32(value).
   2003	 */
   2004
   2005	temp_ip = swab32(ntohl(ip));
   2006	memcpy(&cmd.req.arg[2], &temp_ip, sizeof(u32));
   2007	err = qlcnic_issue_cmd(adapter, &cmd);
   2008	if (err != QLCNIC_RCODE_SUCCESS)
   2009		dev_err(&adapter->netdev->dev,
   2010			"could not notify %s IP 0x%x request\n",
   2011			(mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
   2012
   2013	qlcnic_free_mbx_args(&cmd);
   2014}
   2015
   2016int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode)
   2017{
   2018	int err;
   2019	u32 temp, arg1;
   2020	struct qlcnic_cmd_args cmd;
   2021	int lro_bit_mask;
   2022
   2023	lro_bit_mask = (mode ? (BIT_0 | BIT_1 | BIT_2 | BIT_3) : 0);
   2024
   2025	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
   2026		return 0;
   2027
   2028	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO);
   2029	if (err)
   2030		return err;
   2031
   2032	temp = adapter->recv_ctx->context_id << 16;
   2033	arg1 = lro_bit_mask | temp;
   2034	cmd.req.arg[1] = arg1;
   2035
   2036	err = qlcnic_issue_cmd(adapter, &cmd);
   2037	if (err)
   2038		dev_info(&adapter->pdev->dev, "LRO config failed\n");
   2039	qlcnic_free_mbx_args(&cmd);
   2040
   2041	return err;
   2042}
   2043
   2044int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable)
   2045{
   2046	int err;
   2047	u32 word;
   2048	struct qlcnic_cmd_args cmd;
   2049	const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL,
   2050			    0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL,
   2051			    0x255b0ec26d5a56daULL };
   2052
   2053	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS);
   2054	if (err)
   2055		return err;
   2056	/*
   2057	 * RSS request:
   2058	 * bits 3-0: Rsvd
   2059	 *      5-4: hash_type_ipv4
   2060	 *	7-6: hash_type_ipv6
   2061	 *	  8: enable
   2062	 *        9: use indirection table
   2063	 *    16-31: indirection table mask
   2064	 */
   2065	word =  ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) |
   2066		((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) |
   2067		((u32)(enable & 0x1) << 8) |
   2068		((0x7ULL) << 16);
   2069	cmd.req.arg[1] = (adapter->recv_ctx->context_id);
   2070	cmd.req.arg[2] = word;
   2071	memcpy(&cmd.req.arg[4], key, sizeof(key));
   2072
   2073	err = qlcnic_issue_cmd(adapter, &cmd);
   2074
   2075	if (err)
   2076		dev_info(&adapter->pdev->dev, "RSS config failed\n");
   2077	qlcnic_free_mbx_args(&cmd);
   2078
   2079	return err;
   2080
   2081}
   2082
   2083static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
   2084						 u32 *interface_id)
   2085{
   2086	if (qlcnic_sriov_pf_check(adapter)) {
   2087		qlcnic_pf_set_interface_id_macaddr(adapter, interface_id);
   2088	} else {
   2089		if (!qlcnic_sriov_vf_check(adapter))
   2090			*interface_id = adapter->recv_ctx->context_id << 16;
   2091	}
   2092}
   2093
   2094int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
   2095				   u16 vlan_id, u8 op)
   2096{
   2097	struct qlcnic_cmd_args *cmd = NULL;
   2098	struct qlcnic_macvlan_mbx mv;
   2099	u32 *buf, temp = 0;
   2100	int err;
   2101
   2102	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
   2103		return -EIO;
   2104
   2105	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
   2106	if (!cmd)
   2107		return -ENOMEM;
   2108
   2109	err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
   2110	if (err)
   2111		goto out;
   2112
   2113	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
   2114
   2115	if (vlan_id)
   2116		op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
   2117		     QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;
   2118
   2119	cmd->req.arg[1] = op | (1 << 8);
   2120	qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
   2121	cmd->req.arg[1] |= temp;
   2122	mv.vlan = vlan_id;
   2123	mv.mac_addr0 = addr[0];
   2124	mv.mac_addr1 = addr[1];
   2125	mv.mac_addr2 = addr[2];
   2126	mv.mac_addr3 = addr[3];
   2127	mv.mac_addr4 = addr[4];
   2128	mv.mac_addr5 = addr[5];
   2129	buf = &cmd->req.arg[2];
   2130	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
   2131	err = qlcnic_issue_cmd(adapter, cmd);
   2132	if (!err)
   2133		return err;
   2134
   2135	qlcnic_free_mbx_args(cmd);
   2136out:
   2137	kfree(cmd);
   2138	return err;
   2139}
   2140
   2141void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr,
   2142				  u16 vlan_id,
   2143				  struct qlcnic_host_tx_ring *tx_ring)
   2144{
   2145	u8 mac[ETH_ALEN];
   2146	memcpy(&mac, addr, ETH_ALEN);
   2147	qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD);
   2148}
   2149
   2150static void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac,
   2151				      u8 type, struct qlcnic_cmd_args *cmd)
   2152{
   2153	switch (type) {
   2154	case QLCNIC_SET_STATION_MAC:
   2155	case QLCNIC_SET_FAC_DEF_MAC:
   2156		memcpy(&cmd->req.arg[2], mac, sizeof(u32));
   2157		memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16));
   2158		break;
   2159	}
   2160	cmd->req.arg[1] = type;
   2161}
   2162
   2163int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac,
   2164				u8 function)
   2165{
   2166	int err, i;
   2167	struct qlcnic_cmd_args cmd;
   2168	u32 mac_low, mac_high;
   2169
   2170	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
   2171	if (err)
   2172		return err;
   2173
   2174	qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd);
   2175	err = qlcnic_issue_cmd(adapter, &cmd);
   2176
   2177	if (err == QLCNIC_RCODE_SUCCESS) {
   2178		mac_low = cmd.rsp.arg[1];
   2179		mac_high = cmd.rsp.arg[2];
   2180
   2181		for (i = 0; i < 2; i++)
   2182			mac[i] = (u8) (mac_high >> ((1 - i) * 8));
   2183		for (i = 2; i < 6; i++)
   2184			mac[i] = (u8) (mac_low >> ((5 - i) * 8));
   2185	} else {
   2186		dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n",
   2187			err);
   2188		err = -EIO;
   2189	}
   2190	qlcnic_free_mbx_args(&cmd);
   2191	return err;
   2192}
   2193
   2194static int qlcnic_83xx_set_rx_intr_coal(struct qlcnic_adapter *adapter)
   2195{
   2196	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
   2197	struct qlcnic_cmd_args cmd;
   2198	u16 temp;
   2199	int err;
   2200
   2201	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
   2202	if (err)
   2203		return err;
   2204
   2205	temp = adapter->recv_ctx->context_id;
   2206	cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16;
   2207	temp = coal->rx_time_us;
   2208	cmd.req.arg[2] = coal->rx_packets | temp << 16;
   2209	cmd.req.arg[3] = coal->flag;
   2210
   2211	err = qlcnic_issue_cmd(adapter, &cmd);
   2212	if (err != QLCNIC_RCODE_SUCCESS)
   2213		netdev_err(adapter->netdev,
   2214			   "failed to set interrupt coalescing parameters\n");
   2215
   2216	qlcnic_free_mbx_args(&cmd);
   2217
   2218	return err;
   2219}
   2220
   2221static int qlcnic_83xx_set_tx_intr_coal(struct qlcnic_adapter *adapter)
   2222{
   2223	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
   2224	struct qlcnic_cmd_args cmd;
   2225	u16 temp;
   2226	int err;
   2227
   2228	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL);
   2229	if (err)
   2230		return err;
   2231
   2232	temp = adapter->tx_ring->ctx_id;
   2233	cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_TX | temp << 16;
   2234	temp = coal->tx_time_us;
   2235	cmd.req.arg[2] = coal->tx_packets | temp << 16;
   2236	cmd.req.arg[3] = coal->flag;
   2237
   2238	err = qlcnic_issue_cmd(adapter, &cmd);
   2239	if (err != QLCNIC_RCODE_SUCCESS)
   2240		netdev_err(adapter->netdev,
   2241			   "failed to set interrupt coalescing  parameters\n");
   2242
   2243	qlcnic_free_mbx_args(&cmd);
   2244
   2245	return err;
   2246}
   2247
   2248int qlcnic_83xx_set_rx_tx_intr_coal(struct qlcnic_adapter *adapter)
   2249{
   2250	int err = 0;
   2251
   2252	err = qlcnic_83xx_set_rx_intr_coal(adapter);
   2253	if (err)
   2254		netdev_err(adapter->netdev,
   2255			   "failed to set Rx coalescing parameters\n");
   2256
   2257	err = qlcnic_83xx_set_tx_intr_coal(adapter);
   2258	if (err)
   2259		netdev_err(adapter->netdev,
   2260			   "failed to set Tx coalescing parameters\n");
   2261
   2262	return err;
   2263}
   2264
   2265int qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter,
   2266				 struct ethtool_coalesce *ethcoal)
   2267{
   2268	struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal;
   2269	u32 rx_coalesce_usecs, rx_max_frames;
   2270	u32 tx_coalesce_usecs, tx_max_frames;
   2271	int err;
   2272
   2273	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
   2274		return -EIO;
   2275
   2276	tx_coalesce_usecs = ethcoal->tx_coalesce_usecs;
   2277	tx_max_frames = ethcoal->tx_max_coalesced_frames;
   2278	rx_coalesce_usecs = ethcoal->rx_coalesce_usecs;
   2279	rx_max_frames = ethcoal->rx_max_coalesced_frames;
   2280	coal->flag = QLCNIC_INTR_DEFAULT;
   2281
   2282	if ((coal->rx_time_us == rx_coalesce_usecs) &&
   2283	    (coal->rx_packets == rx_max_frames)) {
   2284		coal->type = QLCNIC_INTR_COAL_TYPE_TX;
   2285		coal->tx_time_us = tx_coalesce_usecs;
   2286		coal->tx_packets = tx_max_frames;
   2287	} else if ((coal->tx_time_us == tx_coalesce_usecs) &&
   2288		   (coal->tx_packets == tx_max_frames)) {
   2289		coal->type = QLCNIC_INTR_COAL_TYPE_RX;
   2290		coal->rx_time_us = rx_coalesce_usecs;
   2291		coal->rx_packets = rx_max_frames;
   2292	} else {
   2293		coal->type = QLCNIC_INTR_COAL_TYPE_RX_TX;
   2294		coal->rx_time_us = rx_coalesce_usecs;
   2295		coal->rx_packets = rx_max_frames;
   2296		coal->tx_time_us = tx_coalesce_usecs;
   2297		coal->tx_packets = tx_max_frames;
   2298	}
   2299
   2300	switch (coal->type) {
   2301	case QLCNIC_INTR_COAL_TYPE_RX:
   2302		err = qlcnic_83xx_set_rx_intr_coal(adapter);
   2303		break;
   2304	case QLCNIC_INTR_COAL_TYPE_TX:
   2305		err = qlcnic_83xx_set_tx_intr_coal(adapter);
   2306		break;
   2307	case QLCNIC_INTR_COAL_TYPE_RX_TX:
   2308		err = qlcnic_83xx_set_rx_tx_intr_coal(adapter);
   2309		break;
   2310	default:
   2311		err = -EINVAL;
   2312		netdev_err(adapter->netdev,
   2313			   "Invalid Interrupt coalescing type\n");
   2314		break;
   2315	}
   2316
   2317	return err;
   2318}
   2319
   2320static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
   2321					u32 data[])
   2322{
   2323	struct qlcnic_hardware_context *ahw = adapter->ahw;
   2324	u8 link_status, duplex;
   2325	/* link speed */
   2326	link_status = LSB(data[3]) & 1;
   2327	if (link_status) {
   2328		ahw->link_speed = MSW(data[2]);
   2329		duplex = LSB(MSW(data[3]));
   2330		if (duplex)
   2331			ahw->link_duplex = DUPLEX_FULL;
   2332		else
   2333			ahw->link_duplex = DUPLEX_HALF;
   2334	} else {
   2335		ahw->link_speed = SPEED_UNKNOWN;
   2336		ahw->link_duplex = DUPLEX_UNKNOWN;
   2337	}
   2338
   2339	ahw->link_autoneg = MSB(MSW(data[3]));
   2340	ahw->module_type = MSB(LSW(data[3]));
   2341	ahw->has_link_events = 1;
   2342	ahw->lb_mode = data[4] & QLCNIC_LB_MODE_MASK;
   2343	qlcnic_advert_link_change(adapter, link_status);
   2344}
   2345
   2346static irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
   2347{
   2348	u32 mask, resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
   2349	struct qlcnic_adapter *adapter = data;
   2350	struct qlcnic_mailbox *mbx;
   2351	unsigned long flags;
   2352
   2353	mbx = adapter->ahw->mailbox;
   2354	spin_lock_irqsave(&mbx->aen_lock, flags);
   2355	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
   2356	if (!(resp & QLCNIC_SET_OWNER))
   2357		goto out;
   2358
   2359	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
   2360	if (event &  QLCNIC_MBX_ASYNC_EVENT) {
   2361		__qlcnic_83xx_process_aen(adapter);
   2362	} else {
   2363		if (mbx->rsp_status != rsp_status)
   2364			qlcnic_83xx_notify_mbx_response(mbx);
   2365		else
   2366			adapter->stats.mbx_spurious_intr++;
   2367	}
   2368
   2369out:
   2370	mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
   2371	writel(0, adapter->ahw->pci_base0 + mask);
   2372	spin_unlock_irqrestore(&mbx->aen_lock, flags);
   2373	return IRQ_HANDLED;
   2374}
   2375
   2376int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter,
   2377			     struct qlcnic_info *nic)
   2378{
   2379	int i, err = -EIO;
   2380	struct qlcnic_cmd_args cmd;
   2381
   2382	if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
   2383		dev_err(&adapter->pdev->dev,
   2384			"%s: Error, invoked by non management func\n",
   2385			__func__);
   2386		return err;
   2387	}
   2388
   2389	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
   2390	if (err)
   2391		return err;
   2392
   2393	cmd.req.arg[1] = (nic->pci_func << 16);
   2394	cmd.req.arg[2] = 0x1 << 16;
   2395	cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16);
   2396	cmd.req.arg[4] = nic->capabilities;
   2397	cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16);
   2398	cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16);
   2399	cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16);
   2400	for (i = 8; i < 32; i++)
   2401		cmd.req.arg[i] = 0;
   2402
   2403	err = qlcnic_issue_cmd(adapter, &cmd);
   2404
   2405	if (err != QLCNIC_RCODE_SUCCESS) {
   2406		dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n",
   2407			err);
   2408		err = -EIO;
   2409	}
   2410
   2411	qlcnic_free_mbx_args(&cmd);
   2412
   2413	return err;
   2414}
   2415
   2416int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter,
   2417			     struct qlcnic_info *npar_info, u8 func_id)
   2418{
   2419	int err;
   2420	u32 temp;
   2421	u8 op = 0;
   2422	struct qlcnic_cmd_args cmd;
   2423	struct qlcnic_hardware_context *ahw = adapter->ahw;
   2424
   2425	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
   2426	if (err)
   2427		return err;
   2428
   2429	if (func_id != ahw->pci_func) {
   2430		temp = func_id << 16;
   2431		cmd.req.arg[1] = op | BIT_31 | temp;
   2432	} else {
   2433		cmd.req.arg[1] = ahw->pci_func << 16;
   2434	}
   2435	err = qlcnic_issue_cmd(adapter, &cmd);
   2436	if (err) {
   2437		dev_info(&adapter->pdev->dev,
   2438			 "Failed to get nic info %d\n", err);
   2439		goto out;
   2440	}
   2441
   2442	npar_info->op_type = cmd.rsp.arg[1];
   2443	npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF;
   2444	npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16;
   2445	npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF;
   2446	npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16;
   2447	npar_info->capabilities = cmd.rsp.arg[4];
   2448	npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF;
   2449	npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16;
   2450	npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF;
   2451	npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16;
   2452	npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF;
   2453	npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16;
   2454	if (cmd.rsp.arg[8] & 0x1)
   2455		npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1;
   2456	if (cmd.rsp.arg[8] & 0x10000) {
   2457		temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
   2458		npar_info->max_linkspeed_reg_offset = temp;
   2459	}
   2460
   2461	memcpy(ahw->extra_capability, &cmd.rsp.arg[16],
   2462	       sizeof(ahw->extra_capability));
   2463
   2464out:
   2465	qlcnic_free_mbx_args(&cmd);
   2466	return err;
   2467}
   2468
   2469int qlcnic_get_pci_func_type(struct qlcnic_adapter *adapter, u16 type,
   2470			     u16 *nic, u16 *fcoe, u16 *iscsi)
   2471{
   2472	struct device *dev = &adapter->pdev->dev;
   2473	int err = 0;
   2474
   2475	switch (type) {
   2476	case QLCNIC_TYPE_NIC:
   2477		(*nic)++;
   2478		break;
   2479	case QLCNIC_TYPE_FCOE:
   2480		(*fcoe)++;
   2481		break;
   2482	case QLCNIC_TYPE_ISCSI:
   2483		(*iscsi)++;
   2484		break;
   2485	default:
   2486		dev_err(dev, "%s: Unknown PCI type[%x]\n",
   2487			__func__, type);
   2488		err = -EIO;
   2489	}
   2490
   2491	return err;
   2492}
   2493
   2494int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,
   2495			     struct qlcnic_pci_info *pci_info)
   2496{
   2497	struct qlcnic_hardware_context *ahw = adapter->ahw;
   2498	struct device *dev = &adapter->pdev->dev;
   2499	u16 nic = 0, fcoe = 0, iscsi = 0;
   2500	struct qlcnic_cmd_args cmd;
   2501	int i, err = 0, j = 0;
   2502	u32 temp;
   2503
   2504	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
   2505	if (err)
   2506		return err;
   2507
   2508	err = qlcnic_issue_cmd(adapter, &cmd);
   2509
   2510	ahw->total_nic_func = 0;
   2511	if (err == QLCNIC_RCODE_SUCCESS) {
   2512		ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF;
   2513		for (i = 2, j = 0; j < ahw->max_vnic_func; j++, pci_info++) {
   2514			pci_info->id = cmd.rsp.arg[i] & 0xFFFF;
   2515			pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
   2516			i++;
   2517			if (!pci_info->active) {
   2518				i += QLC_SKIP_INACTIVE_PCI_REGS;
   2519				continue;
   2520			}
   2521			pci_info->type = cmd.rsp.arg[i] & 0xFFFF;
   2522			err = qlcnic_get_pci_func_type(adapter, pci_info->type,
   2523						       &nic, &fcoe, &iscsi);
   2524			temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
   2525			pci_info->default_port = temp;
   2526			i++;
   2527			pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF;
   2528			temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16;
   2529			pci_info->tx_max_bw = temp;
   2530			i = i + 2;
   2531			memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2);
   2532			i++;
   2533			memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2);
   2534			i = i + 3;
   2535		}
   2536	} else {
   2537		dev_err(dev, "Failed to get PCI Info, error = %d\n", err);
   2538		err = -EIO;
   2539	}
   2540
   2541	ahw->total_nic_func = nic;
   2542	ahw->total_pci_func = nic + fcoe + iscsi;
   2543	if (ahw->total_nic_func == 0 || ahw->total_pci_func == 0) {
   2544		dev_err(dev, "%s: Invalid function count: total nic func[%x], total pci func[%x]\n",
   2545			__func__, ahw->total_nic_func, ahw->total_pci_func);
   2546		err = -EIO;
   2547	}
   2548	qlcnic_free_mbx_args(&cmd);
   2549
   2550	return err;
   2551}
   2552
   2553int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)
   2554{
   2555	int i, index, err;
   2556	u8 max_ints;
   2557	u32 val, temp, type;
   2558	struct qlcnic_cmd_args cmd;
   2559
   2560	max_ints = adapter->ahw->num_msix - 1;
   2561	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT);
   2562	if (err)
   2563		return err;
   2564
   2565	cmd.req.arg[1] = max_ints;
   2566
   2567	if (qlcnic_sriov_vf_check(adapter))
   2568		cmd.req.arg[1] |= (adapter->ahw->pci_func << 8) | BIT_16;
   2569
   2570	for (i = 0, index = 2; i < max_ints; i++) {
   2571		type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
   2572		val = type | (adapter->ahw->intr_tbl[i].type << 4);
   2573		if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
   2574			val |= (adapter->ahw->intr_tbl[i].id << 16);
   2575		cmd.req.arg[index++] = val;
   2576	}
   2577	err = qlcnic_issue_cmd(adapter, &cmd);
   2578	if (err) {
   2579		dev_err(&adapter->pdev->dev,
   2580			"Failed to configure interrupts 0x%x\n", err);
   2581		goto out;
   2582	}
   2583
   2584	max_ints = cmd.rsp.arg[1];
   2585	for (i = 0, index = 2; i < max_ints; i++, index += 2) {
   2586		val = cmd.rsp.arg[index];
   2587		if (LSB(val)) {
   2588			dev_info(&adapter->pdev->dev,
   2589				 "Can't configure interrupt %d\n",
   2590				 adapter->ahw->intr_tbl[i].id);
   2591			continue;
   2592		}
   2593		if (op_type) {
   2594			adapter->ahw->intr_tbl[i].id = MSW(val);
   2595			adapter->ahw->intr_tbl[i].enabled = 1;
   2596			temp = cmd.rsp.arg[index + 1];
   2597			adapter->ahw->intr_tbl[i].src = temp;
   2598		} else {
   2599			adapter->ahw->intr_tbl[i].id = i;
   2600			adapter->ahw->intr_tbl[i].enabled = 0;
   2601			adapter->ahw->intr_tbl[i].src = 0;
   2602		}
   2603	}
   2604out:
   2605	qlcnic_free_mbx_args(&cmd);
   2606	return err;
   2607}
   2608
   2609int qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter)
   2610{
   2611	int id, timeout = 0;
   2612	u32 status = 0;
   2613
   2614	while (status == 0) {
   2615		status = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK);
   2616		if (status)
   2617			break;
   2618
   2619		if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) {
   2620			id = QLC_SHARED_REG_RD32(adapter,
   2621						 QLCNIC_FLASH_LOCK_OWNER);
   2622			dev_err(&adapter->pdev->dev,
   2623				"%s: failed, lock held by %d\n", __func__, id);
   2624			return -EIO;
   2625		}
   2626		usleep_range(1000, 2000);
   2627	}
   2628
   2629	QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum);
   2630	return 0;
   2631}
   2632
   2633void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter)
   2634{
   2635	QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK);
   2636	QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF);
   2637}
   2638
   2639int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
   2640				      u32 flash_addr, u8 *p_data,
   2641				      int count)
   2642{
   2643	u32 word, range, flash_offset, addr = flash_addr, ret;
   2644	ulong indirect_add, direct_window;
   2645	int i, err = 0;
   2646
   2647	flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
   2648	if (addr & 0x3) {
   2649		dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
   2650		return -EIO;
   2651	}
   2652
   2653	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
   2654				     (addr & 0xFFFF0000));
   2655
   2656	range = flash_offset + (count * sizeof(u32));
   2657	/* Check if data is spread across multiple sectors */
   2658	if (range > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
   2659
   2660		/* Multi sector read */
   2661		for (i = 0; i < count; i++) {
   2662			indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
   2663			ret = QLCRD32(adapter, indirect_add, &err);
   2664			if (err == -EIO)
   2665				return err;
   2666
   2667			word = ret;
   2668			*(u32 *)p_data  = word;
   2669			p_data = p_data + 4;
   2670			addr = addr + 4;
   2671			flash_offset = flash_offset + 4;
   2672
   2673			if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) {
   2674				direct_window = QLC_83XX_FLASH_DIRECT_WINDOW;
   2675				/* This write is needed once for each sector */
   2676				qlcnic_83xx_wrt_reg_indirect(adapter,
   2677							     direct_window,
   2678							     (addr));
   2679				flash_offset = 0;
   2680			}
   2681		}
   2682	} else {
   2683		/* Single sector read */
   2684		for (i = 0; i < count; i++) {
   2685			indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
   2686			ret = QLCRD32(adapter, indirect_add, &err);
   2687			if (err == -EIO)
   2688				return err;
   2689
   2690			word = ret;
   2691			*(u32 *)p_data  = word;
   2692			p_data = p_data + 4;
   2693			addr = addr + 4;
   2694		}
   2695	}
   2696
   2697	return 0;
   2698}
   2699
   2700static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
   2701{
   2702	u32 status;
   2703	int retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
   2704	int err = 0;
   2705
   2706	do {
   2707		status = QLCRD32(adapter, QLC_83XX_FLASH_STATUS, &err);
   2708		if (err == -EIO)
   2709			return err;
   2710
   2711		if ((status & QLC_83XX_FLASH_STATUS_READY) ==
   2712		    QLC_83XX_FLASH_STATUS_READY)
   2713			break;
   2714
   2715		usleep_range(1000, 1100);
   2716	} while (--retries);
   2717
   2718	if (!retries)
   2719		return -EIO;
   2720
   2721	return 0;
   2722}
   2723
   2724int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *adapter)
   2725{
   2726	int ret;
   2727	u32 cmd;
   2728	cmd = adapter->ahw->fdt.write_statusreg_cmd;
   2729	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2730				     (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | cmd));
   2731	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
   2732				     adapter->ahw->fdt.write_enable_bits);
   2733	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2734				     QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
   2735	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2736	if (ret)
   2737		return -EIO;
   2738
   2739	return 0;
   2740}
   2741
   2742int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)
   2743{
   2744	int ret;
   2745
   2746	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2747				     (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG |
   2748				     adapter->ahw->fdt.write_statusreg_cmd));
   2749	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
   2750				     adapter->ahw->fdt.write_disable_bits);
   2751	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2752				     QLC_83XX_FLASH_SECOND_ERASE_MS_VAL);
   2753	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2754	if (ret)
   2755		return -EIO;
   2756
   2757	return 0;
   2758}
   2759
   2760int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
   2761{
   2762	int ret, err = 0;
   2763	u32 mfg_id;
   2764
   2765	if (qlcnic_83xx_lock_flash(adapter))
   2766		return -EIO;
   2767
   2768	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2769				     QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL);
   2770	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2771				     QLC_83XX_FLASH_READ_CTRL);
   2772	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2773	if (ret) {
   2774		qlcnic_83xx_unlock_flash(adapter);
   2775		return -EIO;
   2776	}
   2777
   2778	mfg_id = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
   2779	if (err == -EIO) {
   2780		qlcnic_83xx_unlock_flash(adapter);
   2781		return err;
   2782	}
   2783
   2784	adapter->flash_mfg_id = (mfg_id & 0xFF);
   2785	qlcnic_83xx_unlock_flash(adapter);
   2786
   2787	return 0;
   2788}
   2789
   2790int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
   2791{
   2792	int count, fdt_size, ret = 0;
   2793
   2794	fdt_size = sizeof(struct qlcnic_fdt);
   2795	count = fdt_size / sizeof(u32);
   2796
   2797	if (qlcnic_83xx_lock_flash(adapter))
   2798		return -EIO;
   2799
   2800	memset(&adapter->ahw->fdt, 0, fdt_size);
   2801	ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
   2802						(u8 *)&adapter->ahw->fdt,
   2803						count);
   2804	qlcnic_swap32_buffer((u32 *)&adapter->ahw->fdt, count);
   2805	qlcnic_83xx_unlock_flash(adapter);
   2806	return ret;
   2807}
   2808
   2809int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
   2810				   u32 sector_start_addr)
   2811{
   2812	u32 reversed_addr, addr1, addr2, cmd;
   2813	int ret = -EIO;
   2814
   2815	if (qlcnic_83xx_lock_flash(adapter) != 0)
   2816		return -EIO;
   2817
   2818	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
   2819		ret = qlcnic_83xx_enable_flash_write(adapter);
   2820		if (ret) {
   2821			qlcnic_83xx_unlock_flash(adapter);
   2822			dev_err(&adapter->pdev->dev,
   2823				"%s failed at %d\n",
   2824				__func__, __LINE__);
   2825			return ret;
   2826		}
   2827	}
   2828
   2829	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2830	if (ret) {
   2831		qlcnic_83xx_unlock_flash(adapter);
   2832		dev_err(&adapter->pdev->dev,
   2833			"%s: failed at %d\n", __func__, __LINE__);
   2834		return -EIO;
   2835	}
   2836
   2837	addr1 = (sector_start_addr & 0xFF) << 16;
   2838	addr2 = (sector_start_addr & 0xFF0000) >> 16;
   2839	reversed_addr = addr1 | addr2 | (sector_start_addr & 0xFF00);
   2840
   2841	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
   2842				     reversed_addr);
   2843	cmd = QLC_83XX_FLASH_FDT_ERASE_DEF_SIG | adapter->ahw->fdt.erase_cmd;
   2844	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id)
   2845		qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, cmd);
   2846	else
   2847		qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2848					     QLC_83XX_FLASH_OEM_ERASE_SIG);
   2849	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2850				     QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
   2851
   2852	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2853	if (ret) {
   2854		qlcnic_83xx_unlock_flash(adapter);
   2855		dev_err(&adapter->pdev->dev,
   2856			"%s: failed at %d\n", __func__, __LINE__);
   2857		return -EIO;
   2858	}
   2859
   2860	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) {
   2861		ret = qlcnic_83xx_disable_flash_write(adapter);
   2862		if (ret) {
   2863			qlcnic_83xx_unlock_flash(adapter);
   2864			dev_err(&adapter->pdev->dev,
   2865				"%s: failed at %d\n", __func__, __LINE__);
   2866			return ret;
   2867		}
   2868	}
   2869
   2870	qlcnic_83xx_unlock_flash(adapter);
   2871
   2872	return 0;
   2873}
   2874
   2875int qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr,
   2876			      u32 *p_data)
   2877{
   2878	int ret = -EIO;
   2879	u32 addr1 = 0x00800000 | (addr >> 2);
   2880
   2881	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, addr1);
   2882	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data);
   2883	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2884				     QLC_83XX_FLASH_LAST_ERASE_MS_VAL);
   2885	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2886	if (ret) {
   2887		dev_err(&adapter->pdev->dev,
   2888			"%s: failed at %d\n", __func__, __LINE__);
   2889		return -EIO;
   2890	}
   2891
   2892	return 0;
   2893}
   2894
   2895int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
   2896				 u32 *p_data, int count)
   2897{
   2898	u32 temp;
   2899	int ret = -EIO, err = 0;
   2900
   2901	if ((count < QLC_83XX_FLASH_WRITE_MIN) ||
   2902	    (count > QLC_83XX_FLASH_WRITE_MAX)) {
   2903		dev_err(&adapter->pdev->dev,
   2904			"%s: Invalid word count\n", __func__);
   2905		return -EIO;
   2906	}
   2907
   2908	temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
   2909	if (err == -EIO)
   2910		return err;
   2911
   2912	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL,
   2913				     (temp | QLC_83XX_FLASH_SPI_CTRL));
   2914	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2915				     QLC_83XX_FLASH_ADDR_TEMP_VAL);
   2916
   2917	/* First DWORD write */
   2918	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
   2919	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2920				     QLC_83XX_FLASH_FIRST_MS_PATTERN);
   2921	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2922	if (ret) {
   2923		dev_err(&adapter->pdev->dev,
   2924			"%s: failed at %d\n", __func__, __LINE__);
   2925		return -EIO;
   2926	}
   2927
   2928	count--;
   2929	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2930				     QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL);
   2931	/* Second to N-1 DWORD writes */
   2932	while (count != 1) {
   2933		qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
   2934					     *p_data++);
   2935		qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2936					     QLC_83XX_FLASH_SECOND_MS_PATTERN);
   2937		ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2938		if (ret) {
   2939			dev_err(&adapter->pdev->dev,
   2940				"%s: failed at %d\n", __func__, __LINE__);
   2941			return -EIO;
   2942		}
   2943		count--;
   2944	}
   2945
   2946	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   2947				     QLC_83XX_FLASH_ADDR_TEMP_VAL |
   2948				     (addr >> 2));
   2949	/* Last DWORD write */
   2950	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++);
   2951	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   2952				     QLC_83XX_FLASH_LAST_MS_PATTERN);
   2953	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   2954	if (ret) {
   2955		dev_err(&adapter->pdev->dev,
   2956			"%s: failed at %d\n", __func__, __LINE__);
   2957		return -EIO;
   2958	}
   2959
   2960	ret = QLCRD32(adapter, QLC_83XX_FLASH_SPI_STATUS, &err);
   2961	if (err == -EIO)
   2962		return err;
   2963
   2964	if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) {
   2965		dev_err(&adapter->pdev->dev, "%s: failed at %d\n",
   2966			__func__, __LINE__);
   2967		/* Operation failed, clear error bit */
   2968		temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
   2969		if (err == -EIO)
   2970			return err;
   2971
   2972		qlcnic_83xx_wrt_reg_indirect(adapter,
   2973					     QLC_83XX_FLASH_SPI_CONTROL,
   2974					     (temp | QLC_83XX_FLASH_SPI_CTRL));
   2975	}
   2976
   2977	return 0;
   2978}
   2979
   2980static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
   2981{
   2982	u32 val, id;
   2983
   2984	val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
   2985
   2986	/* Check if recovery need to be performed by the calling function */
   2987	if ((val & QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK) == 0) {
   2988		val = val & ~0x3F;
   2989		val = val | ((adapter->portnum << 2) |
   2990			     QLC_83XX_NEED_DRV_LOCK_RECOVERY);
   2991		QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
   2992		dev_info(&adapter->pdev->dev,
   2993			 "%s: lock recovery initiated\n", __func__);
   2994		msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
   2995		val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
   2996		id = ((val >> 2) & 0xF);
   2997		if (id == adapter->portnum) {
   2998			val = val & ~QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK;
   2999			val = val | QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS;
   3000			QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
   3001			/* Force release the lock */
   3002			QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
   3003			/* Clear recovery bits */
   3004			val = val & ~0x3F;
   3005			QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
   3006			dev_info(&adapter->pdev->dev,
   3007				 "%s: lock recovery completed\n", __func__);
   3008		} else {
   3009			dev_info(&adapter->pdev->dev,
   3010				 "%s: func %d to resume lock recovery process\n",
   3011				 __func__, id);
   3012		}
   3013	} else {
   3014		dev_info(&adapter->pdev->dev,
   3015			 "%s: lock recovery initiated by other functions\n",
   3016			 __func__);
   3017	}
   3018}
   3019
   3020int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
   3021{
   3022	u32 lock_alive_counter, val, id, i = 0, status = 0, temp = 0;
   3023	int max_attempt = 0;
   3024
   3025	while (status == 0) {
   3026		status = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK);
   3027		if (status)
   3028			break;
   3029
   3030		msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
   3031		i++;
   3032
   3033		if (i == 1)
   3034			temp = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
   3035
   3036		if (i == QLC_83XX_DRV_LOCK_WAIT_COUNTER) {
   3037			val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
   3038			if (val == temp) {
   3039				id = val & 0xFF;
   3040				dev_info(&adapter->pdev->dev,
   3041					 "%s: lock to be recovered from %d\n",
   3042					 __func__, id);
   3043				qlcnic_83xx_recover_driver_lock(adapter);
   3044				i = 0;
   3045				max_attempt++;
   3046			} else {
   3047				dev_err(&adapter->pdev->dev,
   3048					"%s: failed to get lock\n", __func__);
   3049				return -EIO;
   3050			}
   3051		}
   3052
   3053		/* Force exit from while loop after few attempts */
   3054		if (max_attempt == QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT) {
   3055			dev_err(&adapter->pdev->dev,
   3056				"%s: failed to get lock\n", __func__);
   3057			return -EIO;
   3058		}
   3059	}
   3060
   3061	val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
   3062	lock_alive_counter = val >> 8;
   3063	lock_alive_counter++;
   3064	val = lock_alive_counter << 8 | adapter->portnum;
   3065	QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
   3066
   3067	return 0;
   3068}
   3069
   3070void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter)
   3071{
   3072	u32 val, lock_alive_counter, id;
   3073
   3074	val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID);
   3075	id = val & 0xFF;
   3076	lock_alive_counter = val >> 8;
   3077
   3078	if (id != adapter->portnum)
   3079		dev_err(&adapter->pdev->dev,
   3080			"%s:Warning func %d is unlocking lock owned by %d\n",
   3081			__func__, adapter->portnum, id);
   3082
   3083	val = (lock_alive_counter << 8) | 0xFF;
   3084	QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val);
   3085	QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK);
   3086}
   3087
   3088int qlcnic_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
   3089				u32 *data, u32 count)
   3090{
   3091	int i, j, ret = 0;
   3092	u32 temp;
   3093
   3094	/* Check alignment */
   3095	if (addr & 0xF)
   3096		return -EIO;
   3097
   3098	mutex_lock(&adapter->ahw->mem_lock);
   3099	qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_HI, 0);
   3100
   3101	for (i = 0; i < count; i++, addr += 16) {
   3102		if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET,
   3103				     QLCNIC_ADDR_QDR_NET_MAX)) ||
   3104		      (ADDR_IN_RANGE(addr, QLCNIC_ADDR_DDR_NET,
   3105				     QLCNIC_ADDR_DDR_NET_MAX)))) {
   3106			mutex_unlock(&adapter->ahw->mem_lock);
   3107			return -EIO;
   3108		}
   3109
   3110		qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_LO, addr);
   3111		qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_LO, *data++);
   3112		qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_HI, *data++);
   3113		qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_ULO, *data++);
   3114		qlcnic_ind_wr(adapter, QLCNIC_MS_WRTDATA_UHI, *data++);
   3115		qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_WRITE_ENABLE);
   3116		qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_WRITE_START);
   3117
   3118		for (j = 0; j < MAX_CTL_CHECK; j++) {
   3119			temp = qlcnic_ind_rd(adapter, QLCNIC_MS_CTRL);
   3120
   3121			if ((temp & TA_CTL_BUSY) == 0)
   3122				break;
   3123		}
   3124
   3125		/* Status check failure */
   3126		if (j >= MAX_CTL_CHECK) {
   3127			printk_ratelimited(KERN_WARNING
   3128					   "MS memory write failed\n");
   3129			mutex_unlock(&adapter->ahw->mem_lock);
   3130			return -EIO;
   3131		}
   3132	}
   3133
   3134	mutex_unlock(&adapter->ahw->mem_lock);
   3135
   3136	return ret;
   3137}
   3138
   3139int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
   3140			     u8 *p_data, int count)
   3141{
   3142	u32 word, addr = flash_addr, ret;
   3143	ulong  indirect_addr;
   3144	int i, err = 0;
   3145
   3146	if (qlcnic_83xx_lock_flash(adapter) != 0)
   3147		return -EIO;
   3148
   3149	if (addr & 0x3) {
   3150		dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
   3151		qlcnic_83xx_unlock_flash(adapter);
   3152		return -EIO;
   3153	}
   3154
   3155	for (i = 0; i < count; i++) {
   3156		if (qlcnic_83xx_wrt_reg_indirect(adapter,
   3157						 QLC_83XX_FLASH_DIRECT_WINDOW,
   3158						 (addr))) {
   3159			qlcnic_83xx_unlock_flash(adapter);
   3160			return -EIO;
   3161		}
   3162
   3163		indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
   3164		ret = QLCRD32(adapter, indirect_addr, &err);
   3165		if (err == -EIO) {
   3166			qlcnic_83xx_unlock_flash(adapter);
   3167			return err;
   3168		}
   3169
   3170		word = ret;
   3171		*(u32 *)p_data  = word;
   3172		p_data = p_data + 4;
   3173		addr = addr + 4;
   3174	}
   3175
   3176	qlcnic_83xx_unlock_flash(adapter);
   3177
   3178	return 0;
   3179}
   3180
   3181void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter)
   3182{
   3183	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3184	struct qlcnic_cmd_args cmd;
   3185	u32 config;
   3186	int err;
   3187
   3188	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
   3189	if (err)
   3190		return;
   3191
   3192	err = qlcnic_issue_cmd(adapter, &cmd);
   3193	if (err) {
   3194		dev_info(&adapter->pdev->dev,
   3195			 "Get Link Status Command failed: 0x%x\n", err);
   3196		goto out;
   3197	} else {
   3198		config = cmd.rsp.arg[3];
   3199
   3200		switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
   3201		case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
   3202		case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
   3203		case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
   3204		case QLC_83XX_MODULE_TP_1000BASE_T:
   3205			ahw->port_type = QLCNIC_GBE;
   3206			break;
   3207		default:
   3208			ahw->port_type = QLCNIC_XGBE;
   3209		}
   3210	}
   3211out:
   3212	qlcnic_free_mbx_args(&cmd);
   3213}
   3214
   3215int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
   3216{
   3217	u8 pci_func;
   3218	int err;
   3219	u32 config = 0, state;
   3220	struct qlcnic_cmd_args cmd;
   3221	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3222
   3223	if (qlcnic_sriov_vf_check(adapter))
   3224		pci_func = adapter->portnum;
   3225	else
   3226		pci_func = ahw->pci_func;
   3227
   3228	state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(pci_func));
   3229	if (!QLC_83xx_FUNC_VAL(state, pci_func)) {
   3230		dev_info(&adapter->pdev->dev, "link state down\n");
   3231		return config;
   3232	}
   3233
   3234	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
   3235	if (err)
   3236		return err;
   3237
   3238	err = qlcnic_issue_cmd(adapter, &cmd);
   3239	if (err) {
   3240		dev_info(&adapter->pdev->dev,
   3241			 "Get Link Status Command failed: 0x%x\n", err);
   3242		goto out;
   3243	} else {
   3244		config = cmd.rsp.arg[1];
   3245		switch (QLC_83XX_CURRENT_LINK_SPEED(config)) {
   3246		case QLC_83XX_10M_LINK:
   3247			ahw->link_speed = SPEED_10;
   3248			break;
   3249		case QLC_83XX_100M_LINK:
   3250			ahw->link_speed = SPEED_100;
   3251			break;
   3252		case QLC_83XX_1G_LINK:
   3253			ahw->link_speed = SPEED_1000;
   3254			break;
   3255		case QLC_83XX_10G_LINK:
   3256			ahw->link_speed = SPEED_10000;
   3257			break;
   3258		default:
   3259			ahw->link_speed = 0;
   3260			break;
   3261		}
   3262		config = cmd.rsp.arg[3];
   3263		switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
   3264		case QLC_83XX_MODULE_FIBRE_10GBASE_LRM:
   3265		case QLC_83XX_MODULE_FIBRE_10GBASE_LR:
   3266		case QLC_83XX_MODULE_FIBRE_10GBASE_SR:
   3267			ahw->supported_type = PORT_FIBRE;
   3268			ahw->port_type = QLCNIC_XGBE;
   3269			break;
   3270		case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
   3271		case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
   3272		case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
   3273			ahw->supported_type = PORT_FIBRE;
   3274			ahw->port_type = QLCNIC_GBE;
   3275			break;
   3276		case QLC_83XX_MODULE_TP_1000BASE_T:
   3277			ahw->supported_type = PORT_TP;
   3278			ahw->port_type = QLCNIC_GBE;
   3279			break;
   3280		case QLC_83XX_MODULE_DA_10GE_PASSIVE_CP:
   3281		case QLC_83XX_MODULE_DA_10GE_ACTIVE_CP:
   3282		case QLC_83XX_MODULE_DA_10GE_LEGACY_CP:
   3283		case QLC_83XX_MODULE_DA_1GE_PASSIVE_CP:
   3284			ahw->supported_type = PORT_DA;
   3285			ahw->port_type = QLCNIC_XGBE;
   3286			break;
   3287		default:
   3288			ahw->supported_type = PORT_OTHER;
   3289			ahw->port_type = QLCNIC_XGBE;
   3290		}
   3291		if (config & 1)
   3292			err = 1;
   3293	}
   3294out:
   3295	qlcnic_free_mbx_args(&cmd);
   3296	return config;
   3297}
   3298
   3299int qlcnic_83xx_get_link_ksettings(struct qlcnic_adapter *adapter,
   3300				   struct ethtool_link_ksettings *ecmd)
   3301{
   3302	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3303	u32 config = 0;
   3304	int status = 0;
   3305	u32 supported, advertising;
   3306
   3307	if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
   3308		/* Get port configuration info */
   3309		status = qlcnic_83xx_get_port_info(adapter);
   3310		/* Get Link Status related info */
   3311		config = qlcnic_83xx_test_link(adapter);
   3312		ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
   3313	}
   3314
   3315	/* hard code until there is a way to get it from flash */
   3316	ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
   3317
   3318	if (netif_running(adapter->netdev) && ahw->has_link_events) {
   3319		ecmd->base.speed = ahw->link_speed;
   3320		ecmd->base.duplex = ahw->link_duplex;
   3321		ecmd->base.autoneg = ahw->link_autoneg;
   3322	} else {
   3323		ecmd->base.speed = SPEED_UNKNOWN;
   3324		ecmd->base.duplex = DUPLEX_UNKNOWN;
   3325		ecmd->base.autoneg = AUTONEG_DISABLE;
   3326	}
   3327
   3328	supported = (SUPPORTED_10baseT_Full |
   3329			   SUPPORTED_100baseT_Full |
   3330			   SUPPORTED_1000baseT_Full |
   3331			   SUPPORTED_10000baseT_Full |
   3332			   SUPPORTED_Autoneg);
   3333
   3334	ethtool_convert_link_mode_to_legacy_u32(&advertising,
   3335						ecmd->link_modes.advertising);
   3336
   3337	if (ecmd->base.autoneg == AUTONEG_ENABLE) {
   3338		if (ahw->port_config & QLC_83XX_10_CAPABLE)
   3339			advertising |= SUPPORTED_10baseT_Full;
   3340		if (ahw->port_config & QLC_83XX_100_CAPABLE)
   3341			advertising |= SUPPORTED_100baseT_Full;
   3342		if (ahw->port_config & QLC_83XX_1G_CAPABLE)
   3343			advertising |= SUPPORTED_1000baseT_Full;
   3344		if (ahw->port_config & QLC_83XX_10G_CAPABLE)
   3345			advertising |= SUPPORTED_10000baseT_Full;
   3346		if (ahw->port_config & QLC_83XX_AUTONEG_ENABLE)
   3347			advertising |= ADVERTISED_Autoneg;
   3348	} else {
   3349		switch (ahw->link_speed) {
   3350		case SPEED_10:
   3351			advertising = SUPPORTED_10baseT_Full;
   3352			break;
   3353		case SPEED_100:
   3354			advertising = SUPPORTED_100baseT_Full;
   3355			break;
   3356		case SPEED_1000:
   3357			advertising = SUPPORTED_1000baseT_Full;
   3358			break;
   3359		case SPEED_10000:
   3360			advertising = SUPPORTED_10000baseT_Full;
   3361			break;
   3362		default:
   3363			break;
   3364		}
   3365
   3366	}
   3367
   3368	switch (ahw->supported_type) {
   3369	case PORT_FIBRE:
   3370		supported |= SUPPORTED_FIBRE;
   3371		advertising |= ADVERTISED_FIBRE;
   3372		ecmd->base.port = PORT_FIBRE;
   3373		break;
   3374	case PORT_TP:
   3375		supported |= SUPPORTED_TP;
   3376		advertising |= ADVERTISED_TP;
   3377		ecmd->base.port = PORT_TP;
   3378		break;
   3379	case PORT_DA:
   3380		supported |= SUPPORTED_FIBRE;
   3381		advertising |= ADVERTISED_FIBRE;
   3382		ecmd->base.port = PORT_DA;
   3383		break;
   3384	default:
   3385		supported |= SUPPORTED_FIBRE;
   3386		advertising |= ADVERTISED_FIBRE;
   3387		ecmd->base.port = PORT_OTHER;
   3388		break;
   3389	}
   3390	ecmd->base.phy_address = ahw->physical_port;
   3391
   3392	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
   3393						supported);
   3394	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
   3395						advertising);
   3396
   3397	return status;
   3398}
   3399
   3400int qlcnic_83xx_set_link_ksettings(struct qlcnic_adapter *adapter,
   3401				   const struct ethtool_link_ksettings *ecmd)
   3402{
   3403	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3404	u32 config = adapter->ahw->port_config;
   3405	int status = 0;
   3406
   3407	/* 83xx devices do not support Half duplex */
   3408	if (ecmd->base.duplex == DUPLEX_HALF) {
   3409		netdev_info(adapter->netdev,
   3410			    "Half duplex mode not supported\n");
   3411		return -EINVAL;
   3412	}
   3413
   3414	if (ecmd->base.autoneg) {
   3415		ahw->port_config |= QLC_83XX_AUTONEG_ENABLE;
   3416		ahw->port_config |= (QLC_83XX_100_CAPABLE |
   3417				     QLC_83XX_1G_CAPABLE |
   3418				     QLC_83XX_10G_CAPABLE);
   3419	} else { /* force speed */
   3420		ahw->port_config &= ~QLC_83XX_AUTONEG_ENABLE;
   3421		switch (ecmd->base.speed) {
   3422		case SPEED_10:
   3423			ahw->port_config &= ~(QLC_83XX_100_CAPABLE |
   3424					      QLC_83XX_1G_CAPABLE |
   3425					      QLC_83XX_10G_CAPABLE);
   3426			ahw->port_config |= QLC_83XX_10_CAPABLE;
   3427			break;
   3428		case SPEED_100:
   3429			ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
   3430					      QLC_83XX_1G_CAPABLE |
   3431					      QLC_83XX_10G_CAPABLE);
   3432			ahw->port_config |= QLC_83XX_100_CAPABLE;
   3433			break;
   3434		case SPEED_1000:
   3435			ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
   3436					      QLC_83XX_100_CAPABLE |
   3437					      QLC_83XX_10G_CAPABLE);
   3438			ahw->port_config |= QLC_83XX_1G_CAPABLE;
   3439			break;
   3440		case SPEED_10000:
   3441			ahw->port_config &= ~(QLC_83XX_10_CAPABLE |
   3442					      QLC_83XX_100_CAPABLE |
   3443					      QLC_83XX_1G_CAPABLE);
   3444			ahw->port_config |= QLC_83XX_10G_CAPABLE;
   3445			break;
   3446		default:
   3447			return -EINVAL;
   3448		}
   3449	}
   3450	status = qlcnic_83xx_set_port_config(adapter);
   3451	if (status) {
   3452		netdev_info(adapter->netdev,
   3453			    "Failed to Set Link Speed and autoneg.\n");
   3454		ahw->port_config = config;
   3455	}
   3456
   3457	return status;
   3458}
   3459
   3460static inline u64 *qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd,
   3461					  u64 *data, int index)
   3462{
   3463	u32 low, hi;
   3464	u64 val;
   3465
   3466	low = cmd->rsp.arg[index];
   3467	hi = cmd->rsp.arg[index + 1];
   3468	val = (((u64) low) | (((u64) hi) << 32));
   3469	*data++ = val;
   3470	return data;
   3471}
   3472
   3473static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter,
   3474				   struct qlcnic_cmd_args *cmd, u64 *data,
   3475				   int type, int *ret)
   3476{
   3477	int err, k, total_regs;
   3478
   3479	*ret = 0;
   3480	err = qlcnic_issue_cmd(adapter, cmd);
   3481	if (err != QLCNIC_RCODE_SUCCESS) {
   3482		dev_info(&adapter->pdev->dev,
   3483			 "Error in get statistics mailbox command\n");
   3484		*ret = -EIO;
   3485		return data;
   3486	}
   3487	total_regs = cmd->rsp.num;
   3488	switch (type) {
   3489	case QLC_83XX_STAT_MAC:
   3490		/* fill in MAC tx counters */
   3491		for (k = 2; k < 28; k += 2)
   3492			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3493		/* skip 24 bytes of reserved area */
   3494		/* fill in MAC rx counters */
   3495		for (k += 6; k < 60; k += 2)
   3496			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3497		/* skip 24 bytes of reserved area */
   3498		/* fill in MAC rx frame stats */
   3499		for (k += 6; k < 80; k += 2)
   3500			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3501		/* fill in eSwitch stats */
   3502		for (; k < total_regs; k += 2)
   3503			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3504		break;
   3505	case QLC_83XX_STAT_RX:
   3506		for (k = 2; k < 8; k += 2)
   3507			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3508		/* skip 8 bytes of reserved data */
   3509		for (k += 2; k < 24; k += 2)
   3510			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3511		/* skip 8 bytes containing RE1FBQ error data */
   3512		for (k += 2; k < total_regs; k += 2)
   3513			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3514		break;
   3515	case QLC_83XX_STAT_TX:
   3516		for (k = 2; k < 10; k += 2)
   3517			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3518		/* skip 8 bytes of reserved data */
   3519		for (k += 2; k < total_regs; k += 2)
   3520			data = qlcnic_83xx_copy_stats(cmd, data, k);
   3521		break;
   3522	default:
   3523		dev_warn(&adapter->pdev->dev, "Unknown get statistics mode\n");
   3524		*ret = -EIO;
   3525	}
   3526	return data;
   3527}
   3528
   3529void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
   3530{
   3531	struct qlcnic_cmd_args cmd;
   3532	struct net_device *netdev = adapter->netdev;
   3533	int ret = 0;
   3534
   3535	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
   3536	if (ret)
   3537		return;
   3538	/* Get Tx stats */
   3539	cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16);
   3540	cmd.rsp.num = QLC_83XX_TX_STAT_REGS;
   3541	data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
   3542				      QLC_83XX_STAT_TX, &ret);
   3543	if (ret) {
   3544		netdev_err(netdev, "Error getting Tx stats\n");
   3545		goto out;
   3546	}
   3547	/* Get MAC stats */
   3548	cmd.req.arg[1] = BIT_2 | (adapter->portnum << 16);
   3549	cmd.rsp.num = QLC_83XX_MAC_STAT_REGS;
   3550	memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
   3551	data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
   3552				      QLC_83XX_STAT_MAC, &ret);
   3553	if (ret) {
   3554		netdev_err(netdev, "Error getting MAC stats\n");
   3555		goto out;
   3556	}
   3557	/* Get Rx stats */
   3558	cmd.req.arg[1] = adapter->recv_ctx->context_id << 16;
   3559	cmd.rsp.num = QLC_83XX_RX_STAT_REGS;
   3560	memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num);
   3561	data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
   3562				      QLC_83XX_STAT_RX, &ret);
   3563	if (ret)
   3564		netdev_err(netdev, "Error getting Rx stats\n");
   3565out:
   3566	qlcnic_free_mbx_args(&cmd);
   3567}
   3568
   3569#define QLCNIC_83XX_ADD_PORT0		BIT_0
   3570#define QLCNIC_83XX_ADD_PORT1		BIT_1
   3571#define QLCNIC_83XX_EXTENDED_MEM_SIZE	13 /* In MB */
   3572int qlcnic_83xx_extend_md_capab(struct qlcnic_adapter *adapter)
   3573{
   3574	struct qlcnic_cmd_args cmd;
   3575	int err;
   3576
   3577	err = qlcnic_alloc_mbx_args(&cmd, adapter,
   3578				    QLCNIC_CMD_83XX_EXTEND_ISCSI_DUMP_CAP);
   3579	if (err)
   3580		return err;
   3581
   3582	cmd.req.arg[1] = (QLCNIC_83XX_ADD_PORT0 | QLCNIC_83XX_ADD_PORT1);
   3583	cmd.req.arg[2] = QLCNIC_83XX_EXTENDED_MEM_SIZE;
   3584	cmd.req.arg[3] = QLCNIC_83XX_EXTENDED_MEM_SIZE;
   3585
   3586	err = qlcnic_issue_cmd(adapter, &cmd);
   3587	if (err)
   3588		dev_err(&adapter->pdev->dev,
   3589			"failed to issue extend iSCSI minidump capability\n");
   3590
   3591	return err;
   3592}
   3593
   3594int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter)
   3595{
   3596	u32 major, minor, sub;
   3597
   3598	major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
   3599	minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
   3600	sub = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
   3601
   3602	if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) {
   3603		dev_info(&adapter->pdev->dev, "%s: Reg test failed\n",
   3604			 __func__);
   3605		return 1;
   3606	}
   3607	return 0;
   3608}
   3609
   3610inline int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter)
   3611{
   3612	return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) *
   3613		sizeof(*adapter->ahw->ext_reg_tbl)) +
   3614		(ARRAY_SIZE(qlcnic_83xx_reg_tbl) *
   3615		sizeof(*adapter->ahw->reg_tbl));
   3616}
   3617
   3618int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff)
   3619{
   3620	int i, j = 0;
   3621
   3622	for (i = QLCNIC_DEV_INFO_SIZE + 1;
   3623	     j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++)
   3624		regs_buff[i] = QLC_SHARED_REG_RD32(adapter, j);
   3625
   3626	for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++)
   3627		regs_buff[i++] = QLCRDX(adapter->ahw, j);
   3628	return i;
   3629}
   3630
   3631int qlcnic_83xx_interrupt_test(struct net_device *netdev)
   3632{
   3633	struct qlcnic_adapter *adapter = netdev_priv(netdev);
   3634	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3635	struct qlcnic_cmd_args cmd;
   3636	u8 val, drv_sds_rings = adapter->drv_sds_rings;
   3637	u8 drv_tx_rings = adapter->drv_tx_rings;
   3638	u32 data;
   3639	u16 intrpt_id, id;
   3640	int ret;
   3641
   3642	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
   3643		netdev_info(netdev, "Device is resetting\n");
   3644		return -EBUSY;
   3645	}
   3646
   3647	if (qlcnic_get_diag_lock(adapter)) {
   3648		netdev_info(netdev, "Device in diagnostics mode\n");
   3649		return -EBUSY;
   3650	}
   3651
   3652	ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST,
   3653					 drv_sds_rings);
   3654	if (ret)
   3655		goto fail_diag_irq;
   3656
   3657	ahw->diag_cnt = 0;
   3658	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
   3659	if (ret)
   3660		goto fail_mbx_args;
   3661
   3662	if (adapter->flags & QLCNIC_MSIX_ENABLED)
   3663		intrpt_id = ahw->intr_tbl[0].id;
   3664	else
   3665		intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
   3666
   3667	cmd.req.arg[1] = 1;
   3668	cmd.req.arg[2] = intrpt_id;
   3669	cmd.req.arg[3] = BIT_0;
   3670
   3671	ret = qlcnic_issue_cmd(adapter, &cmd);
   3672	data = cmd.rsp.arg[2];
   3673	id = LSW(data);
   3674	val = LSB(MSW(data));
   3675	if (id != intrpt_id)
   3676		dev_info(&adapter->pdev->dev,
   3677			 "Interrupt generated: 0x%x, requested:0x%x\n",
   3678			 id, intrpt_id);
   3679	if (val)
   3680		dev_err(&adapter->pdev->dev,
   3681			 "Interrupt test error: 0x%x\n", val);
   3682	if (ret)
   3683		goto done;
   3684
   3685	msleep(20);
   3686	ret = !ahw->diag_cnt;
   3687
   3688done:
   3689	qlcnic_free_mbx_args(&cmd);
   3690
   3691fail_mbx_args:
   3692	qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
   3693
   3694fail_diag_irq:
   3695	adapter->drv_sds_rings = drv_sds_rings;
   3696	adapter->drv_tx_rings = drv_tx_rings;
   3697	qlcnic_release_diag_lock(adapter);
   3698	return ret;
   3699}
   3700
   3701void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter,
   3702				struct ethtool_pauseparam *pause)
   3703{
   3704	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3705	int status = 0;
   3706	u32 config;
   3707
   3708	status = qlcnic_83xx_get_port_config(adapter);
   3709	if (status) {
   3710		dev_err(&adapter->pdev->dev,
   3711			"%s: Get Pause Config failed\n", __func__);
   3712		return;
   3713	}
   3714	config = ahw->port_config;
   3715	if (config & QLC_83XX_CFG_STD_PAUSE) {
   3716		switch (MSW(config)) {
   3717		case QLC_83XX_TX_PAUSE:
   3718			pause->tx_pause = 1;
   3719			break;
   3720		case QLC_83XX_RX_PAUSE:
   3721			pause->rx_pause = 1;
   3722			break;
   3723		case QLC_83XX_TX_RX_PAUSE:
   3724		default:
   3725			/* Backward compatibility for existing
   3726			 * flash definitions
   3727			 */
   3728			pause->tx_pause = 1;
   3729			pause->rx_pause = 1;
   3730		}
   3731	}
   3732
   3733	if (QLC_83XX_AUTONEG(config))
   3734		pause->autoneg = 1;
   3735}
   3736
   3737int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,
   3738			       struct ethtool_pauseparam *pause)
   3739{
   3740	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3741	int status = 0;
   3742	u32 config;
   3743
   3744	status = qlcnic_83xx_get_port_config(adapter);
   3745	if (status) {
   3746		dev_err(&adapter->pdev->dev,
   3747			"%s: Get Pause Config failed.\n", __func__);
   3748		return status;
   3749	}
   3750	config = ahw->port_config;
   3751
   3752	if (ahw->port_type == QLCNIC_GBE) {
   3753		if (pause->autoneg)
   3754			ahw->port_config |= QLC_83XX_ENABLE_AUTONEG;
   3755		if (!pause->autoneg)
   3756			ahw->port_config &= ~QLC_83XX_ENABLE_AUTONEG;
   3757	} else if ((ahw->port_type == QLCNIC_XGBE) && (pause->autoneg)) {
   3758		return -EOPNOTSUPP;
   3759	}
   3760
   3761	if (!(config & QLC_83XX_CFG_STD_PAUSE))
   3762		ahw->port_config |= QLC_83XX_CFG_STD_PAUSE;
   3763
   3764	if (pause->rx_pause && pause->tx_pause) {
   3765		ahw->port_config |= QLC_83XX_CFG_STD_TX_RX_PAUSE;
   3766	} else if (pause->rx_pause && !pause->tx_pause) {
   3767		ahw->port_config &= ~QLC_83XX_CFG_STD_TX_PAUSE;
   3768		ahw->port_config |= QLC_83XX_CFG_STD_RX_PAUSE;
   3769	} else if (pause->tx_pause && !pause->rx_pause) {
   3770		ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE;
   3771		ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE;
   3772	} else if (!pause->rx_pause && !pause->tx_pause) {
   3773		ahw->port_config &= ~(QLC_83XX_CFG_STD_TX_RX_PAUSE |
   3774				      QLC_83XX_CFG_STD_PAUSE);
   3775	}
   3776	status = qlcnic_83xx_set_port_config(adapter);
   3777	if (status) {
   3778		dev_err(&adapter->pdev->dev,
   3779			"%s: Set Pause Config failed.\n", __func__);
   3780		ahw->port_config = config;
   3781	}
   3782	return status;
   3783}
   3784
   3785static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
   3786{
   3787	int ret, err = 0;
   3788	u32 temp;
   3789
   3790	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
   3791				     QLC_83XX_FLASH_OEM_READ_SIG);
   3792	qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL,
   3793				     QLC_83XX_FLASH_READ_CTRL);
   3794	ret = qlcnic_83xx_poll_flash_status_reg(adapter);
   3795	if (ret)
   3796		return -EIO;
   3797
   3798	temp = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
   3799	if (err == -EIO)
   3800		return err;
   3801
   3802	return temp & 0xFF;
   3803}
   3804
   3805int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
   3806{
   3807	int status;
   3808
   3809	status = qlcnic_83xx_read_flash_status_reg(adapter);
   3810	if (status == -EIO) {
   3811		dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n",
   3812			 __func__);
   3813		return 1;
   3814	}
   3815	return 0;
   3816}
   3817
   3818static int qlcnic_83xx_shutdown(struct pci_dev *pdev)
   3819{
   3820	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
   3821	struct net_device *netdev = adapter->netdev;
   3822
   3823	netif_device_detach(netdev);
   3824	qlcnic_cancel_idc_work(adapter);
   3825
   3826	if (netif_running(netdev))
   3827		qlcnic_down(adapter, netdev);
   3828
   3829	qlcnic_83xx_disable_mbx_intr(adapter);
   3830	cancel_delayed_work_sync(&adapter->idc_aen_work);
   3831
   3832	return pci_save_state(pdev);
   3833}
   3834
   3835static int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
   3836{
   3837	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3838	struct qlc_83xx_idc *idc = &ahw->idc;
   3839	int err = 0;
   3840
   3841	err = qlcnic_83xx_idc_init(adapter);
   3842	if (err)
   3843		return err;
   3844
   3845	if (ahw->nic_mode == QLCNIC_VNIC_MODE) {
   3846		if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
   3847			qlcnic_83xx_set_vnic_opmode(adapter);
   3848		} else {
   3849			err = qlcnic_83xx_check_vnic_state(adapter);
   3850			if (err)
   3851				return err;
   3852		}
   3853	}
   3854
   3855	err = qlcnic_83xx_idc_reattach_driver(adapter);
   3856	if (err)
   3857		return err;
   3858
   3859	qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
   3860			     idc->delay);
   3861	return err;
   3862}
   3863
   3864void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx)
   3865{
   3866	reinit_completion(&mbx->completion);
   3867	set_bit(QLC_83XX_MBX_READY, &mbx->status);
   3868}
   3869
   3870void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
   3871{
   3872	if (!mbx)
   3873		return;
   3874
   3875	destroy_workqueue(mbx->work_q);
   3876	kfree(mbx);
   3877}
   3878
   3879static inline void
   3880qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter,
   3881				  struct qlcnic_cmd_args *cmd)
   3882{
   3883	atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED);
   3884
   3885	if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) {
   3886		qlcnic_free_mbx_args(cmd);
   3887		kfree(cmd);
   3888		return;
   3889	}
   3890	complete(&cmd->completion);
   3891}
   3892
   3893static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter)
   3894{
   3895	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
   3896	struct list_head *head = &mbx->cmd_q;
   3897	struct qlcnic_cmd_args *cmd = NULL;
   3898
   3899	spin_lock_bh(&mbx->queue_lock);
   3900
   3901	while (!list_empty(head)) {
   3902		cmd = list_entry(head->next, struct qlcnic_cmd_args, list);
   3903		dev_info(&adapter->pdev->dev, "%s: Mailbox command 0x%x\n",
   3904			 __func__, cmd->cmd_op);
   3905		list_del(&cmd->list);
   3906		mbx->num_cmds--;
   3907		qlcnic_83xx_notify_cmd_completion(adapter, cmd);
   3908	}
   3909
   3910	spin_unlock_bh(&mbx->queue_lock);
   3911}
   3912
   3913static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter)
   3914{
   3915	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3916	struct qlcnic_mailbox *mbx = ahw->mailbox;
   3917	u32 host_mbx_ctrl;
   3918
   3919	if (!test_bit(QLC_83XX_MBX_READY, &mbx->status))
   3920		return -EBUSY;
   3921
   3922	host_mbx_ctrl = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);
   3923	if (host_mbx_ctrl) {
   3924		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
   3925		ahw->idc.collect_dump = 1;
   3926		return -EIO;
   3927	}
   3928
   3929	return 0;
   3930}
   3931
   3932static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter,
   3933					      u8 issue_cmd)
   3934{
   3935	if (issue_cmd)
   3936		QLCWRX(adapter->ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
   3937	else
   3938		QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
   3939}
   3940
   3941static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter,
   3942					struct qlcnic_cmd_args *cmd)
   3943{
   3944	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
   3945
   3946	spin_lock_bh(&mbx->queue_lock);
   3947
   3948	list_del(&cmd->list);
   3949	mbx->num_cmds--;
   3950
   3951	spin_unlock_bh(&mbx->queue_lock);
   3952
   3953	qlcnic_83xx_notify_cmd_completion(adapter, cmd);
   3954}
   3955
   3956static void qlcnic_83xx_encode_mbx_cmd(struct qlcnic_adapter *adapter,
   3957				       struct qlcnic_cmd_args *cmd)
   3958{
   3959	u32 mbx_cmd, fw_hal_version, hdr_size, total_size, tmp;
   3960	struct qlcnic_hardware_context *ahw = adapter->ahw;
   3961	int i, j;
   3962
   3963	if (cmd->op_type != QLC_83XX_MBX_POST_BC_OP) {
   3964		mbx_cmd = cmd->req.arg[0];
   3965		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
   3966		for (i = 1; i < cmd->req.num; i++)
   3967			writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));
   3968	} else {
   3969		fw_hal_version = ahw->fw_hal_version;
   3970		hdr_size = sizeof(struct qlcnic_bc_hdr) / sizeof(u32);
   3971		total_size = cmd->pay_size + hdr_size;
   3972		tmp = QLCNIC_CMD_BC_EVENT_SETUP | total_size << 16;
   3973		mbx_cmd = tmp | fw_hal_version << 29;
   3974		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
   3975
   3976		/* Back channel specific operations bits */
   3977		mbx_cmd = 0x1 | 1 << 4;
   3978
   3979		if (qlcnic_sriov_pf_check(adapter))
   3980			mbx_cmd |= cmd->func_num << 5;
   3981
   3982		writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1));
   3983
   3984		for (i = 2, j = 0; j < hdr_size; i++, j++)
   3985			writel(*(cmd->hdr++), QLCNIC_MBX_HOST(ahw, i));
   3986		for (j = 0; j < cmd->pay_size; j++, i++)
   3987			writel(*(cmd->pay++), QLCNIC_MBX_HOST(ahw, i));
   3988	}
   3989}
   3990
   3991void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
   3992{
   3993	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
   3994
   3995	if (!mbx)
   3996		return;
   3997
   3998	clear_bit(QLC_83XX_MBX_READY, &mbx->status);
   3999	complete(&mbx->completion);
   4000	cancel_work_sync(&mbx->work);
   4001	flush_workqueue(mbx->work_q);
   4002	qlcnic_83xx_flush_mbx_queue(adapter);
   4003}
   4004
   4005static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter,
   4006				       struct qlcnic_cmd_args *cmd,
   4007				       unsigned long *timeout)
   4008{
   4009	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
   4010
   4011	if (test_bit(QLC_83XX_MBX_READY, &mbx->status)) {
   4012		atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_WAIT);
   4013		init_completion(&cmd->completion);
   4014		cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_UNKNOWN;
   4015
   4016		spin_lock_bh(&mbx->queue_lock);
   4017
   4018		list_add_tail(&cmd->list, &mbx->cmd_q);
   4019		mbx->num_cmds++;
   4020		cmd->total_cmds = mbx->num_cmds;
   4021		*timeout = cmd->total_cmds * QLC_83XX_MBX_TIMEOUT;
   4022		queue_work(mbx->work_q, &mbx->work);
   4023
   4024		spin_unlock_bh(&mbx->queue_lock);
   4025
   4026		return 0;
   4027	}
   4028
   4029	return -EBUSY;
   4030}
   4031
   4032static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter,
   4033				       struct qlcnic_cmd_args *cmd)
   4034{
   4035	u8 mac_cmd_rcode;
   4036	u32 fw_data;
   4037
   4038	if (cmd->cmd_op == QLCNIC_CMD_CONFIG_MAC_VLAN) {
   4039		fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
   4040		mac_cmd_rcode = (u8)fw_data;
   4041		if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
   4042		    mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
   4043		    mac_cmd_rcode == QLC_83XX_MAC_ABSENT) {
   4044			cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS;
   4045			return QLCNIC_RCODE_SUCCESS;
   4046		}
   4047	}
   4048
   4049	return -EINVAL;
   4050}
   4051
   4052static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter,
   4053				       struct qlcnic_cmd_args *cmd)
   4054{
   4055	struct qlcnic_hardware_context *ahw = adapter->ahw;
   4056	struct device *dev = &adapter->pdev->dev;
   4057	u8 mbx_err_code;
   4058	u32 fw_data;
   4059
   4060	fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
   4061	mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
   4062	qlcnic_83xx_get_mbx_data(adapter, cmd);
   4063
   4064	switch (mbx_err_code) {
   4065	case QLCNIC_MBX_RSP_OK:
   4066	case QLCNIC_MBX_PORT_RSP_OK:
   4067		cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS;
   4068		break;
   4069	default:
   4070		if (!qlcnic_83xx_check_mac_rcode(adapter, cmd))
   4071			break;
   4072
   4073		dev_err(dev, "%s: Mailbox command failed, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x, error=0x%x\n",
   4074			__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
   4075			ahw->op_mode, mbx_err_code);
   4076		cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_FAILED;
   4077		qlcnic_dump_mbx(adapter, cmd);
   4078	}
   4079
   4080	return;
   4081}
   4082
   4083static inline void qlcnic_dump_mailbox_registers(struct qlcnic_adapter *adapter)
   4084{
   4085	struct qlcnic_hardware_context *ahw = adapter->ahw;
   4086	u32 offset;
   4087
   4088	offset = QLCRDX(ahw, QLCNIC_DEF_INT_MASK);
   4089	dev_info(&adapter->pdev->dev, "Mbx interrupt mask=0x%x, Mbx interrupt enable=0x%x, Host mbx control=0x%x, Fw mbx control=0x%x",
   4090		 readl(ahw->pci_base0 + offset),
   4091		 QLCRDX(ahw, QLCNIC_MBX_INTR_ENBL),
   4092		 QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL),
   4093		 QLCRDX(ahw, QLCNIC_FW_MBX_CTRL));
   4094}
   4095
   4096static void qlcnic_83xx_mailbox_worker(struct work_struct *work)
   4097{
   4098	struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox,
   4099						  work);
   4100	struct qlcnic_adapter *adapter = mbx->adapter;
   4101	const struct qlcnic_mbx_ops *mbx_ops = mbx->ops;
   4102	struct device *dev = &adapter->pdev->dev;
   4103	struct list_head *head = &mbx->cmd_q;
   4104	struct qlcnic_hardware_context *ahw;
   4105	struct qlcnic_cmd_args *cmd = NULL;
   4106	unsigned long flags;
   4107
   4108	ahw = adapter->ahw;
   4109
   4110	while (true) {
   4111		if (qlcnic_83xx_check_mbx_status(adapter)) {
   4112			qlcnic_83xx_flush_mbx_queue(adapter);
   4113			return;
   4114		}
   4115
   4116		spin_lock_irqsave(&mbx->aen_lock, flags);
   4117		mbx->rsp_status = QLC_83XX_MBX_RESPONSE_WAIT;
   4118		spin_unlock_irqrestore(&mbx->aen_lock, flags);
   4119
   4120		spin_lock_bh(&mbx->queue_lock);
   4121
   4122		if (list_empty(head)) {
   4123			spin_unlock_bh(&mbx->queue_lock);
   4124			return;
   4125		}
   4126		cmd = list_entry(head->next, struct qlcnic_cmd_args, list);
   4127
   4128		spin_unlock_bh(&mbx->queue_lock);
   4129
   4130		mbx_ops->encode_cmd(adapter, cmd);
   4131		mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_REQUEST);
   4132
   4133		if (wait_for_completion_timeout(&mbx->completion,
   4134						QLC_83XX_MBX_TIMEOUT)) {
   4135			mbx_ops->decode_resp(adapter, cmd);
   4136			mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_COMPLETION);
   4137		} else {
   4138			dev_err(dev, "%s: Mailbox command timeout, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x\n",
   4139				__func__, cmd->cmd_op, cmd->type, ahw->pci_func,
   4140				ahw->op_mode);
   4141			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
   4142			qlcnic_dump_mailbox_registers(adapter);
   4143			qlcnic_83xx_get_mbx_data(adapter, cmd);
   4144			qlcnic_dump_mbx(adapter, cmd);
   4145			qlcnic_83xx_idc_request_reset(adapter,
   4146						      QLCNIC_FORCE_FW_DUMP_KEY);
   4147			cmd->rsp_opcode = QLCNIC_RCODE_TIMEOUT;
   4148		}
   4149		mbx_ops->dequeue_cmd(adapter, cmd);
   4150	}
   4151}
   4152
   4153static const struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = {
   4154	.enqueue_cmd    = qlcnic_83xx_enqueue_mbx_cmd,
   4155	.dequeue_cmd    = qlcnic_83xx_dequeue_mbx_cmd,
   4156	.decode_resp    = qlcnic_83xx_decode_mbx_rsp,
   4157	.encode_cmd     = qlcnic_83xx_encode_mbx_cmd,
   4158	.nofity_fw      = qlcnic_83xx_signal_mbx_cmd,
   4159};
   4160
   4161int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter)
   4162{
   4163	struct qlcnic_hardware_context *ahw = adapter->ahw;
   4164	struct qlcnic_mailbox *mbx;
   4165
   4166	ahw->mailbox = kzalloc(sizeof(*mbx), GFP_KERNEL);
   4167	if (!ahw->mailbox)
   4168		return -ENOMEM;
   4169
   4170	mbx = ahw->mailbox;
   4171	mbx->ops = &qlcnic_83xx_mbx_ops;
   4172	mbx->adapter = adapter;
   4173
   4174	spin_lock_init(&mbx->queue_lock);
   4175	spin_lock_init(&mbx->aen_lock);
   4176	INIT_LIST_HEAD(&mbx->cmd_q);
   4177	init_completion(&mbx->completion);
   4178
   4179	mbx->work_q = create_singlethread_workqueue("qlcnic_mailbox");
   4180	if (mbx->work_q == NULL) {
   4181		kfree(mbx);
   4182		return -ENOMEM;
   4183	}
   4184
   4185	INIT_WORK(&mbx->work, qlcnic_83xx_mailbox_worker);
   4186	set_bit(QLC_83XX_MBX_READY, &mbx->status);
   4187	return 0;
   4188}
   4189
   4190static pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev,
   4191						      pci_channel_state_t state)
   4192{
   4193	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
   4194
   4195	if (state == pci_channel_io_perm_failure)
   4196		return PCI_ERS_RESULT_DISCONNECT;
   4197
   4198	if (state == pci_channel_io_normal)
   4199		return PCI_ERS_RESULT_RECOVERED;
   4200
   4201	set_bit(__QLCNIC_AER, &adapter->state);
   4202	set_bit(__QLCNIC_RESETTING, &adapter->state);
   4203
   4204	qlcnic_83xx_aer_stop_poll_work(adapter);
   4205
   4206	pci_save_state(pdev);
   4207	pci_disable_device(pdev);
   4208
   4209	return PCI_ERS_RESULT_NEED_RESET;
   4210}
   4211
   4212static pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev)
   4213{
   4214	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
   4215	int err = 0;
   4216
   4217	pdev->error_state = pci_channel_io_normal;
   4218	err = pci_enable_device(pdev);
   4219	if (err)
   4220		goto disconnect;
   4221
   4222	pci_set_power_state(pdev, PCI_D0);
   4223	pci_set_master(pdev);
   4224	pci_restore_state(pdev);
   4225
   4226	err = qlcnic_83xx_aer_reset(adapter);
   4227	if (err == 0)
   4228		return PCI_ERS_RESULT_RECOVERED;
   4229disconnect:
   4230	clear_bit(__QLCNIC_AER, &adapter->state);
   4231	clear_bit(__QLCNIC_RESETTING, &adapter->state);
   4232	return PCI_ERS_RESULT_DISCONNECT;
   4233}
   4234
   4235static void qlcnic_83xx_io_resume(struct pci_dev *pdev)
   4236{
   4237	struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
   4238
   4239	if (test_and_clear_bit(__QLCNIC_AER, &adapter->state))
   4240		qlcnic_83xx_aer_start_poll_work(adapter);
   4241}