Skip to content

Commit

Permalink
r8169: Fix runtime power management
Browse files Browse the repository at this point in the history
I noticed that one of the post-2.6.36 patches broke runtime PM of the
r8169 on my MSI Wind test machine in such a way that the link was not
brought up after reconnecting the network cable.

In the process of debugging the issue I realized that we only should
invoke the runtime PM functions in rtl8169_check_link_status() when
link change is reported and if we do so, the problem goes away.
Moreover, this allows rtl8169_runtime_idle() to be simplified quite
a bit.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Rafael J. Wysocki authored and David S. Miller committed Dec 10, 2010
1 parent 6934d33 commit e4fbce7
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions drivers/net/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,26 +744,36 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
mdio_write(ioaddr, MII_BMCR, val & 0xffff);
}

static void rtl8169_check_link_status(struct net_device *dev,
static void __rtl8169_check_link_status(struct net_device *dev,
struct rtl8169_private *tp,
void __iomem *ioaddr)
void __iomem *ioaddr,
bool pm)
{
unsigned long flags;

spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
/* This is to cancel a scheduled suspend if there's one. */
pm_request_resume(&tp->pci_dev->dev);
if (pm)
pm_request_resume(&tp->pci_dev->dev);
netif_carrier_on(dev);
netif_info(tp, ifup, dev, "link up\n");
} else {
netif_carrier_off(dev);
netif_info(tp, ifdown, dev, "link down\n");
pm_schedule_suspend(&tp->pci_dev->dev, 100);
if (pm)
pm_schedule_suspend(&tp->pci_dev->dev, 100);
}
spin_unlock_irqrestore(&tp->lock, flags);
}

static void rtl8169_check_link_status(struct net_device *dev,
struct rtl8169_private *tp,
void __iomem *ioaddr)
{
__rtl8169_check_link_status(dev, tp, ioaddr, false);
}

#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)

static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
Expand Down Expand Up @@ -4600,7 +4610,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
}

if (status & LinkChg)
rtl8169_check_link_status(dev, tp, ioaddr);
__rtl8169_check_link_status(dev, tp, ioaddr, true);

/* We need to see the lastest version of tp->intr_mask to
* avoid ignoring an MSI interrupt and having to wait for
Expand Down Expand Up @@ -4890,11 +4900,7 @@ static int rtl8169_runtime_idle(struct device *device)
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);

if (!tp->TxDescArray)
return 0;

rtl8169_check_link_status(dev, tp, tp->mmio_addr);
return -EBUSY;
return tp->TxDescArray ? -EBUSY : 0;
}

static const struct dev_pm_ops rtl8169_pm_ops = {
Expand Down

0 comments on commit e4fbce7

Please sign in to comment.