aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/p54/p54pci.c56
-rw-r--r--drivers/net/wireless/p54/p54pci.h6
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 */
238static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, 237static 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
271static void p54p_rx_tasklet(unsigned long dev_id) 279static 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
323out:
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