diff options
author | Zhu Yi <yi.zhu@intel.com> | 2007-12-19 22:27:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:07:53 -0500 |
commit | 12342c475f5de17071eaf24ea2938ba8dfe285f2 (patch) | |
tree | a2cdfd191069397e093f2410009092e7e96c9325 /drivers/net/wireless | |
parent | 7e94041ca17685cf12c658b8edc008dd0bdb00c7 (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/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 120 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.h | 36 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 120 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.h | 24 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 109 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 90 |
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 | ||
241 | void 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 | |||
241 | static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, | 334 | static 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 | ||
94 | struct 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 | |||
107 | struct 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 | ||
961 | static 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 | |||
983 | extern const struct iwl3945_channel_info *iwl3945_get_channel_info( | 971 | extern 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 | ||
3592 | static 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 | |||
3591 | static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data, | 3697 | static 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 | ||
94 | struct 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 | |||
107 | struct 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 | ||
1500 | static 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 | |||
1510 | static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) | 1500 | static 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 | ||
3124 | void 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 | ||
3214 | int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | 3116 | int 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 | ||
3250 | void 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; |