diff options
author | Denis Kirjanov <dkirjanov@kernel.org> | 2010-09-14 20:58:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-15 17:32:39 -0400 |
commit | 84176b7b56704580e008e6cb820dd4ccf622a1fd (patch) | |
tree | e4a55028c485f3d48ee3ec2a051fb972f8d1899c | |
parent | 01f83d69844d307be2aa6fea88b0e8fe5cbdb2f4 (diff) |
3c59x: Remove atomic context inside vortex_{set|get}_wol
There is no need to use spinlocks in vortex_{set|get}_wol.
This also fixes a bug:
[ 254.214993] 3c59x 0000:00:0d.0: PME# enabled
[ 254.215021] BUG: sleeping function called from invalid context at kernel/mutex.c:94
[ 254.215030] in_atomic(): 0, irqs_disabled(): 1, pid: 4875, name: ethtool
[ 254.215042] Pid: 4875, comm: ethtool Tainted: G W 2.6.36-rc3+ #7
[ 254.215049] Call Trace:
[ 254.215050] [] __might_sleep+0xb1/0xb6
[ 254.215050] [] mutex_lock+0x17/0x30
[ 254.215050] [] acpi_enable_wakeup_device_power+0x2b/0xb1
[ 254.215050] [] acpi_pm_device_sleep_wake+0x42/0x7f
[ 254.215050] [] acpi_pci_sleep_wake+0x5d/0x63
[ 254.215050] [] platform_pci_sleep_wake+0x1d/0x20
[ 254.215050] [] __pci_enable_wake+0x90/0xd0
[ 254.215050] [] acpi_set_WOL+0x8e/0xf5 [3c59x]
[ 254.215050] [] vortex_set_wol+0x4e/0x5e [3c59x]
[ 254.215050] [] dev_ethtool+0x1cf/0xb61
[ 254.215050] [] ? debug_mutex_free_waiter+0x45/0x4a
[ 254.215050] [] ? __mutex_lock_common+0x204/0x20e
[ 254.215050] [] ? __mutex_lock_slowpath+0x12/0x15
[ 254.215050] [] ? mutex_lock+0x23/0x30
[ 254.215050] [] dev_ioctl+0x42c/0x533
[ 254.215050] [] ? _cond_resched+0x8/0x1c
[ 254.215050] [] ? lock_page+0x1c/0x30
[ 254.215050] [] ? page_address+0x15/0x7c
[ 254.215050] [] ? filemap_fault+0x187/0x2c4
[ 254.215050] [] sock_ioctl+0x1d4/0x1e0
[ 254.215050] [] ? sock_ioctl+0x0/0x1e0
[ 254.215050] [] vfs_ioctl+0x19/0x33
[ 254.215050] [] do_vfs_ioctl+0x424/0x46f
[ 254.215050] [] ? selinux_file_ioctl+0x3c/0x40
[ 254.215050] [] sys_ioctl+0x40/0x5a
[ 254.215050] [] sysenter_do_call+0x12/0x22
vortex_set_wol protected with a spinlock, but nested acpi_set_WOL acquires a mutex inside atomic context.
Ethtool operations are already serialized by RTNL mutex, so it is safe to drop the locks.
Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/3c59x.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 85671adae455..fa42103b2874 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; |
@@ -2939,13 +2942,11 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
2939 | { | 2942 | { |
2940 | struct vortex_private *vp = netdev_priv(dev); | 2943 | struct vortex_private *vp = netdev_priv(dev); |
2941 | 2944 | ||
2942 | spin_lock_irq(&vp->lock); | ||
2943 | wol->supported = WAKE_MAGIC; | 2945 | wol->supported = WAKE_MAGIC; |
2944 | 2946 | ||
2945 | wol->wolopts = 0; | 2947 | wol->wolopts = 0; |
2946 | if (vp->enable_wol) | 2948 | if (vp->enable_wol) |
2947 | wol->wolopts |= WAKE_MAGIC; | 2949 | wol->wolopts |= WAKE_MAGIC; |
2948 | spin_unlock_irq(&vp->lock); | ||
2949 | } | 2950 | } |
2950 | 2951 | ||
2951 | static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | 2952 | static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) |
@@ -2954,13 +2955,11 @@ static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
2954 | if (wol->wolopts & ~WAKE_MAGIC) | 2955 | if (wol->wolopts & ~WAKE_MAGIC) |
2955 | return -EINVAL; | 2956 | return -EINVAL; |
2956 | 2957 | ||
2957 | spin_lock_irq(&vp->lock); | ||
2958 | if (wol->wolopts & WAKE_MAGIC) | 2958 | if (wol->wolopts & WAKE_MAGIC) |
2959 | vp->enable_wol = 1; | 2959 | vp->enable_wol = 1; |
2960 | else | 2960 | else |
2961 | vp->enable_wol = 0; | 2961 | vp->enable_wol = 0; |
2962 | acpi_set_WOL(dev); | 2962 | acpi_set_WOL(dev); |
2963 | spin_unlock_irq(&vp->lock); | ||
2964 | 2963 | ||
2965 | return 0; | 2964 | return 0; |
2966 | } | 2965 | } |