]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
qlcnic: Replace poll mode mailbox interface with interrupt based mailbox interface
[linux.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_sriov_common.c
index d9c6ae5e0d3bbf25298ba1a7d571f76f075d6349..e58c1d4fa01f1614025d24a6de6b0348ccc4b512 100644 (file)
@@ -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, &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);
-
-       if (qlcnic_sriov_pf_check(adapter))
-               mbx_cmd |= (pci_func << 5);
+       struct qlcnic_mailbox *mbx = ahw->mailbox;
+       struct qlcnic_cmd_args cmd;
+       unsigned long timeout;
+       int err;
 
-       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));
+       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;
+
+       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)
@@ -522,8 +464,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);
@@ -637,8 +579,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;
@@ -1395,6 +1335,7 @@ 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 +1352,7 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
                goto cleanup_transaction;
 
 retry:
-       if (!test_bit(QLC_83XX_MBX_READY, &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 +1395,7 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
        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:
@@ -1657,8 +1598,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 +1645,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 +1656,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 +1681,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 +1731,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 +1739,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 +1748,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 +1758,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;