diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2010-01-22 02:01:11 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-01-22 16:11:41 -0500 |
commit | b92f7d30830a319148df2943b7565989494e5ad1 (patch) | |
tree | 1f03218a846f242f735bad31347a59138753a92c /drivers/net/wireless/p54/p54pci.c | |
parent | 59af099b1956086b06c0d0f32ea99ce136b415b7 (diff) |
p54pci: revise tx locking
This patch continues the effort which began with:
"[PATCH] p54pci: move tx cleanup into tasklet".
Thanks to these changes, p54pci's interrupt & tx
cleanup routines can be made lock-less.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54pci.c')
-rw-r--r-- | drivers/net/wireless/p54/p54pci.c | 16 |
1 files changed, 4 insertions, 12 deletions
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 48cae48ed6eb..bda29c00f3ef 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -238,7 +238,6 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
238 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | 238 | int ring_index, struct p54p_desc *ring, u32 ring_limit, |
239 | struct sk_buff **tx_buf) | 239 | struct sk_buff **tx_buf) |
240 | { | 240 | { |
241 | unsigned long flags; | ||
242 | struct p54p_priv *priv = dev->priv; | 241 | struct p54p_priv *priv = dev->priv; |
243 | struct p54p_ring_control *ring_control = priv->ring_control; | 242 | struct p54p_ring_control *ring_control = priv->ring_control; |
244 | struct p54p_desc *desc; | 243 | struct p54p_desc *desc; |
@@ -249,7 +248,6 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
249 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); | 248 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); |
250 | idx %= ring_limit; | 249 | idx %= ring_limit; |
251 | 250 | ||
252 | spin_lock_irqsave(&priv->lock, flags); | ||
253 | while (i != idx) { | 251 | while (i != idx) { |
254 | desc = &ring[i]; | 252 | desc = &ring[i]; |
255 | 253 | ||
@@ -264,16 +262,12 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
264 | desc->len = 0; | 262 | desc->len = 0; |
265 | desc->flags = 0; | 263 | desc->flags = 0; |
266 | 264 | ||
267 | if (skb && FREE_AFTER_TX(skb)) { | 265 | if (skb && FREE_AFTER_TX(skb)) |
268 | spin_unlock_irqrestore(&priv->lock, flags); | ||
269 | p54_free_skb(dev, skb); | 266 | p54_free_skb(dev, skb); |
270 | spin_lock_irqsave(&priv->lock, flags); | ||
271 | } | ||
272 | 267 | ||
273 | i++; | 268 | i++; |
274 | i %= ring_limit; | 269 | i %= ring_limit; |
275 | } | 270 | } |
276 | spin_unlock_irqrestore(&priv->lock, flags); | ||
277 | } | 271 | } |
278 | 272 | ||
279 | static void p54p_tasklet(unsigned long dev_id) | 273 | static void p54p_tasklet(unsigned long dev_id) |
@@ -306,7 +300,6 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) | |||
306 | struct p54p_priv *priv = dev->priv; | 300 | struct p54p_priv *priv = dev->priv; |
307 | __le32 reg; | 301 | __le32 reg; |
308 | 302 | ||
309 | spin_lock(&priv->lock); | ||
310 | reg = P54P_READ(int_ident); | 303 | reg = P54P_READ(int_ident); |
311 | if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { | 304 | if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { |
312 | goto out; | 305 | goto out; |
@@ -321,15 +314,14 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) | |||
321 | complete(&priv->boot_comp); | 314 | complete(&priv->boot_comp); |
322 | 315 | ||
323 | out: | 316 | out: |
324 | spin_unlock(&priv->lock); | ||
325 | return reg ? IRQ_HANDLED : IRQ_NONE; | 317 | return reg ? IRQ_HANDLED : IRQ_NONE; |
326 | } | 318 | } |
327 | 319 | ||
328 | static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 320 | static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
329 | { | 321 | { |
322 | unsigned long flags; | ||
330 | struct p54p_priv *priv = dev->priv; | 323 | struct p54p_priv *priv = dev->priv; |
331 | struct p54p_ring_control *ring_control = priv->ring_control; | 324 | struct p54p_ring_control *ring_control = priv->ring_control; |
332 | unsigned long flags; | ||
333 | struct p54p_desc *desc; | 325 | struct p54p_desc *desc; |
334 | dma_addr_t mapping; | 326 | dma_addr_t mapping; |
335 | u32 device_idx, idx, i; | 327 | u32 device_idx, idx, i; |
@@ -370,14 +362,14 @@ static void p54p_stop(struct ieee80211_hw *dev) | |||
370 | unsigned int i; | 362 | unsigned int i; |
371 | struct p54p_desc *desc; | 363 | struct p54p_desc *desc; |
372 | 364 | ||
373 | tasklet_kill(&priv->tasklet); | ||
374 | |||
375 | P54P_WRITE(int_enable, cpu_to_le32(0)); | 365 | P54P_WRITE(int_enable, cpu_to_le32(0)); |
376 | P54P_READ(int_enable); | 366 | P54P_READ(int_enable); |
377 | udelay(10); | 367 | udelay(10); |
378 | 368 | ||
379 | free_irq(priv->pdev->irq, dev); | 369 | free_irq(priv->pdev->irq, dev); |
380 | 370 | ||
371 | tasklet_kill(&priv->tasklet); | ||
372 | |||
381 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); | 373 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); |
382 | 374 | ||
383 | for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { | 375 | for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { |