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

Commit 068a8d19 authored by Manish Chopra's avatar Manish Chopra Committed by David S. Miller
Browse files

qlcnic: Replace poll mode mailbox interface with interrupt based mailbox interface

parent e5c4e6c6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -466,7 +466,6 @@ struct qlcnic_hardware_context {
	u32 *ext_reg_tbl;
	u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
	u32 mbox_reg[4];
	spinlock_t mbx_lock;
	struct qlcnic_mailbox *mailbox;
};

+123 −137
Original line number Diff line number Diff line
@@ -362,6 +362,10 @@ static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter,
				     struct qlcnic_cmd_args *cmd)
{
	int i;

	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
		return;

	for (i = 0; i < cmd->rsp.num; i++)
		cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i));
}
@@ -406,22 +410,25 @@ static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx)

static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter)
{
	u32 resp, event;
	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
	unsigned long flags;

	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);

	spin_lock_irqsave(&mbx->aen_lock, flags);
	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
	if (!(resp & QLCNIC_SET_OWNER))
		goto out;

	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
	if (event &  QLCNIC_MBX_ASYNC_EVENT)
	if (event &  QLCNIC_MBX_ASYNC_EVENT) {
		__qlcnic_83xx_process_aen(adapter);

	} else {
		if (atomic_read(&mbx->rsp_status) != rsp_status)
			qlcnic_83xx_notify_mbx_response(mbx);
	}
out:
	qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter);
	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
	spin_unlock_irqrestore(&mbx->aen_lock, flags);
}

irqreturn_t qlcnic_83xx_intr(int irq, void *data)
@@ -694,6 +701,9 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
{
	int i;

	if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP)
		return;

	dev_info(&adapter->pdev->dev,
		 "Host MBX regs(%d)\n", cmd->req.num);
	for (i = 0; i < cmd->req.num; i++) {
@@ -712,120 +722,74 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter,
	pr_info("\n");
}

/* Mailbox response for mac rcode */
u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter)
static inline void
qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter,
				    struct qlcnic_cmd_args *cmd)
{
	u32 fw_data;
	u8 mac_cmd_rcode;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int opcode = LSW(cmd->req.arg[0]);
	unsigned long max_loops;

	fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2));
	mac_cmd_rcode = (u8)fw_data;
	if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE ||
	    mac_cmd_rcode == QLC_83XX_MAC_PRESENT ||
	    mac_cmd_rcode == QLC_83XX_MAC_ABSENT)
		return QLCNIC_RCODE_SUCCESS;
	return 1;
}
	max_loops = cmd->total_cmds * QLC_83XX_MBX_CMD_LOOP;

u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time)
{
	u32 data;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	/* wait for mailbox completion */
	do {
		data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
		if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) {
			data = QLCNIC_RCODE_TIMEOUT;
			break;
	for (; max_loops; max_loops--) {
		if (atomic_read(&cmd->rsp_status) ==
		    QLC_83XX_MBX_RESPONSE_ARRIVED)
			return;

		udelay(1);
	}
		mdelay(1);
	} while (!data);
	return data;

	dev_err(&adapter->pdev->dev,
		"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
		__func__, opcode, cmd->type, ahw->pci_func, ahw->op_mode);
	flush_workqueue(ahw->mailbox->work_q);
	return;
}

int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
			  struct qlcnic_cmd_args *cmd)
{
	int i;
	u16 opcode;
	u8 mbx_err_code;
	unsigned long flags;
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0;
	int cmd_type, err, opcode;
	unsigned long timeout;

	opcode = LSW(cmd->req.arg[0]);
	if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) {
		dev_info(&adapter->pdev->dev,
			 "Mailbox cmd attempted, 0x%x\n", opcode);
		dev_info(&adapter->pdev->dev, "Mailbox detached\n");
		return 0;
	}

	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
	mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL);

	if (mbx_val) {
		QLCDB(adapter, DRV,
		      "Mailbox cmd attempted, 0x%x\n", opcode);
		QLCDB(adapter, DRV,
		      "Mailbox not available, 0x%x, collect FW dump\n",
		      mbx_val);
		cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
		spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
		return cmd->rsp.arg[0];
	cmd_type = cmd->type;
	err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
	if (err) {
		dev_err(&adapter->pdev->dev,
			"%s: Mailbox not available, cmd_op=0x%x, cmd_context=0x%x, pci_func=0x%x, op_mode=0x%x\n",
			__func__, opcode, cmd->type, ahw->pci_func,
			ahw->op_mode);
		return err;
	}

	/* Fill in mailbox registers */
	mbx_cmd = cmd->req.arg[0];
	writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0));
	for (i = 1; i < cmd->req.num; i++)
		writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i));

	/* Signal FW about the impending command */
	QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER);
