aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2007-12-19 22:27:32 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:07:53 -0500
commit12342c475f5de17071eaf24ea2938ba8dfe285f2 (patch)
treea2cdfd191069397e093f2410009092e7e96c9325 /drivers
parent7e94041ca17685cf12c658b8edc008dd0bdb00c7 (diff)
iwlwifi: proper monitor support
This patch changes the iwlwifi driver to properly support monitor interfaces after the filter flags change. The patch is originally created by Johannes Berg for iwl4965. I fixed some of the comments and created a similar patch for iwl3945. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c120
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h36
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c120
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c109
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c90
6 files changed, 238 insertions, 261 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 7d15b33b9dcd..a793cd11f738 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -35,9 +35,9 @@
35#include <linux/netdevice.h> 35#include <linux/netdevice.h>
36#include <linux/wireless.h> 36#include <linux/wireless.h>
37#include <linux/firmware.h> 37#include <linux/firmware.h>
38#include <net/mac80211.h>
39
40#include <linux/etherdevice.h> 38#include <linux/etherdevice.h>
39#include <asm/unaligned.h>
40#include <net/mac80211.h>
41 41
42#include "iwl-3945.h" 42#include "iwl-3945.h"
43#include "iwl-helpers.h" 43#include "iwl-helpers.h"
@@ -238,10 +238,102 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b
238 priv->last_statistics_time = jiffies; 238 priv->last_statistics_time = jiffies;
239} 239}
240 240
241void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb,
242 struct iwl3945_rx_frame_hdr *rx_hdr,
243 struct ieee80211_rx_status *stats)
244{
245 /* First cache any information we need before we overwrite
246 * the information provided in the skb from the hardware */
247 s8 signal = stats->ssi;
248 s8 noise = 0;
249 int rate = stats->rate;
250 u64 tsf = stats->mactime;
251 __le16 phy_flags_hw = rx_hdr->phy_flags;
252
253 struct iwl3945_rt_rx_hdr {
254 struct ieee80211_radiotap_header rt_hdr;
255 __le64 rt_tsf; /* TSF */
256 u8 rt_flags; /* radiotap packet flags */
257 u8 rt_rate; /* rate in 500kb/s */
258 __le16 rt_channelMHz; /* channel in MHz */
259 __le16 rt_chbitmask; /* channel bitfield */
260 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
261 s8 rt_dbmnoise;
262 u8 rt_antenna; /* antenna number */
263 } __attribute__ ((packed)) *iwl3945_rt;
264
265 if (skb_headroom(skb) < sizeof(*iwl3945_rt)) {
266 if (net_ratelimit())
267 printk(KERN_ERR "not enough headroom [%d] for "
268 "radiotap head [%d]\n",
269 skb_headroom(skb), sizeof(*iwl3945_rt));
270 return;
271 }
272
273 /* put radiotap header in front of 802.11 header and data */
274 iwl3945_rt = (void *)skb_push(skb, sizeof(*iwl3945_rt));
275
276 /* initialise radiotap header */
277 iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
278 iwl3945_rt->rt_hdr.it_pad = 0;
279
280 /* total header + data */
281 put_unaligned(cpu_to_le16(sizeof(*iwl3945_rt)),
282 &iwl3945_rt->rt_hdr.it_len);
283
284 /* Indicate all the fields we add to the radiotap header */
285 put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
286 (1 << IEEE80211_RADIOTAP_FLAGS) |
287 (1 << IEEE80211_RADIOTAP_RATE) |
288 (1 << IEEE80211_RADIOTAP_CHANNEL) |
289 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
290 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
291 (1 << IEEE80211_RADIOTAP_ANTENNA)),
292 &iwl3945_rt->rt_hdr.it_present);
293
294 /* Zero the flags, we'll add to them as we go */
295 iwl3945_rt->rt_flags = 0;
296
297 put_unaligned(cpu_to_le64(tsf), &iwl3945_rt->rt_tsf);
298
299 iwl3945_rt->rt_dbmsignal = signal;
300 iwl3945_rt->rt_dbmnoise = noise;
301
302 /* Convert the channel frequency and set the flags */
303 put_unaligned(cpu_to_le16(stats->freq), &iwl3945_rt->rt_channelMHz);
304 if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
305 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
306 IEEE80211_CHAN_5GHZ),
307 &iwl3945_rt->rt_chbitmask);
308 else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
309 put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
310 IEEE80211_CHAN_2GHZ),
311 &iwl3945_rt->rt_chbitmask);
312 else /* 802.11g */
313 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
314 IEEE80211_CHAN_2GHZ),
315 &iwl3945_rt->rt_chbitmask);
316
317 rate = iwl3945_rate_index_from_plcp(rate);
318 if (rate == -1)
319 iwl3945_rt->rt_rate = 0;
320 else
321 iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
322
323 /* antenna number */
324 iwl3945_rt->rt_antenna =
325 le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
326
327 /* set the preamble flag if we have it */
328 if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
329 iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
330
331 stats->flag |= RX_FLAG_RADIOTAP;
332}
333
241static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, 334static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
242 struct iwl3945_rx_mem_buffer *rxb, 335 struct iwl3945_rx_mem_buffer *rxb,
243 struct ieee80211_rx_status *stats, 336 struct ieee80211_rx_status *stats)
244 u16 phy_flags)
245{ 337{
246 struct ieee80211_hdr *hdr; 338 struct ieee80211_hdr *hdr;
247 struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; 339 struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
@@ -261,15 +353,6 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
261 ("Dropping packet while interface is not open.\n"); 353 ("Dropping packet while interface is not open.\n");
262 return; 354 return;
263 } 355 }
264 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
265 if (iwl3945_param_hwcrypto)
266 iwl3945_set_decrypted_flag(priv, rxb->skb,
267 le32_to_cpu(rx_end->status),
268 stats);
269 iwl3945_handle_data_packet_monitor(priv, rxb, IWL_RX_DATA(pkt),
270 len, stats, phy_flags);
271 return;
272 }
273 356
274 skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); 357 skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
275 /* Set the size of the skb to the size of the frame */ 358 /* Set the size of the skb to the size of the frame */
@@ -281,6 +364,9 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
281 iwl3945_set_decrypted_flag(priv, rxb->skb, 364 iwl3945_set_decrypted_flag(priv, rxb->skb,
282 le32_to_cpu(rx_end->status), stats); 365 le32_to_cpu(rx_end->status), stats);
283 366
367 if (priv->add_radiotap)
368 iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
369
284 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); 370 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
285 rxb->skb = NULL; 371 rxb->skb = NULL;
286} 372}
@@ -295,7 +381,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
295 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); 381 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
296 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); 382 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
297 struct ieee80211_hdr *header; 383 struct ieee80211_hdr *header;
298 u16 phy_flags = le16_to_cpu(rx_hdr->phy_flags);
299 u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); 384 u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
300 u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); 385 u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
301 struct ieee80211_rx_status stats = { 386 struct ieee80211_rx_status stats = {
@@ -325,7 +410,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
325 } 410 }
326 411
327 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { 412 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
328 iwl3945_handle_data_packet(priv, 1, rxb, &stats, phy_flags); 413 iwl3945_handle_data_packet(priv, 1, rxb, &stats);
329 return; 414 return;
330 } 415 }
331 416
@@ -479,7 +564,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
479 } 564 }
480 } 565 }
481 566
482 iwl3945_handle_data_packet(priv, 0, rxb, &stats, phy_flags); 567 iwl3945_handle_data_packet(priv, 0, rxb, &stats);
483 break; 568 break;
484 569
485 case IEEE80211_FTYPE_CTL: 570 case IEEE80211_FTYPE_CTL:
@@ -496,8 +581,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
496 print_mac(mac2, header->addr2), 581 print_mac(mac2, header->addr2),
497 print_mac(mac3, header->addr3)); 582 print_mac(mac3, header->addr3));
498 else 583 else
499 iwl3945_handle_data_packet(priv, 1, rxb, &stats, 584 iwl3945_handle_data_packet(priv, 1, rxb, &stats);
500 phy_flags);
501 break; 585 break;
502 } 586 }
503 } 587 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bfa260654c5a..f1aa4dc5aac4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -91,29 +91,6 @@ struct iwl3945_rx_mem_buffer {
91 struct list_head list; 91 struct list_head list;
92}; 92};
93 93
94struct iwl3945_rt_rx_hdr {
95 struct ieee80211_radiotap_header rt_hdr;
96 __le64 rt_tsf; /* TSF */
97 u8 rt_flags; /* radiotap packet flags */
98 u8 rt_rate; /* rate in 500kb/s */
99 __le16 rt_channelMHz; /* channel in MHz */
100 __le16 rt_chbitmask; /* channel bitfield */
101 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
102 s8 rt_dbmnoise;
103 u8 rt_antenna; /* antenna number */
104 u8 payload[0]; /* payload... */
105} __attribute__ ((packed));
106
107struct iwl3945_rt_tx_hdr {
108 struct ieee80211_radiotap_header rt_hdr;
109 u8 rt_rate; /* rate in 500kb/s */
110 __le16 rt_channel; /* channel in mHz */
111 __le16 rt_chbitmask; /* channel bitfield */
112 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
113 u8 rt_antenna; /* antenna number */
114 u8 payload[0]; /* payload... */
115} __attribute__ ((packed));
116
117/* 94/*
118 * Generic queue structure 95 * Generic queue structure
119 * 96 *
@@ -531,7 +508,7 @@ struct iwl3945_ibss_seq {
531}; 508};
532 509
533/** 510/**
534 * struct iwl4965_driver_hw_info 511 * struct iwl3945_driver_hw_info
535 * @max_txq_num: Max # Tx queues supported 512 * @max_txq_num: Max # Tx queues supported
536 * @ac_queue_count: # Tx queues for EDCA Access Categories (AC) 513 * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
537 * @tx_cmd_len: Size of Tx command (but not including frame itself) 514 * @tx_cmd_len: Size of Tx command (but not including frame itself)
@@ -725,6 +702,7 @@ struct iwl3945_priv {
725 702
726 u8 phymode; 703 u8 phymode;
727 int alloc_rxb_skb; 704 int alloc_rxb_skb;
705 bool add_radiotap;
728 706
729 void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, 707 void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
730 struct iwl3945_rx_mem_buffer *rxb); 708 struct iwl3945_rx_mem_buffer *rxb);
@@ -980,6 +958,16 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
980 return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; 958 return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
981} 959}
982 960
961static inline int iwl3945_rate_index_from_plcp(int plcp)
962{
963 int i;
964
965 for (i = 0; i < IWL_RATE_COUNT; i++)
966 if (iwl3945_rates[i].plcp == plcp)
967 return i;
968 return -1;
969}
970
983extern const struct iwl3945_channel_info *iwl3945_get_channel_info( 971extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
984 const struct iwl3945_priv *priv, int phymode, u16 channel); 972 const struct iwl3945_priv *priv, int phymode, u16 channel);
985 973
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index f65fd6e5fecc..74999af37914 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -36,6 +36,7 @@
36#include <linux/wireless.h> 36#include <linux/wireless.h>
37#include <net/mac80211.h> 37#include <net/mac80211.h>
38#include <linux/etherdevice.h> 38#include <linux/etherdevice.h>
39#include <asm/unaligned.h>
39 40
40#include "iwl-4965.h" 41#include "iwl-4965.h"
41#include "iwl-helpers.h" 42#include "iwl-helpers.h"
@@ -3588,6 +3589,111 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b
3588 queue_work(priv->workqueue, &priv->txpower_work); 3589 queue_work(priv->workqueue, &priv->txpower_work);
3589} 3590}
3590 3591
3592static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
3593 struct sk_buff *skb,
3594 struct iwl4965_rx_phy_res *rx_start,
3595 struct ieee80211_rx_status *stats,
3596 u32 ampdu_status)
3597{
3598 s8 signal = stats->ssi;
3599 s8 noise = 0;
3600 int rate = stats->rate;
3601 u64 tsf = stats->mactime;
3602 __le16 phy_flags_hw = rx_start->phy_flags;
3603 struct iwl4965_rt_rx_hdr {
3604 struct ieee80211_radiotap_header rt_hdr;
3605 __le64 rt_tsf; /* TSF */
3606 u8 rt_flags; /* radiotap packet flags */
3607 u8 rt_rate; /* rate in 500kb/s */
3608 __le16 rt_channelMHz; /* channel in MHz */
3609 __le16 rt_chbitmask; /* channel bitfield */
3610 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
3611 s8 rt_dbmnoise;
3612 u8 rt_antenna; /* antenna number */
3613 } __attribute__ ((packed)) *iwl4965_rt;
3614
3615 /* TODO: We won't have enough headroom for HT frames. Fix it later. */
3616 if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
3617 if (net_ratelimit())
3618 printk(KERN_ERR "not enough headroom [%d] for "
3619 "radiotap head [%d]\n",
3620 skb_headroom(skb), sizeof(*iwl4965_rt));
3621 return;
3622 }
3623
3624 /* put radiotap header in front of 802.11 header and data */
3625 iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
3626
3627 /* initialise radiotap header */
3628 iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
3629 iwl4965_rt->rt_hdr.it_pad = 0;
3630
3631 /* total header + data */
3632 put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
3633 &iwl4965_rt->rt_hdr.it_len);
3634
3635 /* Indicate all the fields we add to the radiotap header */
3636 put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
3637 (1 << IEEE80211_RADIOTAP_FLAGS) |
3638 (1 << IEEE80211_RADIOTAP_RATE) |
3639 (1 << IEEE80211_RADIOTAP_CHANNEL) |
3640 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
3641 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
3642 (1 << IEEE80211_RADIOTAP_ANTENNA)),
3643 &iwl4965_rt->rt_hdr.it_present);
3644
3645 /* Zero the flags, we'll add to them as we go */
3646 iwl4965_rt->rt_flags = 0;
3647
3648 put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf);
3649
3650 iwl4965_rt->rt_dbmsignal = signal;
3651 iwl4965_rt->rt_dbmnoise = noise;
3652
3653 /* Convert the channel frequency and set the flags */
3654 put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz);
3655 if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
3656 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
3657 IEEE80211_CHAN_5GHZ),
3658 &iwl4965_rt->rt_chbitmask);
3659 else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
3660 put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
3661 IEEE80211_CHAN_2GHZ),
3662 &iwl4965_rt->rt_chbitmask);
3663 else /* 802.11g */
3664 put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
3665 IEEE80211_CHAN_2GHZ),
3666 &iwl4965_rt->rt_chbitmask);
3667
3668 rate = iwl4965_rate_index_from_plcp(rate);
3669 if (rate == -1)
3670 iwl4965_rt->rt_rate = 0;
3671 else
3672 iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
3673
3674 /*
3675 * "antenna number"
3676 *
3677 * It seems that the antenna field in the phy flags value
3678 * is actually a bitfield. This is undefined by radiotap,
3679 * it wants an actual antenna number but I always get "7"
3680 * for most legacy frames I receive indicating that the
3681 * same frame was received on all three RX chains.
3682 *
3683 * I think this field should be removed in favour of a
3684 * new 802.11n radiotap field "RX chains" that is defined
3685 * as a bitmask.
3686 */
3687 iwl4965_rt->rt_antenna =
3688 le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
3689
3690 /* set the preamble flag if appropriate */
3691 if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
3692 iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
3693
3694 stats->flag |= RX_FLAG_RADIOTAP;
3695}
3696
3591static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data, 3697static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
3592 int include_phy, 3698 int include_phy,
3593 struct iwl4965_rx_mem_buffer *rxb, 3699 struct iwl4965_rx_mem_buffer *rxb,
@@ -3630,8 +3736,7 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
3630 rx_end = (__le32 *) (((u8 *) hdr) + len); 3736 rx_end = (__le32 *) (((u8 *) hdr) + len);
3631 } 3737 }
3632 if (len > priv->hw_setting.max_pkt_size || len < 16) { 3738 if (len > priv->hw_setting.max_pkt_size || len < 16) {
3633 IWL_WARNING("byte count out of range [16,4K]" 3739 IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
3634 " : %d\n", len);
3635 return; 3740 return;
3636 } 3741 }
3637 3742
@@ -3649,20 +3754,15 @@ static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
3649 return; 3754 return;
3650 } 3755 }
3651 3756
3652 if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
3653 if (iwl4965_param_hwcrypto)
3654 iwl4965_set_decrypted_flag(priv, rxb->skb,
3655 ampdu_status, stats);
3656 iwl4965_handle_data_packet_monitor(priv, rxb, hdr, len, stats, 0);
3657 return;
3658 }
3659
3660 stats->flag = 0; 3757 stats->flag = 0;
3661 hdr = (struct ieee80211_hdr *)rxb->skb->data; 3758 hdr = (struct ieee80211_hdr *)rxb->skb->data;
3662 3759
3663 if (iwl4965_param_hwcrypto) 3760 if (iwl4965_param_hwcrypto)
3664 iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); 3761 iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
3665 3762
3763 if (priv->add_radiotap)
3764 iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
3765
3666 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); 3766 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
3667 priv->alloc_rxb_skb--; 3767 priv->alloc_rxb_skb--;
3668 rxb->skb = NULL; 3768 rxb->skb = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 267ae75254fe..9a975efc9460 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -91,29 +91,6 @@ struct iwl4965_rx_mem_buffer {
91 struct list_head list; 91 struct list_head list;
92}; 92};
93 93
94struct iwl4965_rt_rx_hdr {
95 struct ieee80211_radiotap_header rt_hdr;
96 __le64 rt_tsf; /* TSF */
97 u8 rt_flags; /* radiotap packet flags */
98 u8 rt_rate; /* rate in 500kb/s */
99 __le16 rt_channelMHz; /* channel in MHz */
100 __le16 rt_chbitmask; /* channel bitfield */
101 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
102 s8 rt_dbmnoise;
103 u8 rt_antenna; /* antenna number */
104 u8 payload[0]; /* payload... */
105} __attribute__ ((packed));
106
107struct iwl4965_rt_tx_hdr {
108 struct ieee80211_radiotap_header rt_hdr;
109 u8 rt_rate; /* rate in 500kb/s */
110 __le16 rt_channel; /* channel in mHz */
111 __le16 rt_chbitmask; /* channel bitfield */
112 s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
113 u8 rt_antenna; /* antenna number */
114 u8 payload[0]; /* payload... */
115} __attribute__ ((packed));
116
117/* 94/*
118 * Generic queue structure 95 * Generic queue structure
119 * 96 *
@@ -1054,6 +1031,7 @@ struct iwl4965_priv {
1054 1031
1055 u8 phymode; 1032 u8 phymode;
1056 int alloc_rxb_skb; 1033 int alloc_rxb_skb;
1034 bool add_radiotap;
1057 1035
1058 void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv, 1036 void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
1059 struct iwl4965_rx_mem_buffer *rxb); 1037 struct iwl4965_rx_mem_buffer *rxb);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c366ad55f70e..40b69182e4dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1497,16 +1497,6 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
1497 return priv->ibss_beacon->len; 1497 return priv->ibss_beacon->len;
1498} 1498}
1499 1499
1500static int iwl3945_rate_index_from_plcp(int plcp)
1501{
1502 int i = 0;
1503
1504 for (i = 0; i < IWL_RATE_COUNT; i++)
1505 if (iwl3945_rates[i].plcp == plcp)
1506 return i;
1507 return -1;
1508}
1509
1510static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) 1500static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
1511{ 1501{
1512 u8 i; 1502 u8 i;
@@ -3121,94 +3111,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
3121 } 3111 }
3122} 3112}
3123 3113
3124void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
3125 struct iwl3945_rx_mem_buffer *rxb,
3126 void *data, short len,
3127 struct ieee80211_rx_status *stats,
3128 u16 phy_flags)
3129{
3130 struct iwl3945_rt_rx_hdr *iwl3945_rt;
3131
3132 /* First cache any information we need before we overwrite
3133 * the information provided in the skb from the hardware */
3134 s8 signal = stats->ssi;
3135 s8 noise = 0;
3136 int rate = stats->rate;
3137 u64 tsf = stats->mactime;
3138 __le16 phy_flags_hw = cpu_to_le16(phy_flags);
3139
3140 /* We received data from the HW, so stop the watchdog */
3141 if (len > IWL_RX_BUF_SIZE - sizeof(*iwl3945_rt)) {
3142 IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
3143 return;
3144 }
3145
3146 /* copy the frame data to write after where the radiotap header goes */
3147 iwl3945_rt = (void *)rxb->skb->data;
3148 memmove(iwl3945_rt->payload, data, len);
3149
3150 iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
3151 iwl3945_rt->rt_hdr.it_pad = 0; /* always good to zero */
3152
3153 /* total header + data */
3154 iwl3945_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl3945_rt));
3155
3156 /* Set the size of the skb to the size of the frame */
3157 skb_put(rxb->skb, sizeof(*iwl3945_rt) + len);
3158
3159 /* Big bitfield of all the fields we provide in radiotap */
3160 iwl3945_rt->rt_hdr.it_present =
3161 cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
3162 (1 << IEEE80211_RADIOTAP_FLAGS) |
3163 (1 << IEEE80211_RADIOTAP_RATE) |
3164 (1 << IEEE80211_RADIOTAP_CHANNEL) |
3165 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
3166 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
3167 (1 << IEEE80211_RADIOTAP_ANTENNA));
3168
3169 /* Zero the flags, we'll add to them as we go */
3170 iwl3945_rt->rt_flags = 0;
3171
3172 iwl3945_rt->rt_tsf = cpu_to_le64(tsf);
3173
3174 /* Convert to dBm */
3175 iwl3945_rt->rt_dbmsignal = signal;
3176 iwl3945_rt->rt_dbmnoise = noise;
3177
3178 /* Convert the channel frequency and set the flags */
3179 iwl3945_rt->rt_channelMHz = cpu_to_le16(stats->freq);
3180 if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
3181 iwl3945_rt->rt_chbitmask =
3182 cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
3183 else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
3184 iwl3945_rt->rt_chbitmask =
3185 cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
3186 else /* 802.11g */
3187 iwl3945_rt->rt_chbitmask =
3188 cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
3189
3190 rate = iwl3945_rate_index_from_plcp(rate);
3191 if (rate == -1)
3192 iwl3945_rt->rt_rate = 0;
3193 else
3194 iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
3195
3196 /* antenna number */
3197 iwl3945_rt->rt_antenna =
3198 le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
3199
3200 /* set the preamble flag if we have it */
3201 if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
3202 iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
3203
3204 IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
3205
3206 stats->flag |= RX_FLAG_RADIOTAP;
3207 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
3208 rxb->skb = NULL;
3209}
3210
3211
3212#define IWL_PACKET_RETRY_TIME HZ 3114#define IWL_PACKET_RETRY_TIME HZ
3213 3115
3214int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) 3116int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
@@ -4147,6 +4049,15 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
4147 * more buffers it will schedule replenish */ 4049 * more buffers it will schedule replenish */
4148 break; 4050 break;
4149 } 4051 }
4052
4053 /* If radiotap head is required, reserve some headroom here.
4054 * The physical head count is a variable rx_stats->phy_count.
4055 * We reserve 4 bytes here. Plus these extra bytes, the
4056 * headroom of the physical head should be enough for the
4057 * radiotap head that iwl3945 supported. See iwl3945_rt.
4058 */
4059 skb_reserve(rxb->skb, 4);
4060
4150 priv->alloc_rxb_skb++; 4061 priv->alloc_rxb_skb++;
4151 list_del(element); 4062 list_del(element);
4152 4063
@@ -7114,6 +7025,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
7114 mutex_lock(&priv->mutex); 7025 mutex_lock(&priv->mutex);
7115 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); 7026 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
7116 7027
7028 priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
7029
7117 if (!iwl3945_is_ready(priv)) { 7030 if (!iwl3945_is_ready(priv)) {
7118 IWL_DEBUG_MAC80211("leave - not ready\n"); 7031 IWL_DEBUG_MAC80211("leave - not ready\n");
7119 ret = -EIO; 7032 ret = -EIO;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 14a1124e6ef4..07089754b544 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -41,7 +41,6 @@
41#include <linux/etherdevice.h> 41#include <linux/etherdevice.h>
42#include <linux/if_arp.h> 42#include <linux/if_arp.h>
43 43
44#include <net/ieee80211_radiotap.h>
45#include <net/mac80211.h> 44#include <net/mac80211.h>
46 45
47#include <asm/div64.h> 46#include <asm/div64.h>
@@ -3247,93 +3246,6 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
3247 } 3246 }
3248} 3247}
3249 3248
3250void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv,
3251 struct iwl4965_rx_mem_buffer *rxb,
3252 void *data, short len,
3253 struct ieee80211_rx_status *stats,
3254 u16 phy_flags)
3255{
3256 struct iwl4965_rt_rx_hdr *iwl4965_rt;
3257
3258 /* First cache any information we need before we overwrite
3259 * the information provided in the skb from the hardware */
3260 s8 signal = stats->ssi;
3261 s8 noise = 0;
3262 int rate = stats->rate;
3263 u64 tsf = stats->mactime;
3264 __le16 phy_flags_hw = cpu_to_le16(phy_flags);
3265
3266 /* We received data from the HW, so stop the watchdog */
3267 if (len > priv->hw_setting.rx_buf_size - sizeof(*iwl4965_rt)) {
3268 IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
3269 return;
3270 }
3271
3272 /* copy the frame data to write after where the radiotap header goes */
3273 iwl4965_rt = (void *)rxb->skb->data;
3274 memmove(iwl4965_rt->payload, data, len);
3275
3276 iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
3277 iwl4965_rt->rt_hdr.it_pad = 0; /* always good to zero */
3278
3279 /* total header + data */
3280 iwl4965_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl4965_rt));
3281
3282 /* Set the size of the skb to the size of the frame */
3283 skb_put(rxb->skb, sizeof(*iwl4965_rt) + len);
3284
3285 /* Big bitfield of all the fields we provide in radiotap */
3286 iwl4965_rt->rt_hdr.it_present =
3287 cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
3288 (1 << IEEE80211_RADIOTAP_FLAGS) |
3289 (1 << IEEE80211_RADIOTAP_RATE) |
3290 (1 << IEEE80211_RADIOTAP_CHANNEL) |
3291 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
3292 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
3293 (1 << IEEE80211_RADIOTAP_ANTENNA));
3294
3295 /* Zero the flags, we'll add to them as we go */
3296 iwl4965_rt->rt_flags = 0;
3297
3298 iwl4965_rt->rt_tsf = cpu_to_le64(tsf);
3299
3300 /* Convert to dBm */
3301 iwl4965_rt->rt_dbmsignal = signal;
3302 iwl4965_rt->rt_dbmnoise = noise;
3303
3304 /* Convert the channel frequency and set the flags */
3305 iwl4965_rt->rt_channelMHz = cpu_to_le16(stats->freq);
3306 if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
3307 iwl4965_rt->rt_chbitmask =
3308 cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
3309 else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
3310 iwl4965_rt->rt_chbitmask =
3311 cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
3312 else /* 802.11g */
3313 iwl4965_rt->rt_chbitmask =
3314 cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
3315
3316 rate = iwl4965_rate_index_from_plcp(rate);
3317 if (rate == -1)
3318 iwl4965_rt->rt_rate = 0;
3319 else
3320 iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
3321
3322 /* antenna number */
3323 iwl4965_rt->rt_antenna =
3324 le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
3325
3326 /* set the preamble flag if we have it */
3327 if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
3328 iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
3329
3330 IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
3331
3332 stats->flag |= RX_FLAG_RADIOTAP;
3333 ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
3334 rxb->skb = NULL;
3335}
3336
3337 3249
3338#define IWL_PACKET_RETRY_TIME HZ 3250#define IWL_PACKET_RETRY_TIME HZ
3339 3251
@@ -7556,6 +7468,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
7556 mutex_lock(&priv->mutex); 7468 mutex_lock(&priv->mutex);
7557 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); 7469 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
7558 7470
7471 priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
7472
7559 if (!iwl4965_is_ready(priv)) { 7473 if (!iwl4965_is_ready(priv)) {
7560 IWL_DEBUG_MAC80211("leave - not ready\n"); 7474 IWL_DEBUG_MAC80211("leave - not ready\n");
7561 ret = -EIO; 7475 ret = -EIO;