diff options
author | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-09-16 19:30:39 -0400 |
---|---|---|
committer | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-10-19 02:56:05 -0400 |
commit | ac53aed9349242095a780f57ac0c995fb170c950 (patch) | |
tree | 2962df61c6bdee9f184bb278a8b25b4c5a6d219d /drivers/net/wimax/i2400m | |
parent | cb5b756f746b77c5323ae413a41e9a40ea33c453 (diff) |
wimax/i2400m: on device stop, clean up pending wake & TX work
When the i2400m device needs to wake up an idle WiMAX connection, it
schedules a workqueue job to do it.
Currently, only when the network stack called the _stop() method this
work struct was being cancelled. This has to be done every time the
device is stopped.
So add a call in i2400m_dev_stop() to take care of such cleanup, which
is now wrapped in i2400m_net_wake_stop().
Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m')
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 1 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/netdev.c | 53 |
3 files changed, 35 insertions, 20 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 07d12be0cf81..a33df0431020 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -527,6 +527,7 @@ void __i2400m_dev_stop(struct i2400m *i2400m) | |||
527 | 527 | ||
528 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 528 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
529 | wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); | 529 | wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); |
530 | i2400m_net_wake_stop(i2400m); | ||
530 | i2400m_dev_shutdown(i2400m); | 531 | i2400m_dev_shutdown(i2400m); |
531 | i2400m->ready = 0; | 532 | i2400m->ready = 0; |
532 | i2400m->bus_dev_stop(i2400m); | 533 | i2400m->bus_dev_stop(i2400m); |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 916b1d319299..303eb78bce32 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -691,6 +691,7 @@ extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, | |||
691 | const void *, int); | 691 | const void *, int); |
692 | extern void i2400m_net_erx(struct i2400m *, struct sk_buff *, | 692 | extern void i2400m_net_erx(struct i2400m *, struct sk_buff *, |
693 | enum i2400m_cs); | 693 | enum i2400m_cs); |
694 | extern void i2400m_net_wake_stop(struct i2400m *); | ||
694 | enum i2400m_pt; | 695 | enum i2400m_pt; |
695 | extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); | 696 | extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); |
696 | 697 | ||
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 960fb5467546..0e8f6a046b9b 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -113,11 +113,6 @@ int i2400m_open(struct net_device *net_dev) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | /* | ||
117 | * | ||
118 | * On kernel versions where cancel_work_sync() didn't return anything, | ||
119 | * we rely on wake_tx_skb() being non-NULL. | ||
120 | */ | ||
121 | static | 116 | static |
122 | int i2400m_stop(struct net_device *net_dev) | 117 | int i2400m_stop(struct net_device *net_dev) |
123 | { | 118 | { |
@@ -125,21 +120,7 @@ int i2400m_stop(struct net_device *net_dev) | |||
125 | struct device *dev = i2400m_dev(i2400m); | 120 | struct device *dev = i2400m_dev(i2400m); |
126 | 121 | ||
127 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); | 122 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); |
128 | /* See i2400m_hard_start_xmit(), references are taken there | 123 | i2400m_net_wake_stop(i2400m); |
129 | * and here we release them if the work was still | ||
130 | * pending. Note we can't differentiate work not pending vs | ||
131 | * never scheduled, so the NULL check does that. */ | ||
132 | if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 | ||
133 | && i2400m->wake_tx_skb != NULL) { | ||
134 | unsigned long flags; | ||
135 | struct sk_buff *wake_tx_skb; | ||
136 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
137 | wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ | ||
138 | i2400m->wake_tx_skb = NULL; /* compat help */ | ||
139 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
140 | i2400m_put(i2400m); | ||
141 | kfree_skb(wake_tx_skb); | ||
142 | } | ||
143 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m); | 124 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m); |
144 | return 0; | 125 | return 0; |
145 | } | 126 | } |
@@ -230,6 +211,38 @@ void i2400m_tx_prep_header(struct sk_buff *skb) | |||
230 | } | 211 | } |
231 | 212 | ||
232 | 213 | ||
214 | |||
215 | /* | ||
216 | * Cleanup resources acquired during i2400m_net_wake_tx() | ||
217 | * | ||
218 | * This is called by __i2400m_dev_stop and means we have to make sure | ||
219 | * the workqueue is flushed from any pending work. | ||
220 | */ | ||
221 | void i2400m_net_wake_stop(struct i2400m *i2400m) | ||
222 | { | ||
223 | struct device *dev = i2400m_dev(i2400m); | ||
224 | |||
225 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
226 | /* See i2400m_hard_start_xmit(), references are taken there | ||
227 | * and here we release them if the work was still | ||
228 | * pending. Note we can't differentiate work not pending vs | ||
229 | * never scheduled, so the NULL check does that. */ | ||
230 | if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 | ||
231 | && i2400m->wake_tx_skb != NULL) { | ||
232 | unsigned long flags; | ||
233 | struct sk_buff *wake_tx_skb; | ||
234 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
235 | wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ | ||
236 | i2400m->wake_tx_skb = NULL; /* compat help */ | ||
237 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
238 | i2400m_put(i2400m); | ||
239 | kfree_skb(wake_tx_skb); | ||
240 | } | ||
241 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | |||
233 | /* | 246 | /* |
234 | * TX an skb to an idle device | 247 | * TX an skb to an idle device |
235 | * | 248 | * |