poll:
	rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time);
	if (rsp != QLCNIC_RCODE_TIMEOUT) {
		/* Get the FW response data */
		fw_data = readl(QLCNIC_MBX_FW(ahw, 0));
		if (fw_data &  QLCNIC_MBX_ASYNC_EVENT) {
			__qlcnic_83xx_process_aen(adapter);
			goto poll;
	switch (cmd_type) {
	case QLC_83XX_MBX_CMD_WAIT:
		if (!wait_for_completion_timeout(&cmd->completion, timeout)) {
			dev_err(&adapter->pdev->dev,
				"%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
				__func__, opcode, cmd_type, ahw->pci_func,
				ahw->op_mode);
			flush_workqueue(mbx->work_q);
		}
		mbx_err_code = QLCNIC_MBX_STATUS(fw_data);
		rsp_num = QLCNIC_MBX_NUM_REGS(fw_data);
		opcode = QLCNIC_MBX_RSP(fw_data);
		qlcnic_83xx_get_mbx_data(adapter, cmd);

		switch (mbx_err_code) {
		case QLCNIC_MBX_RSP_OK:
		case QLCNIC_MBX_PORT_RSP_OK:
			rsp = QLCNIC_RCODE_SUCCESS;
		break;
	case QLC_83XX_MBX_CMD_NO_WAIT:
		return 0;
	case QLC_83XX_MBX_CMD_BUSY_WAIT:
		qlcnic_83xx_poll_for_mbx_completion(adapter, cmd);
		break;
	default:
			if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) {
				rsp = qlcnic_83xx_mac_rcode(adapter);
				if (!rsp)
					goto out;
			}
		dev_err(&adapter->pdev->dev,
				"MBX command 0x%x failed with err:0x%x\n",
				opcode, mbx_err_code);
			rsp = mbx_err_code;
			qlcnic_dump_mbx(adapter, cmd);
			break;
		}
		goto out;
			"%s: Invalid mailbox command, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n",
			__func__, opcode, cmd_type, ahw->pci_func,
			ahw->op_mode);
		qlcnic_83xx_detach_mailbox_work(adapter);
	}

	dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n",
		QLCNIC_MBX_RSP(mbx_cmd));
	rsp = QLCNIC_RCODE_TIMEOUT;
out:
	/* clear fw mbx control register */
	QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER);
	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);
	return rsp;
	return cmd->rsp_opcode;
}

int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
@@ -858,6 +822,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
			memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
			temp = adapter->ahw->fw_hal_version << 29;
			mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp);
			mbx->cmd_op = type;
			return 0;
		}
	}
@@ -941,20 +906,23 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)

static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter)
{
	u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	u32 resp, event;
	struct qlcnic_mailbox *mbx = ahw->mailbox;
	unsigned long flags;

	spin_lock_irqsave(&ahw->mbx_lock, flags);

	spin_lock_irqsave(&mbx->aen_lock, flags);
	resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL);
	if (resp & QLCNIC_SET_OWNER) {
		event = readl(QLCNIC_MBX_FW(ahw, 0));
		if (event &  QLCNIC_MBX_ASYNC_EVENT)
		if (event &  QLCNIC_MBX_ASYNC_EVENT) {
			__qlcnic_83xx_process_aen(adapter);
		} else {
			if (atomic_read(&mbx->rsp_status) != rsp_status)
				qlcnic_83xx_notify_mbx_response(mbx);
		}

	spin_unlock_irqrestore(&ahw->mbx_lock, flags);
	}
	spin_unlock_irqrestore(&mbx->aen_lock, flags);
}

static void qlcnic_83xx_mbx_poll_work(struct work_struct *work)
@@ -1627,26 +1595,33 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter,

