o Implement shutdown and resume handlers for 83xx.
o Refactor 82xx shutdown and resume handlers.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
void (*napi_del)(struct qlcnic_adapter *);
void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int);
irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *);
+ int (*shutdown)(struct pci_dev *);
+ int (*resume)(struct qlcnic_adapter *);
};
/* Adapter hardware abstraction */
adapter->ahw->hw_ops->napi_enable(adapter);
}
+static inline int __qlcnic_shutdown(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+
+ return adapter->nic_ops->shutdown(pdev);
+}
+
+static inline int __qlcnic_resume(struct qlcnic_adapter *adapter)
+{
+ return adapter->nic_ops->resume(adapter);
+}
+
static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->napi_disable(adapter);
.napi_del = qlcnic_83xx_napi_del,
.config_ipaddr = qlcnic_83xx_config_ipaddr,
.clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
+ .shutdown = qlcnic_83xx_shutdown,
+ .resume = qlcnic_83xx_resume,
};
void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw)
}
return 0;
}
+
+int qlcnic_83xx_shutdown(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+ int retval;
+
+ netif_device_detach(netdev);
+ qlcnic_cancel_idc_work(adapter);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_83xx_disable_mbx_intr(adapter);
+ cancel_delayed_work_sync(&adapter->idc_aen_work);
+
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+
+ return 0;
+}
+
+int qlcnic_83xx_resume(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlc_83xx_idc *idc = &ahw->idc;
+ int err = 0;
+
+ err = qlcnic_83xx_idc_init(adapter);
+ if (err)
+ return err;
+
+ if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) {
+ if (ahw->op_mode == QLCNIC_MGMT_FUNC) {
+ qlcnic_83xx_set_vnic_opmode(adapter);
+ } else {
+ err = qlcnic_83xx_check_vnic_state(adapter);
+ if (err)
+ return err;
+ }
+ }
+
+ err = qlcnic_83xx_idc_reattach_driver(adapter);
+ if (err)
+ return err;
+
+ qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state,
+ idc->delay);
+ return err;
+}
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 *);
+int qlcnic_83xx_shutdown(struct pci_dev *);
+int qlcnic_83xx_resume(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *);
+int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *);
+int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *);
+int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *);
#endif
return 0;
}
-static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
{
int err;
return 0;
}
-static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter)
{
int ret = -EIO;
int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev)
{
- u8 *p_buff;
- u32 addr, count;
struct qlcnic_hardware_context *ahw = p_dev->ahw;
+ u32 addr, count, prev_ver, curr_ver;
+ u8 *p_buff;
+
+ if (ahw->reset.buff != NULL) {
+ prev_ver = p_dev->fw_version;
+ curr_ver = qlcnic_83xx_get_fw_version(p_dev);
+ if (curr_ver > prev_ver)
+ kfree(ahw->reset.buff);
+ else
+ return 0;
+ }
ahw->reset.seq_error = 0;
ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
return 0;
}
-static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
+int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
{
u8 id;
int ret = -EBUSY;
return 0;
}
+
+int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_hardware_context *ahw = adapter->ahw;
+ struct qlc_83xx_idc *idc = &ahw->idc;
+ u32 state;
+
+ state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
+ while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) {
+ msleep(1000);
+ state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
+ }
+
+ if (!idc->vnic_wait_limit) {
+ dev_err(&adapter->pdev->dev,
+ "vNIC mode not operational, state check timed out.\n");
+ return -EIO;
+ }
+
+ return 0;
+}
{
qlcnic_pcie_sem_unlock(adapter, 5);
}
+
+int qlcnic_82xx_shutdown(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+ int retval;
+
+ netif_device_detach(netdev);
+
+ qlcnic_cancel_idc_work(adapter);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_clr_all_drv_state(adapter, 0);
+
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+
+ if (qlcnic_wol_supported(adapter)) {
+ pci_enable_wake(pdev, PCI_D3cold, 1);
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ }
+
+ return 0;
+}
+
+int qlcnic_82xx_resume(struct qlcnic_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int err;
+
+ err = qlcnic_start_firmware(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev, "failed to start firmware\n");
+ return err;
+ }
+
+ if (netif_running(netdev)) {
+ err = qlcnic_up(adapter, netdev);
+ if (!err)
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+ }
+
+ netif_device_attach(netdev);
+ qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+ return err;
+}
void qlcnic_82xx_napi_enable(struct qlcnic_adapter *);
void qlcnic_82xx_napi_disable(struct qlcnic_adapter *);
void qlcnic_82xx_napi_del(struct qlcnic_adapter *);
+int qlcnic_82xx_shutdown(struct pci_dev *);
+int qlcnic_82xx_resume(struct qlcnic_adapter *);
+void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed);
+void qlcnic_fw_poll_work(struct work_struct *work);
#endif /* __QLCNIC_HW_H_ */
static void qlcnic_tx_timeout(struct net_device *netdev);
static void qlcnic_attach_work(struct work_struct *work);
static void qlcnic_fwinit_work(struct work_struct *work);
-static void qlcnic_fw_poll_work(struct work_struct *work);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void qlcnic_poll_controller(struct net_device *netdev);
#endif
static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
-static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
static irqreturn_t qlcnic_tmp_intr(int irq, void *data);
.napi_add = qlcnic_82xx_napi_add,
.napi_del = qlcnic_82xx_napi_del,
.config_ipaddr = qlcnic_82xx_config_ipaddr,
+ .shutdown = qlcnic_82xx_shutdown,
+ .resume = qlcnic_82xx_resume,
.clear_legacy_intr = qlcnic_82xx_clear_legacy_intr,
};
kfree(ahw);
free_netdev(netdev);
}
-static int __qlcnic_shutdown(struct pci_dev *pdev)
-{
- struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
- struct net_device *netdev = adapter->netdev;
- int retval;
-
- netif_device_detach(netdev);
-
- qlcnic_cancel_idc_work(adapter);
-
- if (netif_running(netdev))
- qlcnic_down(adapter, netdev);
-
- qlcnic_sriov_cleanup(adapter);
- if (qlcnic_82xx_check(adapter))
- qlcnic_clr_all_drv_state(adapter, 0);
-
- clear_bit(__QLCNIC_RESETTING, &adapter->state);
-
- retval = pci_save_state(pdev);
- if (retval)
- return retval;
- if (qlcnic_82xx_check(adapter)) {
- if (qlcnic_wol_supported(adapter)) {
- pci_enable_wake(pdev, PCI_D3cold, 1);
- pci_enable_wake(pdev, PCI_D3hot, 1);
- }
- }
-
- return 0;
-}
static void qlcnic_shutdown(struct pci_dev *pdev)
{
}
#ifdef CONFIG_PM
-static int
-qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
+static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
{
int retval;
return 0;
}
-static int
-qlcnic_resume(struct pci_dev *pdev)
+static int qlcnic_resume(struct pci_dev *pdev)
{
struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
- struct net_device *netdev = adapter->netdev;
int err;
err = pci_enable_device(pdev);
pci_set_master(pdev);
pci_restore_state(pdev);
- err = qlcnic_start_firmware(adapter);
- if (err) {
- dev_err(&pdev->dev, "failed to start firmware\n");
- return err;
- }
-
- if (netif_running(netdev)) {
- err = qlcnic_up(adapter, netdev);
- if (err)
- goto done;
-
- qlcnic_restore_indev_addr(netdev, NETDEV_UP);
- }
-done:
- netif_device_attach(netdev);
- qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
- return 0;
+ return __qlcnic_resume(adapter);
}
#endif
return 0;
}
-static void
-qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
+void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
{
u32 val;
return 1;
}
-static void
-qlcnic_fw_poll_work(struct work_struct *work)
+void qlcnic_fw_poll_work(struct work_struct *work)
{
struct qlcnic_adapter *adapter = container_of(work,
struct qlcnic_adapter, fw_work.work);
int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
struct qlcnic_info *, u16);
int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
+int qlcnic_sriov_vf_shutdown(struct pci_dev *);
+int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
{
.cancel_idc_work = qlcnic_sriov_vf_cancel_fw_work,
.napi_add = qlcnic_83xx_napi_add,
.napi_del = qlcnic_83xx_napi_del,
+ .shutdown = qlcnic_sriov_vf_shutdown,
+ .resume = qlcnic_sriov_vf_resume,
.config_ipaddr = qlcnic_83xx_config_ipaddr,
.clear_legacy_intr = qlcnic_83xx_clear_legacy_intr,
};
kfree(cur);
}
}
+
+int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+ int retval;
+
+ netif_device_detach(netdev);
+ qlcnic_cancel_idc_work(adapter);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM);
+ qlcnic_sriov_cfg_bc_intr(adapter, 0);
+ qlcnic_83xx_disable_mbx_intr(adapter);
+ cancel_delayed_work_sync(&adapter->idc_aen_work);
+
+ retval = pci_save_state(pdev);
+ if (retval)
+ return retval;
+
+ return 0;
+}
+
+int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter)
+{
+ struct qlc_83xx_idc *idc = &adapter->ahw->idc;
+ struct net_device *netdev = adapter->netdev;
+ int err;
+
+ set_bit(QLC_83XX_MODULE_LOADED, &idc->status);
+ qlcnic_83xx_enable_mbx_intrpt(adapter);
+ err = qlcnic_sriov_cfg_bc_intr(adapter, 1);
+ if (err)
+ return err;
+
+ err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT);
+ if (!err) {
+ if (netif_running(netdev)) {
+ err = qlcnic_up(adapter, netdev);
+ if (!err)
+ qlcnic_restore_indev_addr(netdev, NETDEV_UP);
+ }
+ }
+
+ netif_device_attach(netdev);
+ qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state,
+ idc->delay);
+ return err;
+}