Skip to content

Commit 90869dd

Browse files
caildavem330
authored andcommitted
net: aquantia: Implement pci shutdown callback
We should close link and all NIC operations during shutdown. On some systems graceful reboot never closes NIC interface on its own, but only indicates pci device shutdown. Without explicit handler, NIC rx rings continued to transfer DMA data into prepared buffers while CPU rebooted already. That caused memory corruptions on soft reboot. Signed-off-by: Igor Russkikh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3e9a545 commit 90869dd

File tree

3 files changed

+36
-0
lines changed

3 files changed

+36
-0
lines changed

drivers/net/ethernet/aquantia/atlantic/aq_nic.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,3 +939,23 @@ int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg)
939939
out:
940940
return err;
941941
}
942+
943+
void aq_nic_shutdown(struct aq_nic_s *self)
944+
{
945+
int err = 0;
946+
947+
if (!self->ndev)
948+
return;
949+
950+
rtnl_lock();
951+
952+
netif_device_detach(self->ndev);
953+
954+
err = aq_nic_stop(self);
955+
if (err < 0)
956+
goto err_exit;
957+
aq_nic_deinit(self);
958+
959+
err_exit:
960+
rtnl_unlock();
961+
}

drivers/net/ethernet/aquantia/atlantic/aq_nic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,6 @@ struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
118118
u32 aq_nic_get_fw_version(struct aq_nic_s *self);
119119
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
120120
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
121+
void aq_nic_shutdown(struct aq_nic_s *self);
121122

122123
#endif /* AQ_NIC_H */

drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ static void aq_pci_remove(struct pci_dev *pdev)
323323
pci_disable_device(pdev);
324324
}
325325

326+
static void aq_pci_shutdown(struct pci_dev *pdev)
327+
{
328+
struct aq_nic_s *self = pci_get_drvdata(pdev);
329+
330+
aq_nic_shutdown(self);
331+
332+
pci_disable_device(pdev);
333+
334+
if (system_state == SYSTEM_POWER_OFF) {
335+
pci_wake_from_d3(pdev, false);
336+
pci_set_power_state(pdev, PCI_D3hot);
337+
}
338+
}
339+
326340
static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg)
327341
{
328342
struct aq_nic_s *self = pci_get_drvdata(pdev);
@@ -345,6 +359,7 @@ static struct pci_driver aq_pci_ops = {
345359
.remove = aq_pci_remove,
346360
.suspend = aq_pci_suspend,
347361
.resume = aq_pci_resume,
362+
.shutdown = aq_pci_shutdown,
348363
};
349364

350365
module_pci_driver(aq_pci_ops);

0 commit comments

Comments
 (0)