int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
{
	int err;
	struct qlcnic_cmd_args *cmd = NULL;
	u32 temp = 0;
	struct qlcnic_cmd_args cmd;
	int err;

	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
		return -EIO;

	err = qlcnic_alloc_mbx_args(&cmd, adapter,
	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
	if (!cmd)
		return -ENOMEM;

	err = qlcnic_alloc_mbx_args(cmd, adapter,
				    QLCNIC_CMD_CONFIGURE_MAC_RX_MODE);
	if (err)
		return err;
		goto out;

	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;
	qlcnic_83xx_set_interface_id_promisc(adapter, &temp);
	cmd.req.arg[1] = (mode ? 1 : 0) | temp;
	err = qlcnic_issue_cmd(adapter, &cmd);
	if (err)
		dev_info(&adapter->pdev->dev,
			 "Promiscous mode config failed\n");
	cmd->req.arg[1] = (mode ? 1 : 0) | temp;
	err = qlcnic_issue_cmd(adapter, cmd);
	if (!err)
		return err;

	qlcnic_free_mbx_args(&cmd);
	qlcnic_free_mbx_args(cmd);

out:
	kfree(cmd);
	return err;
}

@@ -1967,25 +1942,31 @@ static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter,
int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
				   u16 vlan_id, u8 op)
{
	int err;
	u32 *buf, temp = 0;
	struct qlcnic_cmd_args cmd;
	struct qlcnic_cmd_args *cmd = NULL;
	struct qlcnic_macvlan_mbx mv;
	u32 *buf, temp = 0;
	int err;

	if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED)
		return -EIO;

	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
	if (!cmd)
		return -ENOMEM;

	err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN);
	if (err)
		return err;
		goto out;

	cmd->type = QLC_83XX_MBX_CMD_NO_WAIT;

	if (vlan_id)
		op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ?
		     QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL;

	cmd.req.arg[1] = op | (1 << 8);
	cmd->req.arg[1] = op | (1 << 8);
	qlcnic_83xx_set_interface_id_macaddr(adapter, &temp);
	cmd.req.arg[1] |= temp;
	cmd->req.arg[1] |= temp;
	mv.vlan = vlan_id;
	mv.mac_addr0 = addr[0];
	mv.mac_addr1 = addr[1];
@@ -1993,14 +1974,15 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
	mv.mac_addr3 = addr[3];
	mv.mac_addr4 = addr[4];
	mv.mac_addr5 = addr[5];
	buf = &cmd.req.arg[2];
	buf = &cmd->req.arg[2];
	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));
	err = qlcnic_issue_cmd(adapter, &cmd);
	if (err)
		dev_err(&adapter->pdev->dev,
			"MAC-VLAN %s to CAM failed, err=%d.\n",
			((op == 1) ? "add " : "delete "), err);
	qlcnic_free_mbx_args(&cmd);
	err = qlcnic_issue_cmd(adapter, cmd);
	if (!err)
		return err;

	qlcnic_free_mbx_args(cmd);
out:
	kfree(cmd);
	return err;
}

@@ -2109,10 +2091,12 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter,
irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
{
	struct qlcnic_adapter *adapter = data;
	unsigned long flags;
	struct qlcnic_mailbox *mbx;
	u32 mask, resp, event;
	unsigned long flags;

	spin_lock_irqsave(&adapter->ahw->mbx_lock, flags);
	mbx = adapter->ahw->mailbox;
	spin_lock_irqsave(&mbx->aen_lock, flags);
	resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL);
	if (!(resp & QLCNIC_SET_OWNER))
		goto out;
@@ -2120,11 +2104,13 @@ irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data)
	event = readl(QLCNIC_MBX_FW(adapter->ahw, 0));
	if (event &  QLCNIC_MBX_ASYNC_EVENT)
		__qlcnic_83xx_process_aen(adapter);
	else
		qlcnic_83xx_notify_mbx_response(mbx);

out:
	mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK);
	writel(0, adapter->ahw->pci_base0 + mask);
	spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags);

	spin_unlock_irqrestore(&mbx->aen_lock, flags);
	return IRQ_HANDLED;
}

+0 −2
Original line number Diff line number Diff line
@@ -644,8 +644,6 @@ int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);
int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
+61 −20
Original line number Diff line number Diff line
@@ -399,6 +399,7 @@ static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
	struct net_device *netdev = adapter->netdev;

	netif_device_detach(netdev);
	qlcnic_83xx_detach_mailbox_work(adapter);

	/* Disable mailbox interrupt */
	qlcnic_83xx_disable_mbx_intr(adapter);
@@ -610,6 +611,9 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
{
	int err;

	qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
	qlcnic_83xx_enable_mbx_interrupt(adapter);

	/* register for NIC IDC AEN Events */
	qlcnic_83xx_register_nic_idc_func(adapter, 1);

@@ -640,7 +644,6 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
	qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);

@@ -810,9 +813,10 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
 **/
