Re: 2.6.29-rc3: tg3 dead after resume

Rafael J. Wysocki
2009-01-29T23:04:20Z

On Thursday 29 January 2009, Parag Warudkar wrote:
>
> On Thu, 29 Jan 2009, Matt Carlson wrote:
>
> > Can you apply the following test patch and see if it helps? The patch
> > does two things. First, it enables a bit which should restore firmware
> > communication. If that fixes the problem, then let me know and I'll
> > spin a proper patch.
> >
> > In the event that it doesn't work, the patch goes on to test the memory
> > mapping by simply printing the register value at offset 0x0. The value
> > should be the device's vendor ID and device ID. Please post the
> > results so that I can verify it.
> >
> >
> > diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
> > index 8b3f846..39fce42 100644
> > --- a/drivers/net/tg3.c
> > +++ b/drivers/net/tg3.c
> > @@ -7227,6 +7227,11 @@ static int tg3_init_hw(struct tg3 *tp, int reset_phy)
> > {
> > tg3_switch_clocks(tp);
> >
> > + printk( KERN_NOTICE "%s: Reg value at offset 0x0 is 0x%x\n",
> > + tp->dev->name, tr32(0x0) );
> > +
> > + tw32(MEMARB_MODE, tr32(MEMARB_MODE) | MEMARB_MODE_ENABLE);
> > +
> > tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
> >
> > return tg3_reset_hw(tp, reset_phy);
> >
>
> Hi Matt,
>
> Thanks for the patch. It didn't help with resume - but below is the
> output after patching, let me know if you need more details.

[--snip--]

In the meantime I tried to rework tg3 suspend/resume so that it uses the new
PCI core capability of handling the PCI-specific parts of both operations.

The patch is appended, please see if it makes any difference.

Thanks,
Rafael

---
drivers/net/tg3.c | 70 +++++++++++++++++++-----------------------------------
1 file changed, 25 insertions(+), 45 deletions(-)

Index: linux-2.6/drivers/net/tg3.c
===================================================================
--- linux-2.6.orig/drivers/net/tg3.c
+++ linux-2.6/drivers/net/tg3.c
@@ -13330,18 +13330,13 @@ static void __devexit tg3_remove_one(str
}
}

-static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
+#ifdef CONFIG_PM
+
+static int tg3_suspend(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
struct tg3 *tp = netdev_priv(dev);
- pci_power_t target_state;
- int err;
-
- /* PCI register 4 needs to be saved whether netif_running() or not.
- * MSI address and data need to be saved if using MSI and
- * netif_running().
- */
- pci_save_state(pdev);

if (!netif_running(dev))
return 0;
@@ -13363,50 +13358,19 @@ static int tg3_suspend(struct pci_dev *p
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
tg3_full_unlock(tp);

- target_state = pdev->pm_cap ? pci_target_state(pdev) : PCI_D3hot;
-
- err = tg3_set_power_state(tp, target_state);
- if (err) {
- int err2;
-
- tg3_full_lock(tp, 0);
-
- tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- err2 = tg3_restart_hw(tp, 1);
- if (err2)
- goto out;
-
- tp->timer.expires = jiffies + tp->timer_offset;
- add_timer(&tp->timer);
-
- netif_device_attach(dev);
- tg3_netif_start(tp);
-
-out:
- tg3_full_unlock(tp);
-
- if (!err2)
- tg3_phy_start(tp);
- }
-
- return err;
+ return 0;
}

-static int tg3_resume(struct pci_dev *pdev)
+static int tg3_resume(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct net_device *dev = pci_get_drvdata(pdev);
struct tg3 *tp = netdev_priv(dev);
int err;

- pci_restore_state(tp->pdev);
-
if (!netif_running(dev))
return 0;

- err = tg3_set_power_state(tp, PCI_D0);
- if (err)
- return err;
-
netif_device_attach(dev);

tg3_full_lock(tp, 0);
@@ -13430,13 +13394,29 @@ out:
return err;
}

+struct dev_pm_ops tg3_pm_ops = {
+ .suspend = tg3_suspend,
+ .resume = tg3_resume,
+ .freeze = tg3_suspend,
+ .thaw = tg3_resume,
+ .poweroff = tg3_suspend,
+ .restore = tg3_resume,
+};
+
+#define TG3_PM_OPS (&tg3_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define TG3_PM_OPS NULL
+
+#endif /* !CONFIG_PM */
+
static struct pci_driver tg3_driver = {
.name = DRV_MODULE_NAME,
.id_table = tg3_pci_tbl,
.probe = tg3_init_one,
.remove = __devexit_p(tg3_remove_one),
- .suspend = tg3_suspend,
- .resume = tg3_resume
+ .driver.pm = TG3_PM_OPS,
};

static int __init tg3_init(void)