diff options
-rw-r--r-- | drivers/net/wireless/p54/p54pci.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54pci.h | 6 |
2 files changed, 32 insertions, 30 deletions
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 4bf4c213baec..48cae48ed6eb 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -234,25 +234,26 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, | |||
234 | p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); | 234 | p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); |
235 | } | 235 | } |
236 | 236 | ||
237 | /* caller must hold priv->lock */ | ||
238 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | 237 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, |
239 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | 238 | int ring_index, struct p54p_desc *ring, u32 ring_limit, |
240 | void **tx_buf) | 239 | struct sk_buff **tx_buf) |
241 | { | 240 | { |
241 | unsigned long flags; | ||
242 | struct p54p_priv *priv = dev->priv; | 242 | struct p54p_priv *priv = dev->priv; |
243 | struct p54p_ring_control *ring_control = priv->ring_control; | 243 | struct p54p_ring_control *ring_control = priv->ring_control; |
244 | struct p54p_desc *desc; | 244 | struct p54p_desc *desc; |
245 | struct sk_buff *skb; | ||
245 | u32 idx, i; | 246 | u32 idx, i; |
246 | 247 | ||
247 | i = (*index) % ring_limit; | 248 | i = (*index) % ring_limit; |
248 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); | 249 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); |
249 | idx %= ring_limit; | 250 | idx %= ring_limit; |
250 | 251 | ||
252 | spin_lock_irqsave(&priv->lock, flags); | ||
251 | while (i != idx) { | 253 | while (i != idx) { |
252 | desc = &ring[i]; | 254 | desc = &ring[i]; |
253 | if (tx_buf[i]) | 255 | |
254 | if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) | 256 | skb = tx_buf[i]; |
255 | p54_free_skb(dev, tx_buf[i]); | ||
256 | tx_buf[i] = NULL; | 257 | tx_buf[i] = NULL; |
257 | 258 | ||
258 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | 259 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), |
@@ -263,17 +264,32 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
263 | desc->len = 0; | 264 | desc->len = 0; |
264 | desc->flags = 0; | 265 | desc->flags = 0; |
265 | 266 | ||
267 | if (skb && FREE_AFTER_TX(skb)) { | ||
268 | spin_unlock_irqrestore(&priv->lock, flags); | ||
269 | p54_free_skb(dev, skb); | ||
270 | spin_lock_irqsave(&priv->lock, flags); | ||
271 | } | ||
272 | |||
266 | i++; | 273 | i++; |
267 | i %= ring_limit; | 274 | i %= ring_limit; |
268 | } | 275 | } |
276 | spin_unlock_irqrestore(&priv->lock, flags); | ||
269 | } | 277 | } |
270 | 278 | ||
271 | static void p54p_rx_tasklet(unsigned long dev_id) | 279 | static void p54p_tasklet(unsigned long dev_id) |
272 | { | 280 | { |
273 | struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; | 281 | struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; |
274 | struct p54p_priv *priv = dev->priv; | 282 | struct p54p_priv *priv = dev->priv; |
275 | struct p54p_ring_control *ring_control = priv->ring_control; | 283 | struct p54p_ring_control *ring_control = priv->ring_control; |
276 | 284 | ||
285 | p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, | ||
286 | ARRAY_SIZE(ring_control->tx_mgmt), | ||
287 | priv->tx_buf_mgmt); | ||
288 | |||
289 | p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, | ||
290 | ARRAY_SIZE(ring_control->tx_data), | ||
291 | priv->tx_buf_data); | ||
292 | |||
277 | p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, | 293 | p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, |
278 | ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); | 294 | ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); |
279 | 295 | ||
@@ -288,38 +304,24 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) | |||
288 | { | 304 | { |
289 | struct ieee80211_hw *dev = dev_id; | 305 | struct ieee80211_hw *dev = dev_id; |
290 | struct p54p_priv *priv = dev->priv; | 306 | struct p54p_priv *priv = dev->priv; |
291 | struct p54p_ring_control *ring_control = priv->ring_control; | ||
292 | __le32 reg; | 307 | __le32 reg; |
293 | 308 | ||
294 | spin_lock(&priv->lock); | 309 | spin_lock(&priv->lock); |
295 | reg = P54P_READ(int_ident); | 310 | reg = P54P_READ(int_ident); |
296 | if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { | 311 | if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { |
297 | spin_unlock(&priv->lock); | 312 | goto out; |
298 | return IRQ_HANDLED; | ||
299 | } | 313 | } |
300 | |||
301 | P54P_WRITE(int_ack, reg); | 314 | P54P_WRITE(int_ack, reg); |
302 | 315 | ||
303 | reg &= P54P_READ(int_enable); | 316 | reg &= P54P_READ(int_enable); |
304 | 317 | ||
305 | if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { | 318 | if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) |
306 | p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, | 319 | tasklet_schedule(&priv->tasklet); |
307 | 3, ring_control->tx_mgmt, | 320 | else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) |
308 | ARRAY_SIZE(ring_control->tx_mgmt), | ||
309 | priv->tx_buf_mgmt); | ||
310 | |||
311 | p54p_check_tx_ring(dev, &priv->tx_idx_data, | ||
312 | 1, ring_control->tx_data, | ||
313 | ARRAY_SIZE(ring_control->tx_data), | ||
314 | priv->tx_buf_data); | ||
315 | |||
316 | tasklet_schedule(&priv->rx_tasklet); | ||
317 | |||
318 | } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) | ||
319 | complete(&priv->boot_comp); | 321 | complete(&priv->boot_comp); |
320 | 322 | ||
323 | out: | ||
321 | spin_unlock(&priv->lock); | 324 | spin_unlock(&priv->lock); |
322 | |||
323 | return reg ? IRQ_HANDLED : IRQ_NONE; | 325 | return reg ? IRQ_HANDLED : IRQ_NONE; |
324 | } | 326 | } |
325 | 327 | ||
@@ -368,7 +370,7 @@ static void p54p_stop(struct ieee80211_hw *dev) | |||
368 | unsigned int i; | 370 | unsigned int i; |
369 | struct p54p_desc *desc; | 371 | struct p54p_desc *desc; |
370 | 372 | ||
371 | tasklet_kill(&priv->rx_tasklet); | 373 | tasklet_kill(&priv->tasklet); |
372 | 374 | ||
373 | P54P_WRITE(int_enable, cpu_to_le32(0)); | 375 | P54P_WRITE(int_enable, cpu_to_le32(0)); |
374 | P54P_READ(int_enable); | 376 | P54P_READ(int_enable); |
@@ -559,7 +561,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
559 | priv->common.tx = p54p_tx; | 561 | priv->common.tx = p54p_tx; |
560 | 562 | ||
561 | spin_lock_init(&priv->lock); | 563 | spin_lock_init(&priv->lock); |
562 | tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); | 564 | tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev); |
563 | 565 | ||
564 | err = request_firmware(&priv->firmware, "isl3886pci", | 566 | err = request_firmware(&priv->firmware, "isl3886pci", |
565 | &priv->pdev->dev); | 567 | &priv->pdev->dev); |
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index fbb683953fb2..2feead617a3b 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h | |||
@@ -92,7 +92,7 @@ struct p54p_priv { | |||
92 | struct p54_common common; | 92 | struct p54_common common; |
93 | struct pci_dev *pdev; | 93 | struct pci_dev *pdev; |
94 | struct p54p_csr __iomem *map; | 94 | struct p54p_csr __iomem *map; |
95 | struct tasklet_struct rx_tasklet; | 95 | struct tasklet_struct tasklet; |
96 | const struct firmware *firmware; | 96 | const struct firmware *firmware; |
97 | spinlock_t lock; | 97 | spinlock_t lock; |
98 | struct p54p_ring_control *ring_control; | 98 | struct p54p_ring_control *ring_control; |
@@ -101,8 +101,8 @@ struct p54p_priv { | |||
101 | u32 rx_idx_mgmt, tx_idx_mgmt; | 101 | u32 rx_idx_mgmt, tx_idx_mgmt; |
102 | struct sk_buff *rx_buf_data[8]; | 102 | struct sk_buff *rx_buf_data[8]; |
103 | struct sk_buff *rx_buf_mgmt[4]; | 103 | struct sk_buff *rx_buf_mgmt[4]; |
104 | void *tx_buf_data[32]; | 104 | struct sk_buff *tx_buf_data[32]; |
105 | void *tx_buf_mgmt[4]; | 105 | struct sk_buff *tx_buf_mgmt[4]; |
106 | struct completion boot_comp; | 106 | struct completion boot_comp; |
107 | }; | 107 | }; |
108 | 108 | ||