static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
{
	u32 val;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_mailbox *mbx = ahw->mailbox;
	int ret = 0;
	u32 val;

	/* Perform NIC configuration based ready state entry actions */
	if (ahw->idc.state_entry(adapter))
@@ -824,7 +828,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
			dev_err(&adapter->pdev->dev,
				"Error: device temperature %d above limits\n",
				adapter->ahw->temp);
			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
			set_bit(__QLCNIC_RESETTING, &adapter->state);
			qlcnic_83xx_idc_detach_driver(adapter);
			qlcnic_83xx_idc_enter_failed_state(adapter, 1);
@@ -837,7 +841,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
	if (ret) {
		adapter->flags |= QLCNIC_FW_HANG;
		if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
			set_bit(__QLCNIC_RESETTING, &adapter->state);
			qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
		}
@@ -845,6 +849,8 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
	}

	if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {
		clear_bit(QLC_83XX_MBX_READY, &mbx->status);

		/* Move to need reset state and prepare for reset */
		qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
		return ret;
@@ -882,12 +888,13 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 **/
static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
	int ret = 0;

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

@@ -1079,7 +1086,6 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
	adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;

	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);

	/* Check if reset recovery is disabled */
@@ -1190,6 +1196,9 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
{
	u32 val;

	if (qlcnic_sriov_vf_check(adapter))
		return;

	if (qlcnic_83xx_lock_driver(adapter)) {
		dev_err(&adapter->pdev->dev,
			"%s:failed, please retry\n", __func__);
@@ -2110,17 +2119,35 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int err = 0;

	if (qlcnic_sriov_vf_check(adapter))
		return qlcnic_sriov_vf_init(adapter, pci_using_dac);
	ahw->msix_supported = !!qlcnic_use_msi_x;
	err = qlcnic_83xx_init_mailbox_work(adapter);
	if (err)
		goto exit;

	if (qlcnic_83xx_check_hw_status(adapter))
		return -EIO;
	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_vf_init(adapter, pci_using_dac);
		if (err)
			goto detach_mbx;
		else
			return err;
	}

	/* Initilaize 83xx mailbox spinlock */
	spin_lock_init(&ahw->mbx_lock);
	err = qlcnic_83xx_check_hw_status(adapter);
	if (err)
		goto detach_mbx;

	err = qlcnic_setup_intr(adapter, 0);
	if (err) {
		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
		goto disable_intr;
	}

	err = qlcnic_83xx_setup_mbx_intr(adapter);
	if (err)
		goto disable_mbx_intr;

	set_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
	qlcnic_83xx_clear_function_resources(adapter);

	/* register for NIC IDC AEN Events */
@@ -2129,21 +2156,35 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
	if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
		qlcnic_83xx_read_flash_mfg_id(adapter);

	if (qlcnic_83xx_idc_init(adapter))
		return -EIO;
	err = qlcnic_83xx_idc_init(adapter);
	if (err)
		goto disable_mbx_intr;

	/* Configure default, SR-IOV or Virtual NIC mode of operation */
	if (qlcnic_83xx_configure_opmode(adapter))
		return -EIO;
	err = qlcnic_83xx_configure_opmode(adapter);
	if (err)
		goto disable_mbx_intr;

	/* Perform operating mode specific initialization */
	if (adapter->nic_ops->init_driver(adapter))
		return -EIO;
	err = adapter->nic_ops->init_driver(adapter);
	if (err)
		goto disable_mbx_intr;

	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);

	/* Periodically monitor device status */
	qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
	return 0;

	return adapter->ahw->idc.err_code;
disable_mbx_intr:
	qlcnic_83xx_free_mbx_intr(adapter);

disable_intr:
	qlcnic_teardown_intr(adapter);

detach_mbx:
	qlcnic_83xx_detach_mailbox_work(adapter);
	qlcnic_83xx_free_mailbox(ahw->mailbox);
exit:
	return err;
}
+8 −10
Original line number Diff line number Diff line
@@ -2141,16 +2141,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		dev_warn(&pdev->dev,
			 "83xx adapter do not support MSI interrupts\n");

	if (qlcnic_82xx_check(adapter)) {
		err = qlcnic_setup_intr(adapter, 0);
		if (err) {
			dev_err(&pdev->dev, "Failed to setup interrupt\n");
			goto err_out_disable_msi;
		}

	if (qlcnic_83xx_check(adapter)) {
		err = qlcnic_83xx_setup_mbx_intr(adapter);
		if (err)
			goto err_out_disable_msi;
	}

	err = qlcnic_get_act_pci_func(adapter);
@@ -2237,9 +2233,11 @@ static void qlcnic_remove(struct pci_dev *pdev)
	qlcnic_sriov_cleanup(adapter);

	if (qlcnic_83xx_check(adapter)) {
		qlcnic_83xx_free_mbx_intr(adapter);
		qlcnic_83xx_register_nic_idc_func(adapter, 0);
		cancel_delayed_work_sync(&adapter->idc_aen_work);
		qlcnic_83xx_free_mbx_intr(adapter);
		qlcnic_83xx_detach_mailbox_work(adapter);
		qlcnic_83xx_free_mailbox(ahw->mailbox);
	}

	qlcnic_detach(adapter);
Loading