aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/p54pci.c')
-rw-r--r--drivers/net/wireless/p54/p54pci.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index d348c265e867..c24067f1a0cb 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/slab.h>
18#include <linux/firmware.h> 19#include <linux/firmware.h>
19#include <linux/etherdevice.h> 20#include <linux/etherdevice.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
@@ -31,7 +32,7 @@ MODULE_LICENSE("GPL");
31MODULE_ALIAS("prism54pci"); 32MODULE_ALIAS("prism54pci");
32MODULE_FIRMWARE("isl3886pci"); 33MODULE_FIRMWARE("isl3886pci");
33 34
34static struct pci_device_id p54p_table[] __devinitdata = { 35static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
35 /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ 36 /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
36 { PCI_DEVICE(0x1260, 0x3890) }, 37 { PCI_DEVICE(0x1260, 0x3890) },
37 /* 3COM 3CRWE154G72 Wireless LAN adapter */ 38 /* 3COM 3CRWE154G72 Wireless LAN adapter */
@@ -157,6 +158,14 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev,
157 skb_tail_pointer(skb), 158 skb_tail_pointer(skb),
158 priv->common.rx_mtu + 32, 159 priv->common.rx_mtu + 32,
159 PCI_DMA_FROMDEVICE); 160 PCI_DMA_FROMDEVICE);
161
162 if (pci_dma_mapping_error(priv->pdev, mapping)) {
163 dev_kfree_skb_any(skb);
164 dev_err(&priv->pdev->dev,
165 "RX DMA Mapping error\n");
166 break;
167 }
168
160 desc->host_addr = cpu_to_le32(mapping); 169 desc->host_addr = cpu_to_le32(mapping);
161 desc->device_addr = 0; // FIXME: necessary? 170 desc->device_addr = 0; // FIXME: necessary?
162 desc->len = cpu_to_le16(priv->common.rx_mtu + 32); 171 desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
@@ -197,6 +206,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
197 i %= ring_limit; 206 i %= ring_limit;
198 continue; 207 continue;
199 } 208 }
209
210 if (unlikely(len > priv->common.rx_mtu)) {
211 if (net_ratelimit())
212 dev_err(&priv->pdev->dev, "rx'd frame size "
213 "exceeds length threshold.\n");
214
215 len = priv->common.rx_mtu;
216 }
200 skb_put(skb, len); 217 skb_put(skb, len);
201 218
202 if (p54_rx(dev, skb)) { 219 if (p54_rx(dev, skb)) {
@@ -218,25 +235,24 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
218 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); 235 p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
219} 236}
220 237
221/* caller must hold priv->lock */
222static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, 238static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
223 int ring_index, struct p54p_desc *ring, u32 ring_limit, 239 int ring_index, struct p54p_desc *ring, u32 ring_limit,
224 void **tx_buf) 240 struct sk_buff **tx_buf)
225{ 241{
226 struct p54p_priv *priv = dev->priv; 242 struct p54p_priv *priv = dev->priv;
227 struct p54p_ring_control *ring_control = priv->ring_control; 243 struct p54p_ring_control *ring_control = priv->ring_control;
228 struct p54p_desc *desc; 244 struct p54p_desc *desc;
245 struct sk_buff *skb;
229 u32 idx, i; 246 u32 idx, i;
230 247
231 i = (*index) % ring_limit; 248 i = (*index) % ring_limit;
232 (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); 249 (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
233 idx %= ring_limit; 250 idx %= ring_limit;
234 251
235 while (i != idx) { 252 while (i != idx) {
236 desc = &ring[i]; 253 desc = &ring[i];
237 if (tx_buf[i]) 254
238 if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) 255 skb = tx_buf[i];
239 p54_free_skb(dev, tx_buf[i]);
240 tx_buf[i] = NULL; 256 tx_buf[i] = NULL;
241 257
242 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), 258 pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -247,17 +263,28 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
247 desc->len = 0; 263 desc->len = 0;
248 desc->flags = 0; 264 desc->flags = 0;
249 265
266 if (skb && FREE_AFTER_TX(skb))
267 p54_free_skb(dev, skb);
268
250 i++; 269 i++;
251 i %= ring_limit; 270 i %= ring_limit;
252 } 271 }
253} 272}
254 273
255static void p54p_rx_tasklet(unsigned long dev_id) 274static void p54p_tasklet(unsigned long dev_id)
256{ 275{
257 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; 276 struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id;
258 struct p54p_priv *priv = dev->priv; 277 struct p54p_priv *priv = dev->priv;
259 struct p54p_ring_control *ring_control = priv->ring_control; 278 struct p54p_ring_control *ring_control = priv->ring_control;
260 279
280 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
281 ARRAY_SIZE(ring_control->tx_mgmt),
282 priv->tx_buf_mgmt);
283
284 p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
285 ARRAY_SIZE(ring_control->tx_data),
286 priv->tx_buf_data);
287
261 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, 288 p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
262 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); 289 ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
263 290
@@ -272,59 +299,49 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
272{ 299{
273 struct ieee80211_hw *dev = dev_id; 300 struct ieee80211_hw *dev = dev_id;
274 struct p54p_priv *priv = dev->priv; 301 struct p54p_priv *priv = dev->priv;
275 struct p54p_ring_control *ring_control = priv->ring_control;
276 __le32 reg; 302 __le32 reg;
277 303
278 spin_lock(&priv->lock);
279 reg = P54P_READ(int_ident); 304 reg = P54P_READ(int_ident);
280 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { 305 if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
281 spin_unlock(&priv->lock); 306 goto out;
282 return IRQ_HANDLED;
283 } 307 }
284
285 P54P_WRITE(int_ack, reg); 308 P54P_WRITE(int_ack, reg);
286 309
287 reg &= P54P_READ(int_enable); 310 reg &= P54P_READ(int_enable);
288 311
289 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { 312 if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE))
290 p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 313 tasklet_schedule(&priv->tasklet);
291 3, ring_control->tx_mgmt, 314 else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
292 ARRAY_SIZE(ring_control->tx_mgmt),
293 priv->tx_buf_mgmt);
294
295 p54p_check_tx_ring(dev, &priv->tx_idx_data,
296 1, ring_control->tx_data,
297 ARRAY_SIZE(ring_control->tx_data),
298 priv->tx_buf_data);
299
300 tasklet_schedule(&priv->rx_tasklet);
301
302 } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
303 complete(&priv->boot_comp); 315 complete(&priv->boot_comp);
304 316
305 spin_unlock(&priv->lock); 317out:
306
307 return reg ? IRQ_HANDLED : IRQ_NONE; 318 return reg ? IRQ_HANDLED : IRQ_NONE;
308} 319}
309 320
310static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) 321static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
311{ 322{
323 unsigned long flags;
312 struct p54p_priv *priv = dev->priv; 324 struct p54p_priv *priv = dev->priv;
313 struct p54p_ring_control *ring_control = priv->ring_control; 325 struct p54p_ring_control *ring_control = priv->ring_control;
314 unsigned long flags;
315 struct p54p_desc *desc; 326 struct p54p_desc *desc;
316 dma_addr_t mapping; 327 dma_addr_t mapping;
317 u32 device_idx, idx, i; 328 u32 device_idx, idx, i;
318 329
319 spin_lock_irqsave(&priv->lock, flags); 330 spin_lock_irqsave(&priv->lock, flags);
320
321 device_idx = le32_to_cpu(ring_control->device_idx[1]); 331 device_idx = le32_to_cpu(ring_control->device_idx[1]);
322 idx = le32_to_cpu(ring_control->host_idx[1]); 332 idx = le32_to_cpu(ring_control->host_idx[1]);
323 i = idx % ARRAY_SIZE(ring_control->tx_data); 333 i = idx % ARRAY_SIZE(ring_control->tx_data);
324 334
325 priv->tx_buf_data[i] = skb;
326 mapping = pci_map_single(priv->pdev, skb->data, skb->len, 335 mapping = pci_map_single(priv->pdev, skb->data, skb->len,
327 PCI_DMA_TODEVICE); 336 PCI_DMA_TODEVICE);
337 if (pci_dma_mapping_error(priv->pdev, mapping)) {
338 spin_unlock_irqrestore(&priv->lock, flags);
339 p54_free_skb(dev, skb);
340 dev_err(&priv->pdev->dev, "TX DMA mapping error\n");
341 return ;
342 }
343 priv->tx_buf_data[i] = skb;
344
328 desc = &ring_control->tx_data[i]; 345 desc = &ring_control->tx_data[i];
329 desc->host_addr = cpu_to_le32(mapping); 346 desc->host_addr = cpu_to_le32(mapping);
330 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id; 347 desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
@@ -346,14 +363,14 @@ static void p54p_stop(struct ieee80211_hw *dev)
346 unsigned int i; 363 unsigned int i;
347 struct p54p_desc *desc; 364 struct p54p_desc *desc;
348 365
349 tasklet_kill(&priv->rx_tasklet);
350
351 P54P_WRITE(int_enable, cpu_to_le32(0)); 366 P54P_WRITE(int_enable, cpu_to_le32(0));
352 P54P_READ(int_enable); 367 P54P_READ(int_enable);
353 udelay(10); 368 udelay(10);
354 369
355 free_irq(priv->pdev->irq, dev); 370 free_irq(priv->pdev->irq, dev);
356 371
372 tasklet_kill(&priv->tasklet);
373
357 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); 374 P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
358 375
359 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { 376 for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) {
@@ -411,7 +428,7 @@ static int p54p_open(struct ieee80211_hw *dev)
411 int err; 428 int err;
412 429
413 init_completion(&priv->boot_comp); 430 init_completion(&priv->boot_comp);
414 err = request_irq(priv->pdev->irq, &p54p_interrupt, 431 err = request_irq(priv->pdev->irq, p54p_interrupt,
415 IRQF_SHARED, "p54pci", dev); 432 IRQF_SHARED, "p54pci", dev);
416 if (err) { 433 if (err) {
417 dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); 434 dev_err(&priv->pdev->dev, "failed to register IRQ handler\n");
@@ -537,7 +554,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
537 priv->common.tx = p54p_tx; 554 priv->common.tx = p54p_tx;
538 555
539 spin_lock_init(&priv->lock); 556 spin_lock_init(&priv->lock);
540 tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); 557 tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev);
541 558
542 err = request_firmware(&priv->firmware, "isl3886pci", 559 err = request_firmware(&priv->firmware, "isl3886pci",
543 &priv->pdev->dev); 560 &priv->pdev->dev);