u32 page_alloc_fail; /* count of page alloc fails */
        u32 dma_mapping_error; /* count of dma mapping errors */
        u32 stats_report_trigger_cnt; /* count of device-requested stats-reports since last reset */
+       u32 suspend_cnt; /* count of times suspended */
+       u32 resume_cnt; /* count of times resumed */
        struct workqueue_struct *gve_wq;
        struct work_struct service_task;
        struct work_struct stats_report_task;
 
        /* Gvnic device link speed from hypervisor. */
        u64 link_speed;
+       bool up_before_suspend; /* True if dev was up before suspend */
 
        struct gve_options_dqo_rda options_dqo_rda;
        struct gve_ptype_lut *ptype_lut_dqo;
 
        pci_disable_device(pdev);
 }
 
+static void gve_shutdown(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct gve_priv *priv = netdev_priv(netdev);
+       bool was_up = netif_carrier_ok(priv->dev);
+
+       rtnl_lock();
+       if (was_up && gve_close(priv->dev)) {
+               /* If the dev was up, attempt to close, if close fails, reset */
+               gve_reset_and_teardown(priv, was_up);
+       } else {
+               /* If the dev wasn't up or close worked, finish tearing down */
+               gve_teardown_priv_resources(priv);
+       }
+       rtnl_unlock();
+}
+
+#ifdef CONFIG_PM
+static int gve_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct gve_priv *priv = netdev_priv(netdev);
+       bool was_up = netif_carrier_ok(priv->dev);
+
+       priv->suspend_cnt++;
+       rtnl_lock();
+       if (was_up && gve_close(priv->dev)) {
+               /* If the dev was up, attempt to close, if close fails, reset */
+               gve_reset_and_teardown(priv, was_up);
+       } else {
+               /* If the dev wasn't up or close worked, finish tearing down */
+               gve_teardown_priv_resources(priv);
+       }
+       priv->up_before_suspend = was_up;
+       rtnl_unlock();
+       return 0;
+}
+
+static int gve_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct gve_priv *priv = netdev_priv(netdev);
+       int err;
+
+       priv->resume_cnt++;
+       rtnl_lock();
+       err = gve_reset_recovery(priv, priv->up_before_suspend);
+       rtnl_unlock();
+       return err;
+}
+#endif /* CONFIG_PM */
+
 static const struct pci_device_id gve_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_GOOGLE, PCI_DEV_ID_GVNIC) },
        { }
        .id_table       = gve_id_table,
        .probe          = gve_probe,
        .remove         = gve_remove,
+       .shutdown       = gve_shutdown,
+#ifdef CONFIG_PM
+       .suspend        = gve_suspend,
+       .resume         = gve_resume,
+#endif
 };
 
 module_pci_driver(gvnic_driver);