diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2012-01-31 04:47:34 -0500 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2012-01-31 08:32:40 -0500 |
commit | 98ddf986fca17840e46e070354b7e2cd2169da15 (patch) | |
tree | 520b59064cfb654b15d1491536112d41492f8fa1 /drivers | |
parent | ae1f23fb433ac0aaff8aeaa5a7b14348e9aa8277 (diff) |
r8169: bh locking redux and task scheduling.
- atomic bit operations are globally visible
- pending status is always cleared before execution
- scheduled works are either idempotent or only required to happen once
after a series of originating events, say link events for instance
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Suggested-by: Michał Mirosław <mirqus@gmail.com>
Cc: Hayes Wang <hayeswang@realtek.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/realtek/r8169.c | 20 |
1 files changed, 4 insertions, 16 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 859554a03a0..118f6f6fcef 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
@@ -3273,17 +3273,8 @@ out_mod_timer: | |||
3273 | 3273 | ||
3274 | static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) | 3274 | static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) |
3275 | { | 3275 | { |
3276 | spin_lock(&tp->lock); | ||
3277 | if (!test_and_set_bit(flag, tp->wk.flags)) | 3276 | if (!test_and_set_bit(flag, tp->wk.flags)) |
3278 | schedule_work(&tp->wk.work); | 3277 | schedule_work(&tp->wk.work); |
3279 | spin_unlock(&tp->lock); | ||
3280 | } | ||
3281 | |||
3282 | static void rtl_schedule_task_bh(struct rtl8169_private *tp, enum rtl_flag flag) | ||
3283 | { | ||
3284 | local_bh_disable(); | ||
3285 | rtl_schedule_task(tp, flag); | ||
3286 | local_bh_enable(); | ||
3287 | } | 3278 | } |
3288 | 3279 | ||
3289 | static void rtl8169_phy_timer(unsigned long __opaque) | 3280 | static void rtl8169_phy_timer(unsigned long __opaque) |
@@ -3291,7 +3282,7 @@ static void rtl8169_phy_timer(unsigned long __opaque) | |||
3291 | struct net_device *dev = (struct net_device *)__opaque; | 3282 | struct net_device *dev = (struct net_device *)__opaque; |
3292 | struct rtl8169_private *tp = netdev_priv(dev); | 3283 | struct rtl8169_private *tp = netdev_priv(dev); |
3293 | 3284 | ||
3294 | rtl_schedule_task_bh(tp, RTL_FLAG_TASK_PHY_PENDING); | 3285 | rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING); |
3295 | } | 3286 | } |
3296 | 3287 | ||
3297 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3288 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -5635,7 +5626,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) | |||
5635 | 5626 | ||
5636 | rtl8169_hw_reset(tp); | 5627 | rtl8169_hw_reset(tp); |
5637 | 5628 | ||
5638 | rtl_schedule_task_bh(tp, RTL_FLAG_TASK_RESET_PENDING); | 5629 | rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); |
5639 | } | 5630 | } |
5640 | 5631 | ||
5641 | static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) | 5632 | static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) |
@@ -5852,7 +5843,7 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) | |||
5852 | /* Work around for rx fifo overflow */ | 5843 | /* Work around for rx fifo overflow */ |
5853 | case RTL_GIGA_MAC_VER_11: | 5844 | case RTL_GIGA_MAC_VER_11: |
5854 | netif_stop_queue(dev); | 5845 | netif_stop_queue(dev); |
5855 | rtl_schedule_task_bh(tp, RTL_FLAG_TASK_RESET_PENDING); | 5846 | rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); |
5856 | default: | 5847 | default: |
5857 | break; | 5848 | break; |
5858 | } | 5849 | } |
@@ -5894,10 +5885,7 @@ static void rtl_task(struct work_struct *work) | |||
5894 | for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { | 5885 | for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { |
5895 | bool pending; | 5886 | bool pending; |
5896 | 5887 | ||
5897 | spin_lock_bh(&tp->lock); | ||
5898 | pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); | 5888 | pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); |
5899 | spin_unlock_bh(&tp->lock); | ||
5900 | |||
5901 | if (pending) | 5889 | if (pending) |
5902 | rtl_work[i].action(tp); | 5890 | rtl_work[i].action(tp); |
5903 | } | 5891 | } |
@@ -6116,7 +6104,7 @@ static void __rtl8169_resume(struct net_device *dev) | |||
6116 | 6104 | ||
6117 | tp->wk.enabled = true; | 6105 | tp->wk.enabled = true; |
6118 | 6106 | ||
6119 | rtl_schedule_task_bh(tp, RTL_FLAG_TASK_RESET_PENDING); | 6107 | rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); |
6120 | } | 6108 | } |
6121 | 6109 | ||
6122 | static int rtl8169_resume(struct device *device) | 6110 | static int rtl8169_resume(struct device *device) |