r8169: fix broken ring index handling in suspend/resume
rtl8169_hw_start() requires that the descriptor ring indexes be set to zero. Let a deferred invocation of rtl8169_reset_task() handle it. Enabling a few power management bits will not hurt either. suspend/resume is issued with irq on: the spinlock do not need to save the irq flag. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
This commit is contained in:
parent
791917deb6
commit
5d06a99f54
1 changed files with 59 additions and 43 deletions
|
@ -287,6 +287,12 @@ enum RTL8169_register_content {
|
|||
TxInterFrameGapShift = 24,
|
||||
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
|
||||
|
||||
/* Config1 register p.24 */
|
||||
PMEnable = (1 << 0), /* Power Management Enable */
|
||||
|
||||
/* Config5 register p.27 */
|
||||
PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
|
||||
|
||||
/* TBICSR p.28 */
|
||||
TBIReset = 0x80000000,
|
||||
TBILoopback = 0x40000000,
|
||||
|
@ -1442,6 +1448,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
|
|||
}
|
||||
tp->chipset = i;
|
||||
|
||||
RTL_W8(Cfg9346, Cfg9346_Unlock);
|
||||
RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
|
||||
RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
|
||||
RTL_W8(Cfg9346, Cfg9346_Lock);
|
||||
|
||||
*ioaddr_out = ioaddr;
|
||||
*dev_out = dev;
|
||||
out:
|
||||
|
@ -1612,49 +1623,6 @@ rtl8169_remove_one(struct pci_dev *pdev)
|
|||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct rtl8169_private *tp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
unsigned long flags;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
netif_device_detach(dev);
|
||||
netif_stop_queue(dev);
|
||||
spin_lock_irqsave(&tp->lock, flags);
|
||||
|
||||
/* Disable interrupts, stop Rx and Tx */
|
||||
RTL_W16(IntrMask, 0);
|
||||
RTL_W8(ChipCmd, 0);
|
||||
|
||||
/* Update the error counts. */
|
||||
tp->stats.rx_missed_errors += RTL_R32(RxMissed);
|
||||
RTL_W32(RxMissed, 0);
|
||||
spin_unlock_irqrestore(&tp->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8169_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
netif_device_attach(dev);
|
||||
rtl8169_hw_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
|
||||
struct net_device *dev)
|
||||
{
|
||||
|
@ -2700,6 +2668,54 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
|
|||
return &tp->stats;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct rtl8169_private *tp = netdev_priv(dev);
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
|
||||
if (!netif_running(dev))
|
||||
goto out;
|
||||
|
||||
netif_device_detach(dev);
|
||||
netif_stop_queue(dev);
|
||||
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
rtl8169_asic_down(ioaddr);
|
||||
|
||||
tp->stats.rx_missed_errors += RTL_R32(RxMissed);
|
||||
RTL_W32(RxMissed, 0);
|
||||
|
||||
spin_unlock_irq(&tp->lock);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8169_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
if (!netif_running(dev))
|
||||
goto out;
|
||||
|
||||
netif_device_attach(dev);
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
rtl8169_schedule_work(dev, rtl8169_reset_task);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct pci_driver rtl8169_pci_driver = {
|
||||
.name = MODULENAME,
|
||||
.id_table = rtl8169_pci_tbl,
|
||||
|
|
Loading…
Reference in a new issue