aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/qlogic/qlcnic
diff options
context:
space:
mode:
authorRajesh Borundia <rajesh.borundia@qlogic.com>2013-06-22 04:12:06 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-23 21:29:59 -0400
commit486a5bc77a4a83d29b72b17fde229e45a2428194 (patch)
treee722558c9c9f650cb0df41ccf884396aadff6a7b /drivers/net/ethernet/qlogic/qlcnic
parent8af3f33db05c6d0146ad14905145a5c923770856 (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/ethernet/qlogic/qlcnic')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h14
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c53
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h6
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c17
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c23
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c51
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c66
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c53
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
1805static 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
1812static inline int __qlcnic_resume(struct qlcnic_adapter *adapter)
1813{
1814 return adapter->nic_ops->resume(adapter);
1815}
1816
1803static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) 1817static 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
191void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) 193void 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
3399int 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
3421int 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 *);
628void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); 628void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
629void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); 629void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
630void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); 630void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
631int qlcnic_83xx_shutdown(struct pci_dev *);
632int qlcnic_83xx_resume(struct qlcnic_adapter *);
633int qlcnic_83xx_idc_init(struct qlcnic_adapter *);
634int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *);
635int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *);
636int 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
609static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) 609int 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
1138static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) 1138int 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
1555int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev) 1555int 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
42static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) 42int 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
222int 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
1581int 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
1610int 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 *);
199void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); 199void qlcnic_82xx_napi_enable(struct qlcnic_adapter *);
200void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); 200void qlcnic_82xx_napi_disable(struct qlcnic_adapter *);
201void qlcnic_82xx_napi_del(struct qlcnic_adapter *); 201void qlcnic_82xx_napi_del(struct qlcnic_adapter *);
202int qlcnic_82xx_shutdown(struct pci_dev *);
203int qlcnic_82xx_resume(struct qlcnic_adapter *);
204void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed);
205void 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);
59static void qlcnic_tx_timeout(struct net_device *netdev); 59static void qlcnic_tx_timeout(struct net_device *netdev);
60static void qlcnic_attach_work(struct work_struct *work); 60static void qlcnic_attach_work(struct work_struct *work);
61static void qlcnic_fwinit_work(struct work_struct *work); 61static void qlcnic_fwinit_work(struct work_struct *work);
62static void qlcnic_fw_poll_work(struct work_struct *work);
63#ifdef CONFIG_NET_POLL_CONTROLLER 62#ifdef CONFIG_NET_POLL_CONTROLLER
64static void qlcnic_poll_controller(struct net_device *netdev); 63static void qlcnic_poll_controller(struct net_device *netdev);
65#endif 64#endif
66 65
67static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); 66static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
68static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
69static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); 67static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
70 68
71static irqreturn_t qlcnic_tmp_intr(int irq, void *data); 69static 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}
2280static 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
2312static void qlcnic_shutdown(struct pci_dev *pdev) 2281static 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
2321static int 2290static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state)
2322qlcnic_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
2334static int 2302static int qlcnic_resume(struct pci_dev *pdev)
2335qlcnic_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 }
2362done:
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
2704static void 2654void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed)
2705qlcnic_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
3216static void 3165void qlcnic_fw_poll_work(struct work_struct *work)
3217qlcnic_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 *,
195int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, 195int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
196 struct qlcnic_info *, u16); 196 struct qlcnic_info *, u16);
197int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); 197int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
198int qlcnic_sriov_vf_shutdown(struct pci_dev *);
199int qlcnic_sriov_vf_resume(struct qlcnic_adapter *);
198 200
199static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter) 201static 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
1960int 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
1984int 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}