diff options
author | Rajesh Borundia <rajesh.borundia@qlogic.com> | 2013-06-22 04:12:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-23 21:29:59 -0400 |
commit | 486a5bc77a4a83d29b72b17fde229e45a2428194 (patch) | |
tree | e722558c9c9f650cb0df41ccf884396aadff6a7b /drivers/net | |
parent | 8af3f33db05c6d0146ad14905145a5c923770856 (diff) |
qlcnic: Add support for 83xx suspend and resume.
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 53 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 51 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 66 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 53 |
10 files changed, 225 insertions, 64 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 955dd858464a..a89e322be28e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1596,6 +1596,8 @@ struct qlcnic_nic_template { | |||
1596 | void (*napi_del)(struct qlcnic_adapter *); | 1596 | void (*napi_del)(struct qlcnic_adapter *); |
1597 | void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); | 1597 | void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); |
1598 | irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); | 1598 | irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); |
1599 | int (*shutdown)(struct pci_dev *); | ||
1600 | int (*resume)(struct qlcnic_adapter *); | ||
1599 | }; | 1601 | }; |
1600 | 1602 | ||
1601 | /* Adapter hardware abstraction */ | 1603 | /* Adapter hardware abstraction */ |
@@ -1800,6 +1802,18 @@ static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter) | |||
1800 | adapter->ahw->hw_ops->napi_enable(adapter); | 1802 | adapter->ahw->hw_ops->napi_enable(adapter); |
1801 | } | 1803 | } |
1802 | 1804 | ||
1805 | static inline int __qlcnic_shutdown(struct pci_dev *pdev) | ||
1806 | { | ||
1807 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
1808 | |||
1809 | return adapter->nic_ops->shutdown(pdev); | ||
1810 | } | ||
1811 | |||
1812 | static inline int __qlcnic_resume(struct qlcnic_adapter *adapter) | ||
1813 | { | ||
1814 | return adapter->nic_ops->resume(adapter); | ||
1815 | } | ||
1816 | |||
1803 | static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) | 1817 | static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) |
1804 | { | 1818 | { |
1805 | adapter->ahw->hw_ops->napi_disable(adapter); | 1819 | adapter->ahw->hw_ops->napi_disable(adapter); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 1938812bb0e2..0913c623a67e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -186,6 +186,8 @@ static struct qlcnic_nic_template qlcnic_83xx_ops = { | |||
186 | .napi_del = qlcnic_83xx_napi_del, | 186 | .napi_del = qlcnic_83xx_napi_del, |
187 | .config_ipaddr = qlcnic_83xx_config_ipaddr, | 187 | .config_ipaddr = qlcnic_83xx_config_ipaddr, |
188 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, | 188 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, |
189 | .shutdown = qlcnic_83xx_shutdown, | ||
190 | .resume = qlcnic_83xx_resume, | ||
189 | }; | 191 | }; |
190 | 192 | ||
191 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) | 193 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) |
@@ -3393,3 +3395,54 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter) | |||
3393 | } | 3395 | } |
3394 | return 0; | 3396 | return 0; |
3395 | } | 3397 | } |
3398 | |||
3399 | int qlcnic_83xx_shutdown(struct pci_dev *pdev) | ||
3400 | { | ||
3401 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3402 | struct net_device *netdev = adapter->netdev; | ||
3403 | int retval; | ||
3404 | |||
3405 | netif_device_detach(netdev); | ||
3406 | qlcnic_cancel_idc_work(adapter); | ||
3407 | |||
3408 | if (netif_running(netdev)) | ||
3409 | qlcnic_down(adapter, netdev); | ||
3410 | |||
3411 | qlcnic_83xx_disable_mbx_intr(adapter); | ||
3412 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
3413 | |||
3414 | retval = pci_save_state(pdev); | ||
3415 | if (retval) | ||
3416 | return retval; | ||
3417 | |||
3418 | return 0; | ||
3419 | } | ||
3420 | |||
3421 | int qlcnic_83xx_resume(struct qlcnic_adapter *adapter) | ||
3422 | { | ||
3423 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
3424 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
3425 | int err = 0; | ||
3426 | |||
3427 | err = qlcnic_83xx_idc_init(adapter); | ||
3428 | if (err) | ||
3429 | return err; | ||
3430 | |||
3431 | if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) { | ||
3432 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) { | ||
3433 | qlcnic_83xx_set_vnic_opmode(adapter); | ||
3434 | } else { | ||
3435 | err = qlcnic_83xx_check_vnic_state(adapter); | ||
3436 | if (err) | ||
3437 | return err; | ||
3438 | } | ||
3439 | } | ||
3440 | |||
3441 | err = qlcnic_83xx_idc_reattach_driver(adapter); | ||
3442 | if (err) | ||
3443 | return err; | ||
3444 | |||
3445 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, | ||
3446 | idc->delay); | ||
3447 | return err; | ||
3448 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index e356ee87a9a6..2548d1403d75 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -628,4 +628,10 @@ u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *); | |||
628 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); | 628 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); |
629 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); | 629 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); |
630 | void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); | 630 | void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); |
631 | int qlcnic_83xx_shutdown(struct pci_dev *); | ||
632 | int qlcnic_83xx_resume(struct qlcnic_adapter *); | ||
633 | int qlcnic_83xx_idc_init(struct qlcnic_adapter *); | ||
634 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); | ||
635 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); | ||
636 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); | ||
631 | #endif | 637 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index e2d04d5cb9b0..f41dfab1e9a3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -606,7 +606,7 @@ static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter) | |||
606 | return 0; | 606 | return 0; |
607 | } | 607 | } |
608 | 608 | ||
609 | static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | 609 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) |
610 | { | 610 | { |
611 | int err; | 611 | int err; |
612 | 612 | ||
@@ -1135,7 +1135,7 @@ qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter) | |||
1135 | return 0; | 1135 | return 0; |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) | 1138 | int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) |
1139 | { | 1139 | { |
1140 | int ret = -EIO; | 1140 | int ret = -EIO; |
1141 | 1141 | ||
@@ -1554,9 +1554,18 @@ static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev) | |||
1554 | 1554 | ||
1555 | int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev) | 1555 | int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev) |
1556 | { | 1556 | { |
1557 | u8 *p_buff; | ||
1558 | u32 addr, count; | ||
1559 | struct qlcnic_hardware_context *ahw = p_dev->ahw; | 1557 | struct qlcnic_hardware_context *ahw = p_dev->ahw; |
1558 | u32 addr, count, prev_ver, curr_ver; | ||
1559 | u8 *p_buff; | ||
1560 | |||
1561 | if (ahw->reset.buff != NULL) { | ||
1562 | prev_ver = p_dev->fw_version; | ||
1563 | curr_ver = qlcnic_83xx_get_fw_version(p_dev); | ||
1564 | if (curr_ver > prev_ver) | ||
1565 | kfree(ahw->reset.buff); | ||
1566 | else | ||
1567 | return 0; | ||
1568 | } | ||
1560 | 1569 | ||
1561 | ahw->reset.seq_error = 0; | 1570 | ahw->reset.seq_error = 0; |
1562 | ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL); | 1571 | ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index b5054e1d1710..599d1fda52f2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | |||
@@ -39,7 +39,7 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock) | |||
39 | return 0; | 39 | return 0; |
40 | } | 40 | } |
41 | 41 | ||
42 | static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) | 42 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) |
43 | { | 43 | { |
44 | u8 id; | 44 | u8 id; |
45 | int ret = -EBUSY; | 45 | int ret = -EBUSY; |
@@ -218,3 +218,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) | |||
218 | 218 | ||
219 | return 0; | 219 | return 0; |
220 | } | 220 | } |
221 | |||
222 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) | ||
223 | { | ||
224 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
225 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
226 | u32 state; | ||
227 | |||
228 | state = QLCRDX(ahw, QLC_83XX_VNIC_STATE); | ||
229 | while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) { | ||
230 | msleep(1000); | ||
231 | state = QLCRDX(ahw, QLC_83XX_VNIC_STATE); | ||
232 | } | ||
233 | |||
234 | if (!idc->vnic_wait_limit) { | ||
235 | dev_err(&adapter->pdev->dev, | ||
236 | "vNIC mode not operational, state check timed out.\n"); | ||
237 | return -EIO; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 9fcbfd449ac5..5b5d2edf125d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -1577,3 +1577,54 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *adapter) | |||
1577 | { | 1577 | { |
1578 | qlcnic_pcie_sem_unlock(adapter, 5); | 1578 | qlcnic_pcie_sem_unlock(adapter, 5); |
1579 | } | 1579 | } |
1580 | |||
1581 | int qlcnic_82xx_shutdown(struct pci_dev *pdev) | ||
1582 | { | ||
1583 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
1584 | struct net_device *netdev = adapter->netdev; | ||
1585 | int retval; | ||
1586 | |||
1587 | netif_device_detach(netdev); | ||
1588 | |||
1589 | qlcnic_cancel_idc_work(adapter); | ||
1590 | |||
1591 | if (netif_running(netdev)) | ||
1592 | qlcnic_down(adapter, netdev); | ||
1593 | |||
1594 | qlcnic_clr_all_drv_state(adapter, 0); | ||
1595 | |||
1596 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
1597 | |||
1598 | retval = pci_save_state(pdev); | ||
1599 | if (retval) | ||
1600 | return retval; | ||
1601 | |||
1602 | if (qlcnic_wol_supported(adapter)) { | ||
1603 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
1604 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
1605 | } | ||
1606 | |||
1607 | return 0; | ||
1608 | } | ||
1609 | |||
1610 | int qlcnic_82xx_resume(struct qlcnic_adapter *adapter) | ||
1611 | { | ||
1612 | struct net_device *netdev = adapter->netdev; | ||
1613 | int err; | ||
1614 | |||
1615 | err = qlcnic_start_firmware(adapter); | ||
1616 | if (err) { | ||
1617 | dev_err(&adapter->pdev->dev, "failed to start firmware\n"); | ||
1618 | return err; | ||
1619 | } | ||
1620 | |||
1621 | if (netif_running(netdev)) { | ||
1622 | err = qlcnic_up(adapter, netdev); | ||
1623 | if (!err) | ||
1624 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | ||
1625 | } | ||
1626 | |||
1627 | netif_device_attach(netdev); | ||
1628 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); | ||
1629 | return err; | ||
1630 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index b190c8495a85..2c22504f57aa 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -199,4 +199,8 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *); | |||
199 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); | 199 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); |
200 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); | 200 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); |
201 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *); | 201 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *); |
202 | int qlcnic_82xx_shutdown(struct pci_dev *); | ||
203 | int qlcnic_82xx_resume(struct qlcnic_adapter *); | ||
204 | void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed); | ||
205 | void qlcnic_fw_poll_work(struct work_struct *work); | ||
202 | #endif /* __QLCNIC_HW_H_ */ | 206 | #endif /* __QLCNIC_HW_H_ */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 0d7a4fd9975c..4528f8ec333b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -59,13 +59,11 @@ static int qlcnic_close(struct net_device *netdev); | |||
59 | static void qlcnic_tx_timeout(struct net_device *netdev); | 59 | static void qlcnic_tx_timeout(struct net_device *netdev); |
60 | static void qlcnic_attach_work(struct work_struct *work); | 60 | static void qlcnic_attach_work(struct work_struct *work); |
61 | static void qlcnic_fwinit_work(struct work_struct *work); | 61 | static void qlcnic_fwinit_work(struct work_struct *work); |
62 | static void qlcnic_fw_poll_work(struct work_struct *work); | ||
63 | #ifdef CONFIG_NET_POLL_CONTROLLER | 62 | #ifdef CONFIG_NET_POLL_CONTROLLER |
64 | static void qlcnic_poll_controller(struct net_device *netdev); | 63 | static void qlcnic_poll_controller(struct net_device *netdev); |
65 | #endif | 64 | #endif |
66 | 65 | ||
67 | static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); | 66 | static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); |
68 | static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); | ||
69 | static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); | 67 | static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); |
70 | 68 | ||
71 | static irqreturn_t qlcnic_tmp_intr(int irq, void *data); | 69 | static irqreturn_t qlcnic_tmp_intr(int irq, void *data); |
@@ -469,6 +467,8 @@ static struct qlcnic_nic_template qlcnic_ops = { | |||
469 | .napi_add = qlcnic_82xx_napi_add, | 467 | .napi_add = qlcnic_82xx_napi_add, |
470 | .napi_del = qlcnic_82xx_napi_del, | 468 | .napi_del = qlcnic_82xx_napi_del, |
471 | .config_ipaddr = qlcnic_82xx_config_ipaddr, | 469 | .config_ipaddr = qlcnic_82xx_config_ipaddr, |
470 | .shutdown = qlcnic_82xx_shutdown, | ||
471 | .resume = qlcnic_82xx_resume, | ||
472 | .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, | 472 | .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, |
473 | }; | 473 | }; |
474 | 474 | ||
@@ -2277,37 +2277,6 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
2277 | kfree(ahw); | 2277 | kfree(ahw); |
2278 | free_netdev(netdev); | 2278 | free_netdev(netdev); |
2279 | } | 2279 | } |
2280 | static int __qlcnic_shutdown(struct pci_dev *pdev) | ||
2281 | { | ||
2282 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
2283 | struct net_device *netdev = adapter->netdev; | ||
2284 | int retval; | ||
2285 | |||
2286 | netif_device_detach(netdev); | ||
2287 | |||
2288 | qlcnic_cancel_idc_work(adapter); | ||
2289 | |||
2290 | if (netif_running(netdev)) | ||
2291 | qlcnic_down(adapter, netdev); | ||
2292 | |||
2293 | qlcnic_sriov_cleanup(adapter); | ||
2294 | if (qlcnic_82xx_check(adapter)) | ||
2295 | qlcnic_clr_all_drv_state(adapter, 0); | ||
2296 | |||
2297 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
2298 | |||
2299 | retval = pci_save_state(pdev); | ||
2300 | if (retval) | ||
2301 | return retval; | ||
2302 | if (qlcnic_82xx_check(adapter)) { | ||
2303 | if (qlcnic_wol_supported(adapter)) { | ||
2304 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
2305 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
2306 | } | ||
2307 | } | ||
2308 | |||
2309 | return 0; | ||
2310 | } | ||
2311 | 2280 | ||
2312 | static void qlcnic_shutdown(struct pci_dev *pdev) | 2281 | static void qlcnic_shutdown(struct pci_dev *pdev) |
2313 | { | 2282 | { |
@@ -2318,8 +2287,7 @@ static void qlcnic_shutdown(struct pci_dev *pdev) | |||
2318 | } | 2287 | } |
2319 | 2288 | ||
2320 | #ifdef CONFIG_PM | 2289 | #ifdef CONFIG_PM |
2321 | static int | 2290 | static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) |
2322 | qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) | ||
2323 | { | 2291 | { |
2324 | int retval; | 2292 | int retval; |
2325 | 2293 | ||
@@ -2331,11 +2299,9 @@ qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2331 | return 0; | 2299 | return 0; |
2332 | } | 2300 | } |
2333 | 2301 | ||
2334 | static int | 2302 | static int qlcnic_resume(struct pci_dev *pdev) |
2335 | qlcnic_resume(struct pci_dev *pdev) | ||
2336 | { | 2303 | { |
2337 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 2304 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
2338 | struct net_device *netdev = adapter->netdev; | ||
2339 | int err; | 2305 | int err; |
2340 | 2306 | ||
2341 | err = pci_enable_device(pdev); | 2307 | err = pci_enable_device(pdev); |
@@ -2346,23 +2312,7 @@ qlcnic_resume(struct pci_dev *pdev) | |||
2346 | pci_set_master(pdev); | 2312 | pci_set_master(pdev); |
2347 | pci_restore_state(pdev); | 2313 | pci_restore_state(pdev); |
2348 | 2314 | ||
2349 | err = qlcnic_start_firmware(adapter); | 2315 | return __qlcnic_resume(adapter); |
2350 | if (err) { | ||
2351 | dev_err(&pdev->dev, "failed to start firmware\n"); | ||
2352 | return err; | ||
2353 | } | ||
2354 | |||
2355 | if (netif_running(netdev)) { | ||
2356 | err = qlcnic_up(adapter, netdev); | ||
2357 | if (err) | ||
2358 | goto done; | ||
2359 | |||
2360 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | ||
2361 | } | ||
2362 | done: | ||
2363 | netif_device_attach(netdev); | ||
2364 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); | ||
2365 | return 0; | ||
2366 | } | 2316 | } |
2367 | #endif | 2317 | #endif |
2368 | 2318 | ||
@@ -2701,8 +2651,7 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) | |||
2701 | return 0; | 2651 | return 0; |
2702 | } | 2652 | } |
2703 | 2653 | ||
2704 | static void | 2654 | void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) |
2705 | qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) | ||
2706 | { | 2655 | { |
2707 | u32 val; | 2656 | u32 val; |
2708 | 2657 | ||
@@ -3213,8 +3162,7 @@ detach: | |||
3213 | return 1; | 3162 | return 1; |
3214 | } | 3163 | } |
3215 | 3164 | ||
3216 | static void | 3165 | void qlcnic_fw_poll_work(struct work_struct *work) |
3217 | qlcnic_fw_poll_work(struct work_struct *work) | ||
3218 | { | 3166 | { |
3219 | struct qlcnic_adapter *adapter = container_of(work, | 3167 | struct qlcnic_adapter *adapter = container_of(work, |
3220 | struct qlcnic_adapter, fw_work.work); | 3168 | struct qlcnic_adapter, fw_work.work); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index 9176cb015732..0daf660e12a1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | |||
@@ -195,6 +195,8 @@ int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *, | |||
195 | int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, | 195 | int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, |
196 | struct qlcnic_info *, u16); | 196 | struct qlcnic_info *, u16); |
197 | int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); | 197 | int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); |
198 | int qlcnic_sriov_vf_shutdown(struct pci_dev *); | ||
199 | int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); | ||
198 | 200 | ||
199 | static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter) | 201 | static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter) |
200 | { | 202 | { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index bcd200eff981..d55624993b04 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -76,6 +76,8 @@ static struct qlcnic_nic_template qlcnic_sriov_vf_ops = { | |||
76 | .cancel_idc_work = qlcnic_sriov_vf_cancel_fw_work, | 76 | .cancel_idc_work = qlcnic_sriov_vf_cancel_fw_work, |
77 | .napi_add = qlcnic_83xx_napi_add, | 77 | .napi_add = qlcnic_83xx_napi_add, |
78 | .napi_del = qlcnic_83xx_napi_del, | 78 | .napi_del = qlcnic_83xx_napi_del, |
79 | .shutdown = qlcnic_sriov_vf_shutdown, | ||
80 | .resume = qlcnic_sriov_vf_resume, | ||
79 | .config_ipaddr = qlcnic_83xx_config_ipaddr, | 81 | .config_ipaddr = qlcnic_83xx_config_ipaddr, |
80 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, | 82 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, |
81 | }; | 83 | }; |
@@ -1954,3 +1956,54 @@ static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter) | |||
1954 | kfree(cur); | 1956 | kfree(cur); |
1955 | } | 1957 | } |
1956 | } | 1958 | } |
1959 | |||
1960 | int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev) | ||
1961 | { | ||
1962 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
1963 | struct net_device *netdev = adapter->netdev; | ||
1964 | int retval; | ||
1965 | |||
1966 | netif_device_detach(netdev); | ||
1967 | qlcnic_cancel_idc_work(adapter); | ||
1968 | |||
1969 | if (netif_running(netdev)) | ||
1970 | qlcnic_down(adapter, netdev); | ||
1971 | |||
1972 | qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM); | ||
1973 | qlcnic_sriov_cfg_bc_intr(adapter, 0); | ||
1974 | qlcnic_83xx_disable_mbx_intr(adapter); | ||
1975 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
1976 | |||
1977 | retval = pci_save_state(pdev); | ||
1978 | if (retval) | ||
1979 | return retval; | ||
1980 | |||
1981 | return 0; | ||
1982 | } | ||
1983 | |||
1984 | int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) | ||
1985 | { | ||
1986 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; | ||
1987 | struct net_device *netdev = adapter->netdev; | ||
1988 | int err; | ||
1989 | |||
1990 | set_bit(QLC_83XX_MODULE_LOADED, &idc->status); | ||
1991 | qlcnic_83xx_enable_mbx_intrpt(adapter); | ||
1992 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); | ||
1993 | if (err) | ||
1994 | return err; | ||
1995 | |||
1996 | err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT); | ||
1997 | if (!err) { | ||
1998 | if (netif_running(netdev)) { | ||
1999 | err = qlcnic_up(adapter, netdev); | ||
2000 | if (!err) | ||
2001 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | ||
2002 | } | ||
2003 | } | ||
2004 | |||
2005 | netif_device_attach(netdev); | ||
2006 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, | ||
2007 | idc->delay); | ||
2008 | return err; | ||
2009 | } | ||