aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/3c59x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r--drivers/net/3c59x.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index c685a55fc2f4..179871d9e71f 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -635,6 +635,9 @@ struct vortex_private {
635 must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ 635 must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */
636 large_frames:1, /* accept large frames */ 636 large_frames:1, /* accept large frames */
637 handling_irq:1; /* private in_irq indicator */ 637 handling_irq:1; /* private in_irq indicator */
638 /* {get|set}_wol operations are already serialized by rtnl.
639 * no additional locking is required for the enable_wol and acpi_set_WOL()
640 */
638 int drv_flags; 641 int drv_flags;
639 u16 status_enable; 642 u16 status_enable;
640 u16 intr_enable; 643 u16 intr_enable;
@@ -647,7 +650,7 @@ struct vortex_private {
647 u16 io_size; /* Size of PCI region (for release_region) */ 650 u16 io_size; /* Size of PCI region (for release_region) */
648 651
649 /* Serialises access to hardware other than MII and variables below. 652 /* Serialises access to hardware other than MII and variables below.
650 * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ 653 * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */
651 spinlock_t lock; 654 spinlock_t lock;
652 655
653 spinlock_t mii_lock; /* Serialises access to MII */ 656 spinlock_t mii_lock; /* Serialises access to MII */
@@ -1994,10 +1997,9 @@ vortex_error(struct net_device *dev, int status)
1994 } 1997 }
1995 } 1998 }
1996 1999
1997 if (status & RxEarly) { /* Rx early is unused. */ 2000 if (status & RxEarly) /* Rx early is unused. */
1998 vortex_rx(dev);
1999 iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); 2001 iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
2000 } 2002
2001 if (status & StatsFull) { /* Empty statistics. */ 2003 if (status & StatsFull) { /* Empty statistics. */
2002 static int DoneDidThat; 2004 static int DoneDidThat;
2003 if (vortex_debug > 4) 2005 if (vortex_debug > 4)
@@ -2298,7 +2300,12 @@ vortex_interrupt(int irq, void *dev_id)
2298 if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { 2300 if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
2299 if (status == 0xffff) 2301 if (status == 0xffff)
2300 break; 2302 break;
2303 if (status & RxEarly)
2304 vortex_rx(dev);
2305 spin_unlock(&vp->window_lock);
2301 vortex_error(dev, status); 2306 vortex_error(dev, status);
2307 spin_lock(&vp->window_lock);
2308 window_set(vp, 7);
2302 } 2309 }
2303 2310
2304 if (--work_done < 0) { 2311 if (--work_done < 0) {
@@ -2935,28 +2942,31 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
2935{ 2942{
2936 struct vortex_private *vp = netdev_priv(dev); 2943 struct vortex_private *vp = netdev_priv(dev);
2937 2944
2938 spin_lock_irq(&vp->lock); 2945 if (!VORTEX_PCI(vp))
2946 return;
2947
2939 wol->supported = WAKE_MAGIC; 2948 wol->supported = WAKE_MAGIC;
2940 2949
2941 wol->wolopts = 0; 2950 wol->wolopts = 0;
2942 if (vp->enable_wol) 2951 if (vp->enable_wol)
2943 wol->wolopts |= WAKE_MAGIC; 2952 wol->wolopts |= WAKE_MAGIC;
2944 spin_unlock_irq(&vp->lock);
2945} 2953}
2946 2954
2947static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) 2955static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
2948{ 2956{
2949 struct vortex_private *vp = netdev_priv(dev); 2957 struct vortex_private *vp = netdev_priv(dev);
2958
2959 if (!VORTEX_PCI(vp))
2960 return -EOPNOTSUPP;
2961
2950 if (wol->wolopts & ~WAKE_MAGIC) 2962 if (wol->wolopts & ~WAKE_MAGIC)
2951 return -EINVAL; 2963 return -EINVAL;
2952 2964
2953 spin_lock_irq(&vp->lock);
2954 if (wol->wolopts & WAKE_MAGIC) 2965 if (wol->wolopts & WAKE_MAGIC)
2955 vp->enable_wol = 1; 2966 vp->enable_wol = 1;
2956 else 2967 else
2957 vp->enable_wol = 0; 2968 vp->enable_wol = 0;
2958 acpi_set_WOL(dev); 2969 acpi_set_WOL(dev);
2959 spin_unlock_irq(&vp->lock);
2960 2970
2961 return 0; 2971 return 0;
2962} 2972}
@@ -2984,7 +2994,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2984{ 2994{
2985 int err; 2995 int err;
2986 struct vortex_private *vp = netdev_priv(dev); 2996 struct vortex_private *vp = netdev_priv(dev);
2987 unsigned long flags;
2988 pci_power_t state = 0; 2997 pci_power_t state = 0;
2989 2998
2990 if(VORTEX_PCI(vp)) 2999 if(VORTEX_PCI(vp))
@@ -2994,9 +3003,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2994 3003
2995 if(state != 0) 3004 if(state != 0)
2996 pci_set_power_state(VORTEX_PCI(vp), PCI_D0); 3005 pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
2997 spin_lock_irqsave(&vp->lock, flags);
2998 err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); 3006 err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL);
2999 spin_unlock_irqrestore(&vp->lock, flags);
3000 if(state != 0) 3007 if(state != 0)
3001 pci_set_power_state(VORTEX_PCI(vp), state); 3008 pci_set_power_state(VORTEX_PCI(vp), state);
3002 3009
@@ -3201,6 +3208,9 @@ static void acpi_set_WOL(struct net_device *dev)
3201 return; 3208 return;
3202 } 3209 }
3203 3210
3211 if (VORTEX_PCI(vp)->current_state < PCI_D3hot)
3212 return;
3213
3204 /* Change the power state to D3; RxEnable doesn't take effect. */ 3214 /* Change the power state to D3; RxEnable doesn't take effect. */
3205 pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); 3215 pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
3206 } 3216 }