aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ipw2100.c95
-rw-r--r--drivers/net/wireless/ipw2100.h4
2 files changed, 88 insertions, 11 deletions
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 84f63876bf75..d429fd576a66 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2390,15 +2390,6 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
2390 IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); 2390 IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
2391 return; 2391 return;
2392 } 2392 }
2393#ifdef CONFIG_IPW2100_MONITOR
2394 if (unlikely(priv->ieee->iw_mode == IW_MODE_MONITOR &&
2395 priv->config & CFG_CRC_CHECK &&
2396 status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
2397 IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
2398 priv->ieee->stats.rx_errors++;
2399 return;
2400 }
2401#endif
2402 2393
2403 if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && 2394 if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR &&
2404 !(priv->status & STATUS_ASSOCIATED))) { 2395 !(priv->status & STATUS_ASSOCIATED))) {
@@ -2446,6 +2437,88 @@ static void isr_rx(struct ipw2100_priv *priv, int i,
2446 priv->rx_queue.drv[i].host_addr = packet->dma_addr; 2437 priv->rx_queue.drv[i].host_addr = packet->dma_addr;
2447} 2438}
2448 2439
2440#ifdef CONFIG_IPW2100_MONITOR
2441
2442static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
2443 struct ieee80211_rx_stats *stats)
2444{
2445 struct ipw2100_status *status = &priv->status_queue.drv[i];
2446 struct ipw2100_rx_packet *packet = &priv->rx_buffers[i];
2447
2448 IPW_DEBUG_RX("Handler...\n");
2449
2450 /* Magic struct that slots into the radiotap header -- no reason
2451 * to build this manually element by element, we can write it much
2452 * more efficiently than we can parse it. ORDER MATTERS HERE */
2453 struct ipw_rt_hdr {
2454 struct ieee80211_radiotap_header rt_hdr;
2455 s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
2456 } *ipw_rt;
2457
2458 if (unlikely(status->frame_size > skb_tailroom(packet->skb) - sizeof(struct ipw_rt_hdr))) {
2459 IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!"
2460 " Dropping.\n",
2461 priv->net_dev->name,
2462 status->frame_size, skb_tailroom(packet->skb));
2463 priv->ieee->stats.rx_errors++;
2464 return;
2465 }
2466
2467 if (unlikely(!netif_running(priv->net_dev))) {
2468 priv->ieee->stats.rx_errors++;
2469 priv->wstats.discard.misc++;
2470 IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
2471 return;
2472 }
2473
2474 if (unlikely(priv->config & CFG_CRC_CHECK &&
2475 status->flags & IPW_STATUS_FLAG_CRC_ERROR)) {
2476 IPW_DEBUG_RX("CRC error in packet. Dropping.\n");
2477 priv->ieee->stats.rx_errors++;
2478 return;
2479 }
2480
2481 pci_unmap_single(priv->pci_dev,
2482 packet->dma_addr,
2483 sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE);
2484 memmove(packet->skb->data + sizeof(struct ipw_rt_hdr),
2485 packet->skb->data, status->frame_size);
2486
2487 ipw_rt = (struct ipw_rt_hdr *) packet->skb->data;
2488
2489 ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
2490 ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
2491 ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */
2492
2493 ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL;
2494
2495 ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM;
2496
2497 skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr));
2498
2499 if (!ieee80211_rx(priv->ieee, packet->skb, stats)) {
2500 priv->ieee->stats.rx_errors++;
2501
2502 /* ieee80211_rx failed, so it didn't free the SKB */
2503 dev_kfree_skb_any(packet->skb);
2504 packet->skb = NULL;
2505 }
2506
2507 /* We need to allocate a new SKB and attach it to the RDB. */
2508 if (unlikely(ipw2100_alloc_skb(priv, packet))) {
2509 IPW_DEBUG_WARNING(
2510 "%s: Unable to allocate SKB onto RBD ring - disabling "
2511 "adapter.\n", priv->net_dev->name);
2512 /* TODO: schedule adapter shutdown */
2513 IPW_DEBUG_INFO("TODO: Shutdown adapter...\n");
2514 }
2515
2516 /* Update the RDB entry */
2517 priv->rx_queue.drv[i].host_addr = packet->dma_addr;
2518}
2519
2520#endif
2521
2449static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) 2522static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
2450{ 2523{
2451 struct ipw2100_status *status = &priv->status_queue.drv[i]; 2524 struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2577,7 +2650,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
2577 case P8023_DATA_VAL: 2650 case P8023_DATA_VAL:
2578#ifdef CONFIG_IPW2100_MONITOR 2651#ifdef CONFIG_IPW2100_MONITOR
2579 if (priv->ieee->iw_mode == IW_MODE_MONITOR) { 2652 if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
2580 isr_rx(priv, i, &stats); 2653 isr_rx_monitor(priv, i, &stats);
2581 break; 2654 break;
2582 } 2655 }
2583#endif 2656#endif
@@ -3882,7 +3955,7 @@ static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode)
3882#ifdef CONFIG_IPW2100_MONITOR 3955#ifdef CONFIG_IPW2100_MONITOR
3883 case IW_MODE_MONITOR: 3956 case IW_MODE_MONITOR:
3884 priv->last_mode = priv->ieee->iw_mode; 3957 priv->last_mode = priv->ieee->iw_mode;
3885 priv->net_dev->type = ARPHRD_IEEE80211; 3958 priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
3886 break; 3959 break;
3887#endif /* CONFIG_IPW2100_MONITOR */ 3960#endif /* CONFIG_IPW2100_MONITOR */
3888 } 3961 }
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 948d426fcf9d..6f0b40f96abd 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -41,6 +41,10 @@
41 41
42#include <net/ieee80211.h> 42#include <net/ieee80211.h>
43 43
44#ifdef CONFIG_IPW2100_MONITOR
45#include <net/ieee80211_radiotap.h>
46#endif
47
44#include <linux/workqueue.h> 48#include <linux/workqueue.h>
45 49
46struct ipw2100_priv; 50struct ipw2100_priv;