]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
qlcnic: Replace poll mode mailbox interface with interrupt based mailbox interface
[karo-tx-linux.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_83xx_init.c
index 0c5110c74311bd35790a38d6d9de56a8fc61de8d..bb7c649bfe53d75c242397e7437225af39ab3b0c 100644 (file)
@@ -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;
 }