diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 165 |
1 files changed, 60 insertions, 105 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 5d40045b3cea..652cc13c5023 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -33,7 +33,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32); static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *); static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); -static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, +static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *); static void qlcnic_sriov_process_bc_cmd(struct work_struct *); @@ -45,7 +45,7 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { .get_mac_address = qlcnic_83xx_get_mac_address, .setup_intr = qlcnic_83xx_setup_intr, .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, - .mbx_cmd = qlcnic_sriov_vf_mbx_op, + .mbx_cmd = qlcnic_sriov_issue_cmd, .get_func_no = qlcnic_83xx_get_func_no, .api_lock = qlcnic_83xx_cam_lock, .api_unlock = qlcnic_83xx_cam_unlock, @@ -286,96 +286,38 @@ void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, u32 *pay, u8 pci_func, u8 size) { - u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val, wait_time = 0; struct qlcnic_hardware_context *ahw = adapter->ahw; - unsigned long flags; - u16 opcode; - u8 mbx_err_code; - int i, j; - - opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; - - 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(&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); - spin_unlock_irqrestore(&ahw->mbx_lock, flags); - return QLCNIC_RCODE_TIMEOUT; - } - /* Fill in mailbox registers */ - val = size + (sizeof(struct qlcnic_bc_hdr) / sizeof(u32)); - mbx_cmd = 0x31 | (val << 16) | (adapter->ahw->fw_hal_version << 29); - - writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); - mbx_cmd = 0x1 | (1 << 4); + struct qlcnic_mailbox *mbx = ahw->mailbox; + struct qlcnic_cmd_args cmd; + unsigned long timeout; + int err; - if (qlcnic_sriov_pf_check(adapter)) - mbx_cmd |= (pci_func << 5); + memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); + cmd.hdr = hdr; + cmd.pay = pay; + cmd.pay_size = size; + cmd.func_num = pci_func; + cmd.op_type = QLC_83XX_MBX_POST_BC_OP; + cmd.cmd_op = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; - writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1)); - for (i = 2, j = 0; j < (sizeof(struct qlcnic_bc_hdr) / sizeof(u32)); - i++, j++) { - writel(*(hdr++), QLCNIC_MBX_HOST(ahw, i)); + err = mbx->ops->enqueue_cmd(adapter, &cmd, &timeout); + if (err) { + dev_err(&adapter->pdev->dev, + "%s: Mailbox not available, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", + __func__, cmd.cmd_op, cmd.type, ahw->pci_func, + ahw->op_mode); + return err; } - for (j = 0; j < size; j++, i++) - writel(*(pay++), QLCNIC_MBX_HOST(ahw, i)); - /* Signal FW about the impending command */ - QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); - - /* Waiting for the mailbox cmd to complete and while waiting here - * some AEN might arrive. If more than 5 seconds expire we can - * assume something is wrong. - */ -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; - } - mbx_err_code = QLCNIC_MBX_STATUS(fw_data); - rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); - opcode = QLCNIC_MBX_RSP(fw_data); - - switch (mbx_err_code) { - case QLCNIC_MBX_RSP_OK: - case QLCNIC_MBX_PORT_RSP_OK: - rsp = QLCNIC_RCODE_SUCCESS; - 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; - break; - } - goto out; + 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__, cmd.cmd_op, cmd.type, ahw->pci_func, + ahw->op_mode); + flush_workqueue(mbx->work_q); } - 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; } static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter) @@ -458,7 +400,7 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *adapter, static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) { - adapter->rx_pvid = (cmd->rsp.arg[1] >> 16) & 0xffff; + adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; adapter->flags &= ~QLCNIC_TAGGING_ENABLED; return 0; } @@ -490,11 +432,12 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, return 0; } -static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter) +static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, + struct qlcnic_info *info) { struct qlcnic_sriov *sriov = adapter->ahw->sriov; struct qlcnic_cmd_args cmd; - int ret; + int ret = 0; ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); if (ret) @@ -522,8 +465,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter) static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) { - struct qlcnic_info nic_info; struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlcnic_info nic_info; int err; err = qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, 0); @@ -534,7 +477,7 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) if (err) return -EIO; - err = qlcnic_sriov_get_vf_acl(adapter); + err = qlcnic_sriov_get_vf_acl(adapter, &nic_info); if (err) return err; @@ -564,7 +507,7 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, dev_warn(&adapter->pdev->dev, "Device does not support MSI interrupts\n"); - err = qlcnic_setup_intr(adapter, 1); + err = qlcnic_setup_intr(adapter, 1, 0); if (err) { dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); goto err_out_disable_msi; @@ -590,6 +533,9 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, if (err) goto err_out_send_channel_term; + if (adapter->dcb && qlcnic_dcb_attach(adapter)) + qlcnic_clear_dcb_ops(adapter); + err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); if (err) goto err_out_send_channel_term; @@ -597,6 +543,7 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, pci_set_drvdata(adapter->pdev, adapter); dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n", adapter->netdev->name); + qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, adapter->ahw->idc.delay); return 0; @@ -637,8 +584,6 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac) struct qlcnic_hardware_context *ahw = adapter->ahw; int err; - spin_lock_init(&ahw->mbx_lock); - set_bit(QLC_83XX_MBX_READY, &ahw->idc.status); set_bit(QLC_83XX_MODULE_LOADED, &ahw->idc.status); ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; ahw->reset_context = 0; @@ -1085,6 +1030,7 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work) if (test_bit(QLC_BC_VF_FLR, &vf->state)) return; + memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); trans = list_first_entry(&vf->rcv_act.wait_list, struct qlcnic_bc_trans, list); adapter = vf->adapter; @@ -1234,6 +1180,7 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov, return; } + memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); cmd_op = hdr->cmd_op; if (qlcnic_sriov_alloc_bc_trans(&trans)) return; @@ -1359,7 +1306,7 @@ int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable) if (enable) cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); - err = qlcnic_83xx_mbx_op(adapter, &cmd); + err = qlcnic_83xx_issue_cmd(adapter, &cmd); if (err != QLCNIC_RCODE_SUCCESS) { dev_err(&adapter->pdev->dev, @@ -1391,10 +1338,11 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, return -EIO; } -static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, +static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) { struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlcnic_mailbox *mbx = ahw->mailbox; struct device *dev = &adapter->pdev->dev; struct qlcnic_bc_trans *trans; int err; @@ -1411,7 +1359,7 @@ static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, goto cleanup_transaction; retry: - if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { + if (!test_bit(QLC_83XX_MBX_READY, &mbx->status)) { rsp = -EIO; QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n", QLCNIC_MBX_RSP(cmd->req.arg[0]), func); @@ -1454,7 +1402,7 @@ err_out: if (rsp == QLCNIC_RCODE_TIMEOUT) { ahw->reset_context = 1; adapter->need_fw_reset = 1; - clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); + clear_bit(QLC_83XX_MBX_READY, &mbx->status); } cleanup_transaction: @@ -1613,8 +1561,8 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) { int err; - set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); - qlcnic_83xx_enable_mbx_intrpt(adapter); + qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox); + qlcnic_83xx_enable_mbx_interrupt(adapter); err = qlcnic_sriov_cfg_bc_intr(adapter, 1); if (err) @@ -1628,6 +1576,8 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) if (err) goto err_out_term_channel; + qlcnic_dcb_get_info(adapter); + return 0; err_out_term_channel: @@ -1657,8 +1607,10 @@ static void qlcnic_sriov_vf_detach(struct qlcnic_adapter *adapter) struct net_device *netdev = adapter->netdev; u8 i, max_ints = ahw->num_msix - 1; - qlcnic_83xx_disable_mbx_intr(adapter); netif_device_detach(netdev); + qlcnic_83xx_detach_mailbox_work(adapter); + qlcnic_83xx_disable_mbx_intr(adapter); + if (netif_running(netdev)) qlcnic_down(adapter, netdev); @@ -1702,6 +1654,7 @@ static int qlcnic_sriov_vf_handle_dev_ready(struct qlcnic_adapter *adapter) static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) { struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlcnic_mailbox *mbx = ahw->mailbox; struct device *dev = &adapter->pdev->dev; struct qlc_83xx_idc *idc = &ahw->idc; u8 func = ahw->pci_func; @@ -1712,7 +1665,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) /* Skip the context reset and check if FW is hung */ if (adapter->reset_ctx_cnt < 3) { adapter->need_fw_reset = 1; - clear_bit(QLC_83XX_MBX_READY, &idc->status); + clear_bit(QLC_83XX_MBX_READY, &mbx->status); dev_info(dev, "Resetting context, wait here to check if FW is in failed state\n"); return 0; @@ -1737,7 +1690,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) __func__, adapter->reset_ctx_cnt, func); set_bit(__QLCNIC_RESETTING, &adapter->state); adapter->need_fw_reset = 1; - clear_bit(QLC_83XX_MBX_READY, &idc->status); + clear_bit(QLC_83XX_MBX_READY, &mbx->status); qlcnic_sriov_vf_detach(adapter); adapter->need_fw_reset = 0; @@ -1787,6 +1740,7 @@ static int qlcnic_sriov_vf_idc_failed_state(struct qlcnic_adapter *adapter) static int qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) { + struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; struct qlc_83xx_idc *idc = &adapter->ahw->idc; dev_info(&adapter->pdev->dev, "Device is in quiescent state\n"); @@ -1794,7 +1748,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) set_bit(__QLCNIC_RESETTING, &adapter->state); adapter->tx_timeo_cnt = 0; adapter->reset_ctx_cnt = 0; - clear_bit(QLC_83XX_MBX_READY, &idc->status); + clear_bit(QLC_83XX_MBX_READY, &mbx->status); qlcnic_sriov_vf_detach(adapter); } @@ -1803,6 +1757,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) { + struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; struct qlc_83xx_idc *idc = &adapter->ahw->idc; u8 func = adapter->ahw->pci_func; @@ -1812,7 +1767,7 @@ static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) set_bit(__QLCNIC_RESETTING, &adapter->state); adapter->tx_timeo_cnt = 0; adapter->reset_ctx_cnt = 0; - clear_bit(QLC_83XX_MBX_READY, &idc->status); + clear_bit(QLC_83XX_MBX_READY, &mbx->status); qlcnic_sriov_vf_detach(adapter); } return 0; @@ -1990,7 +1945,7 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) int err; set_bit(QLC_83XX_MODULE_LOADED, &idc->status); - qlcnic_83xx_enable_mbx_intrpt(adapter); + qlcnic_83xx_enable_mbx_interrupt(adapter); err = qlcnic_sriov_cfg_bc_intr(adapter, 1); if (err) return err; |