@@ -562,6 +562,81 @@ static void rhine_ack_events(struct rhine_private *rp, u32 mask)
mmiowb();
}
+/* Configures ACPI D0..D3 on card side. */
+static void
+rhine_power_state_configure(struct rhine_private *rp, u8 pci_state)
+{
+ void __iomem *ioaddr = rp->base;
+ u8 other_bits;
+ WARN_ON(!((pci_state >= 0) && (pci_state <= 3)));
+
+ other_bits = ioread8(ioaddr + StickyHW) & 0xFC;
+ iowrite8(other_bits | pci_state, ioaddr + StickyHW);
+}
+
+static inline void
+rhine_wol_configure(struct net_device *dev, u16 *wolstat_out)
+{
+ struct rhine_private *rp = netdev_priv(dev);
+ void __iomem *ioaddr = rp->base;
+ u16 wolstat = 0;
+
+ /* Make sure chip is in power state D0 */
+ rhine_power_state_configure(rp, 0);
+
+ /* Disable "force PME-enable" */
+ iowrite8(0x80, ioaddr + WOLcgClr);
+
+ /* Clear power-event config bits (WOL) */
+ iowrite8(0xFF, ioaddr + WOLcrClr);
+ /* More recent cards can manage two additional patterns */
+ if (rp->quirks & rq6patterns)
+ iowrite8(0x03, ioaddr + WOLcrClr1);
+
+ /* Save power-event status bits */
+ wolstat = ioread8(ioaddr + PwrcsrSet);
+ if (rp->quirks & rq6patterns)
+ wolstat |= (ioread8(ioaddr + PwrcsrSet1) & 0x03) << 8;
+
+ /* Clear power-event status bits */
+ iowrite8(0xFF, ioaddr + PwrcsrClr);
+ if (rp->quirks & rq6patterns)
+ iowrite8(0x03, ioaddr + PwrcsrClr1);
+
+ if (wolstat_out)
+ *wolstat_out = wolstat;
+}
+
+static inline void
+rhine_wol_log_wakeup_reason(struct net_device *dev, u16 wolstat)
+{
+ if (wolstat) {
+ const char *reason;
+ switch (wolstat) {
+ case WOLmagic:
+ reason = "Magic packet";
+ break;
+ case WOLlnkon:
+ reason = "Link went up";
+ break;
+ case WOLlnkoff:
+ reason = "Link went down";
+ break;
+ case WOLucast:
+ reason = "Unicast packet";
+ break;
+ case WOLbmcast:
+ reason = "Multicast/broadcast packet";
+ break;
+ default:
+ reason = "Unknown";
+ break;
+ }
+ netdev_info(dev, "Woke system up. Reason: %s\n",
+ reason);
+ }
+}
+
/*
* Get power related registers into sane state.
* Notify user about past WOL event.
@@ -569,56 +644,12 @@ static void rhine_ack_events(struct rhine_private *rp, u32 mask)
static void rhine_power_init(struct net_device *dev)
{
struct rhine_private *rp = netdev_priv(dev);
- void __iomem *ioaddr = rp->base;
- u16 wolstat;
if (rp->quirks & rqHaveWOL) {
- /* Make sure chip is in power state D0 */
- iowrite8(ioread8(ioaddr + StickyHW) & 0xFC, ioaddr + StickyHW);
-
- /* Disable "force PME-enable" */
- iowrite8(0x80, ioaddr + WOLcgClr);
-
- /* Clear power-event config bits (WOL) */
- iowrite8(0xFF, ioaddr + WOLcrClr);
- /* More recent cards can manage two additional patterns */
- if (rp->quirks & rq6patterns)
- iowrite8(0x03, ioaddr + WOLcrClr1);
-
- /* Save power-event status bits */
- wolstat = ioread8(ioaddr + PwrcsrSet);
- if (rp->quirks & rq6patterns)
- wolstat |= (ioread8(ioaddr + PwrcsrSet1) & 0x03) << 8;
-
- /* Clear power-event status bits */
- iowrite8(0xFF, ioaddr + PwrcsrClr);
- if (rp->quirks & rq6patterns)
- iowrite8(0x03, ioaddr + PwrcsrClr1);
-
- if (wolstat) {
- char *reason;
- switch (wolstat) {
- case WOLmagic:
- reason = "Magic packet";
- break;
- case WOLlnkon:
- reason = "Link went up";
- break;
- case WOLlnkoff:
- reason = "Link went down";
- break;
- case WOLucast:
- reason = "Unicast packet";
- break;
- case WOLbmcast:
- reason = "Multicast/broadcast packet";
- break;
- default:
- reason = "Unknown";
- }
- netdev_info(dev, "Woke system up. Reason: %s\n",
- reason);
- }
+ u16 wolstat;
+ rhine_wol_configure(dev, &wolstat);
+
+ rhine_wol_log_wakeup_reason(dev, wolstat);
}
}
@@ -2325,7 +2356,7 @@ rhine_shutdown_and_keep_wol(struct pci_dev *pdev)
spin_unlock(&rp->lock);
if (system_state == SYSTEM_POWER_OFF && !avoid_D3) {
- iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+ rhine_power_state_configure(rp, 3);
pci_wake_from_d3(pdev, true);
pci_set_power_state(pdev, PCI_D3hot);