diff options
Diffstat (limited to 'drivers/net')
29 files changed, 1614 insertions, 1564 deletions
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 4cca203992e8..fec5645944a4 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
@@ -43,6 +43,23 @@ static bool b43_is_hw_radio_enabled(struct b43_wldev *dev) | |||
43 | return 0; | 43 | return 0; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* Update the rfkill state */ | ||
47 | static void b43_rfkill_update_state(struct b43_wldev *dev) | ||
48 | { | ||
49 | struct b43_rfkill *rfk = &(dev->wl->rfkill); | ||
50 | |||
51 | if (!dev->radio_hw_enable) { | ||
52 | rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; | ||
53 | return; | ||
54 | } | ||
55 | |||
56 | if (!dev->phy.radio_on) | ||
57 | rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; | ||
58 | else | ||
59 | rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
60 | |||
61 | } | ||
62 | |||
46 | /* The poll callback for the hardware button. */ | 63 | /* The poll callback for the hardware button. */ |
47 | static void b43_rfkill_poll(struct input_polled_dev *poll_dev) | 64 | static void b43_rfkill_poll(struct input_polled_dev *poll_dev) |
48 | { | 65 | { |
@@ -60,6 +77,7 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) | |||
60 | if (unlikely(enabled != dev->radio_hw_enable)) { | 77 | if (unlikely(enabled != dev->radio_hw_enable)) { |
61 | dev->radio_hw_enable = enabled; | 78 | dev->radio_hw_enable = enabled; |
62 | report_change = 1; | 79 | report_change = 1; |
80 | b43_rfkill_update_state(dev); | ||
63 | b43info(wl, "Radio hardware status changed to %s\n", | 81 | b43info(wl, "Radio hardware status changed to %s\n", |
64 | enabled ? "ENABLED" : "DISABLED"); | 82 | enabled ? "ENABLED" : "DISABLED"); |
65 | } | 83 | } |
@@ -135,7 +153,7 @@ void b43_rfkill_init(struct b43_wldev *dev) | |||
135 | snprintf(rfk->name, sizeof(rfk->name), | 153 | snprintf(rfk->name, sizeof(rfk->name), |
136 | "b43-%s", wiphy_name(wl->hw->wiphy)); | 154 | "b43-%s", wiphy_name(wl->hw->wiphy)); |
137 | rfk->rfkill->name = rfk->name; | 155 | rfk->rfkill->name = rfk->name; |
138 | rfk->rfkill->state = RFKILL_STATE_ON; | 156 | rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; |
139 | rfk->rfkill->data = dev; | 157 | rfk->rfkill->data = dev; |
140 | rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; | 158 | rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle; |
141 | rfk->rfkill->user_claim_unsupported = 1; | 159 | rfk->rfkill->user_claim_unsupported = 1; |
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c index 8935a302b220..476add97e974 100644 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ b/drivers/net/wireless/b43legacy/rfkill.c | |||
@@ -44,6 +44,23 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) | |||
44 | return 0; | 44 | return 0; |
45 | } | 45 | } |
46 | 46 | ||
47 | /* Update the rfkill state */ | ||
48 | static void b43legacy_rfkill_update_state(struct b43legacy_wldev *dev) | ||
49 | { | ||
50 | struct b43legacy_rfkill *rfk = &(dev->wl->rfkill); | ||
51 | |||
52 | if (!dev->radio_hw_enable) { | ||
53 | rfk->rfkill->state = RFKILL_STATE_HARD_BLOCKED; | ||
54 | return; | ||
55 | } | ||
56 | |||
57 | if (!dev->phy.radio_on) | ||
58 | rfk->rfkill->state = RFKILL_STATE_SOFT_BLOCKED; | ||
59 | else | ||
60 | rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
61 | |||
62 | } | ||
63 | |||
47 | /* The poll callback for the hardware button. */ | 64 | /* The poll callback for the hardware button. */ |
48 | static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) | 65 | static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) |
49 | { | 66 | { |
@@ -61,6 +78,7 @@ static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev) | |||
61 | if (unlikely(enabled != dev->radio_hw_enable)) { | 78 | if (unlikely(enabled != dev->radio_hw_enable)) { |
62 | dev->radio_hw_enable = enabled; | 79 | dev->radio_hw_enable = enabled; |
63 | report_change = 1; | 80 | report_change = 1; |
81 | b43legacy_rfkill_update_state(dev); | ||
64 | b43legacyinfo(wl, "Radio hardware status changed to %s\n", | 82 | b43legacyinfo(wl, "Radio hardware status changed to %s\n", |
65 | enabled ? "ENABLED" : "DISABLED"); | 83 | enabled ? "ENABLED" : "DISABLED"); |
66 | } | 84 | } |
@@ -139,7 +157,7 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev) | |||
139 | snprintf(rfk->name, sizeof(rfk->name), | 157 | snprintf(rfk->name, sizeof(rfk->name), |
140 | "b43legacy-%s", wiphy_name(wl->hw->wiphy)); | 158 | "b43legacy-%s", wiphy_name(wl->hw->wiphy)); |
141 | rfk->rfkill->name = rfk->name; | 159 | rfk->rfkill->name = rfk->name; |
142 | rfk->rfkill->state = RFKILL_STATE_ON; | 160 | rfk->rfkill->state = RFKILL_STATE_UNBLOCKED; |
143 | rfk->rfkill->data = dev; | 161 | rfk->rfkill->data = dev; |
144 | rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; | 162 | rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle; |
145 | rfk->rfkill->user_claim_unsupported = 1; | 163 | rfk->rfkill->user_claim_unsupported = 1; |
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 4fd73809602e..d669e5956ce7 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c | |||
@@ -78,6 +78,9 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb, | |||
78 | prism_header = 2; | 78 | prism_header = 2; |
79 | phdrlen = sizeof(struct linux_wlan_ng_cap_hdr); | 79 | phdrlen = sizeof(struct linux_wlan_ng_cap_hdr); |
80 | } | 80 | } |
81 | } else if (dev->type == ARPHRD_IEEE80211_RADIOTAP) { | ||
82 | prism_header = 3; | ||
83 | phdrlen = sizeof(struct hostap_radiotap_rx); | ||
81 | } else { | 84 | } else { |
82 | prism_header = 0; | 85 | prism_header = 0; |
83 | phdrlen = 0; | 86 | phdrlen = 0; |
@@ -165,6 +168,24 @@ hdr->f.status = s; hdr->f.len = l; hdr->f.data = d | |||
165 | hdr->ssi_noise = htonl(rx_stats->noise); | 168 | hdr->ssi_noise = htonl(rx_stats->noise); |
166 | hdr->preamble = htonl(0); /* unknown */ | 169 | hdr->preamble = htonl(0); /* unknown */ |
167 | hdr->encoding = htonl(1); /* cck */ | 170 | hdr->encoding = htonl(1); /* cck */ |
171 | } else if (prism_header == 3) { | ||
172 | struct hostap_radiotap_rx *hdr; | ||
173 | hdr = (struct hostap_radiotap_rx *)skb_push(skb, phdrlen); | ||
174 | memset(hdr, 0, phdrlen); | ||
175 | hdr->hdr.it_len = cpu_to_le16(phdrlen); | ||
176 | hdr->hdr.it_present = | ||
177 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | ||
178 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
179 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
180 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
181 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)); | ||
182 | hdr->tsft = cpu_to_le64(rx_stats->mac_time); | ||
183 | hdr->chan_freq = cpu_to_le16(freq_list[local->channel - 1]); | ||
184 | hdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_CCK | | ||
185 | IEEE80211_CHAN_2GHZ); | ||
186 | hdr->rate = rx_stats->rate / 5; | ||
187 | hdr->dbm_antsignal = rx_stats->signal; | ||
188 | hdr->dbm_antnoise = rx_stats->noise; | ||
168 | } | 189 | } |
169 | 190 | ||
170 | ret = skb->len - phdrlen; | 191 | ret = skb->len - phdrlen; |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index cdf90c40f11b..79a9bc95d2a7 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -3204,6 +3204,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, | |||
3204 | local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY; | 3204 | local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY; |
3205 | local->sram_type = -1; | 3205 | local->sram_type = -1; |
3206 | local->scan_channel_mask = 0xffff; | 3206 | local->scan_channel_mask = 0xffff; |
3207 | local->monitor_type = PRISM2_MONITOR_RADIOTAP; | ||
3207 | 3208 | ||
3208 | /* Initialize task queue structures */ | 3209 | /* Initialize task queue structures */ |
3209 | INIT_WORK(&local->reset_queue, handle_reset_queue); | 3210 | INIT_WORK(&local->reset_queue, handle_reset_queue); |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index ed52d98317cd..3f8b1d7036e5 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -897,6 +897,8 @@ static void hostap_monitor_set_type(local_info_t *local) | |||
897 | if (local->monitor_type == PRISM2_MONITOR_PRISM || | 897 | if (local->monitor_type == PRISM2_MONITOR_PRISM || |
898 | local->monitor_type == PRISM2_MONITOR_CAPHDR) { | 898 | local->monitor_type == PRISM2_MONITOR_CAPHDR) { |
899 | dev->type = ARPHRD_IEEE80211_PRISM; | 899 | dev->type = ARPHRD_IEEE80211_PRISM; |
900 | } else if (local->monitor_type == PRISM2_MONITOR_RADIOTAP) { | ||
901 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
900 | } else { | 902 | } else { |
901 | dev->type = ARPHRD_IEEE80211; | 903 | dev->type = ARPHRD_IEEE80211; |
902 | } | 904 | } |
@@ -2520,7 +2522,8 @@ static int prism2_ioctl_priv_prism2_param(struct net_device *dev, | |||
2520 | case PRISM2_PARAM_MONITOR_TYPE: | 2522 | case PRISM2_PARAM_MONITOR_TYPE: |
2521 | if (value != PRISM2_MONITOR_80211 && | 2523 | if (value != PRISM2_MONITOR_80211 && |
2522 | value != PRISM2_MONITOR_CAPHDR && | 2524 | value != PRISM2_MONITOR_CAPHDR && |
2523 | value != PRISM2_MONITOR_PRISM) { | 2525 | value != PRISM2_MONITOR_PRISM && |
2526 | value != PRISM2_MONITOR_RADIOTAP) { | ||
2524 | ret = -EINVAL; | 2527 | ret = -EINVAL; |
2525 | break; | 2528 | break; |
2526 | } | 2529 | } |
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c index f7aec9309d04..b5213f61fb0b 100644 --- a/drivers/net/wireless/hostap/hostap_main.c +++ b/drivers/net/wireless/hostap/hostap_main.c | |||
@@ -596,25 +596,7 @@ void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx) | |||
596 | 596 | ||
597 | int hostap_80211_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 597 | int hostap_80211_header_parse(const struct sk_buff *skb, unsigned char *haddr) |
598 | { | 598 | { |
599 | struct hostap_interface *iface = netdev_priv(skb->dev); | 599 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ |
600 | local_info_t *local = iface->local; | ||
601 | |||
602 | if (local->monitor_type == PRISM2_MONITOR_PRISM || | ||
603 | local->monitor_type == PRISM2_MONITOR_CAPHDR) { | ||
604 | const unsigned char *mac = skb_mac_header(skb); | ||
605 | |||
606 | if (*(u32 *)mac == LWNG_CAP_DID_BASE) { | ||
607 | memcpy(haddr, | ||
608 | mac + sizeof(struct linux_wlan_ng_prism_hdr) + 10, | ||
609 | ETH_ALEN); /* addr2 */ | ||
610 | } else { /* (*(u32 *)mac == htonl(LWNG_CAPHDR_VERSION)) */ | ||
611 | memcpy(haddr, | ||
612 | mac + sizeof(struct linux_wlan_ng_cap_hdr) + 10, | ||
613 | ETH_ALEN); /* addr2 */ | ||
614 | } | ||
615 | } else | ||
616 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
617 | |||
618 | return ETH_ALEN; | 600 | return ETH_ALEN; |
619 | } | 601 | } |
620 | 602 | ||
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 15445bce2ac7..ffdf4876121b 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/netdevice.h> | 5 | #include <linux/netdevice.h> |
6 | #include <linux/mutex.h> | 6 | #include <linux/mutex.h> |
7 | #include <net/iw_handler.h> | 7 | #include <net/iw_handler.h> |
8 | #include <net/ieee80211_radiotap.h> | ||
8 | 9 | ||
9 | #include "hostap_config.h" | 10 | #include "hostap_config.h" |
10 | #include "hostap_common.h" | 11 | #include "hostap_common.h" |
@@ -55,6 +56,17 @@ struct linux_wlan_ng_cap_hdr { | |||
55 | __be32 encoding; | 56 | __be32 encoding; |
56 | } __attribute__ ((packed)); | 57 | } __attribute__ ((packed)); |
57 | 58 | ||
59 | struct hostap_radiotap_rx { | ||
60 | struct ieee80211_radiotap_header hdr; | ||
61 | __le64 tsft; | ||
62 | u8 rate; | ||
63 | u8 padding; | ||
64 | __le16 chan_freq; | ||
65 | __le16 chan_flags; | ||
66 | s8 dbm_antsignal; | ||
67 | s8 dbm_antnoise; | ||
68 | } __attribute__ ((packed)); | ||
69 | |||
58 | #define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */ | 70 | #define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */ |
59 | #define LWNG_CAPHDR_VERSION 0x80211001 | 71 | #define LWNG_CAPHDR_VERSION 0x80211001 |
60 | 72 | ||
@@ -734,7 +746,7 @@ struct local_info { | |||
734 | unsigned long scan_timestamp; /* Time started to scan */ | 746 | unsigned long scan_timestamp; /* Time started to scan */ |
735 | enum { | 747 | enum { |
736 | PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1, | 748 | PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1, |
737 | PRISM2_MONITOR_CAPHDR = 2 | 749 | PRISM2_MONITOR_CAPHDR = 2, PRISM2_MONITOR_RADIOTAP = 3 |
738 | } monitor_type; | 750 | } monitor_type; |
739 | int monitor_allow_fcserr; | 751 | int monitor_allow_fcserr; |
740 | 752 | ||
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index d7ea32f39694..b628a44057f7 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -8,7 +8,6 @@ config IWLCORE | |||
8 | select MAC80211_LEDS if IWLWIFI_LEDS | 8 | select MAC80211_LEDS if IWLWIFI_LEDS |
9 | select LEDS_CLASS if IWLWIFI_LEDS | 9 | select LEDS_CLASS if IWLWIFI_LEDS |
10 | select RFKILL if IWLWIFI_RFKILL | 10 | select RFKILL if IWLWIFI_RFKILL |
11 | select RFKILL_INPUT if (IWLWIFI_RFKILL && INPUT) | ||
12 | 11 | ||
13 | config IWLWIFI_LEDS | 12 | config IWLWIFI_LEDS |
14 | bool | 13 | bool |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a9b3edad3868..a77497809d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -36,6 +36,10 @@ | |||
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <net/ieee80211_radiotap.h> | 37 | #include <net/ieee80211_radiotap.h> |
38 | 38 | ||
39 | /*used for rfkill*/ | ||
40 | #include <linux/rfkill.h> | ||
41 | #include <linux/input.h> | ||
42 | |||
39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | 43 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
40 | extern struct pci_device_id iwl3945_hw_card_ids[]; | 44 | extern struct pci_device_id iwl3945_hw_card_ids[]; |
41 | 45 | ||
@@ -686,6 +690,23 @@ enum { | |||
686 | 690 | ||
687 | #endif | 691 | #endif |
688 | 692 | ||
693 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
694 | struct iwl3945_priv; | ||
695 | |||
696 | struct iwl3945_rfkill_mngr { | ||
697 | struct rfkill *rfkill; | ||
698 | struct input_dev *input_dev; | ||
699 | }; | ||
700 | |||
701 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); | ||
702 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); | ||
703 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); | ||
704 | #else | ||
705 | static inline void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) {} | ||
706 | static inline void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) {} | ||
707 | static inline int iwl3945_rfkill_init(struct iwl3945_priv *priv) { return 0; } | ||
708 | #endif | ||
709 | |||
689 | #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES | 710 | #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES |
690 | 711 | ||
691 | struct iwl3945_priv { | 712 | struct iwl3945_priv { |
@@ -779,6 +800,10 @@ struct iwl3945_priv { | |||
779 | struct iwl3945_init_alive_resp card_alive_init; | 800 | struct iwl3945_init_alive_resp card_alive_init; |
780 | struct iwl3945_alive_resp card_alive; | 801 | struct iwl3945_alive_resp card_alive; |
781 | 802 | ||
803 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
804 | struct iwl3945_rfkill_mngr rfkill_mngr; | ||
805 | #endif | ||
806 | |||
782 | #ifdef CONFIG_IWL3945_LEDS | 807 | #ifdef CONFIG_IWL3945_LEDS |
783 | struct iwl3945_led led[IWL_LED_TRG_MAX]; | 808 | struct iwl3945_led led[IWL_LED_TRG_MAX]; |
784 | unsigned long last_blink_time; | 809 | unsigned long last_blink_time; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 202303117285..c7ebb3bf06f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c | |||
@@ -822,9 +822,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
822 | 822 | ||
823 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; | 823 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; |
824 | 824 | ||
825 | if (!priv->lq_mngr.lq_ready) | ||
826 | goto out; | ||
827 | |||
828 | if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && | 825 | if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && |
829 | !lq_sta->ibss_sta_added) | 826 | !lq_sta->ibss_sta_added) |
830 | goto out; | 827 | goto out; |
@@ -1678,10 +1675,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1678 | if (!sta || !sta->rate_ctrl_priv) | 1675 | if (!sta || !sta->rate_ctrl_priv) |
1679 | return; | 1676 | return; |
1680 | 1677 | ||
1681 | if (!priv->lq_mngr.lq_ready) { | ||
1682 | IWL_DEBUG_RATE("still rate scaling not ready\n"); | ||
1683 | return; | ||
1684 | } | ||
1685 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; | 1678 | lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; |
1686 | 1679 | ||
1687 | tid = rs_tl_add_packet(lq_sta, hdr); | 1680 | tid = rs_tl_add_packet(lq_sta, hdr); |
@@ -2140,11 +2133,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, | |||
2140 | lq_sta->ibss_sta_added = 1; | 2133 | lq_sta->ibss_sta_added = 1; |
2141 | rs_initialize_lq(priv, conf, sta); | 2134 | rs_initialize_lq(priv, conf, sta); |
2142 | } | 2135 | } |
2143 | if (!lq_sta->ibss_sta_added) | ||
2144 | goto done; | ||
2145 | } | 2136 | } |
2146 | 2137 | ||
2147 | done: | ||
2148 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | 2138 | if ((i < 0) || (i > IWL_RATE_COUNT)) { |
2149 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 2139 | sel->rate_idx = rate_lowest_index(local, sband, sta); |
2150 | goto out; | 2140 | goto out; |
@@ -2279,9 +2269,6 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2279 | lq_sta->drv = priv; | 2269 | lq_sta->drv = priv; |
2280 | #endif | 2270 | #endif |
2281 | 2271 | ||
2282 | if (priv->assoc_station_added) | ||
2283 | priv->lq_mngr.lq_ready = 1; | ||
2284 | |||
2285 | rs_initialize_lq(priv, conf, sta); | 2272 | rs_initialize_lq(priv, conf, sta); |
2286 | } | 2273 | } |
2287 | 2274 | ||
@@ -2421,7 +2408,7 @@ static void rs_clear(void *priv_rate) | |||
2421 | 2408 | ||
2422 | IWL_DEBUG_RATE("enter\n"); | 2409 | IWL_DEBUG_RATE("enter\n"); |
2423 | 2410 | ||
2424 | priv->lq_mngr.lq_ready = 0; | 2411 | /* TODO - add rate scale state reset */ |
2425 | 2412 | ||
2426 | IWL_DEBUG_RATE("leave\n"); | 2413 | IWL_DEBUG_RATE("leave\n"); |
2427 | } | 2414 | } |
@@ -2716,13 +2703,6 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) | |||
2716 | return cnt; | 2703 | return cnt; |
2717 | } | 2704 | } |
2718 | 2705 | ||
2719 | void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) | ||
2720 | { | ||
2721 | struct iwl_priv *priv = hw->priv; | ||
2722 | |||
2723 | priv->lq_mngr.lq_ready = 1; | ||
2724 | } | ||
2725 | |||
2726 | int iwl4965_rate_control_register(void) | 2706 | int iwl4965_rate_control_register(void) |
2727 | { | 2707 | { |
2728 | return ieee80211_rate_control_register(&rs_ops); | 2708 | return ieee80211_rate_control_register(&rs_ops); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index cbd126418490..9b9972885aa5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h | |||
@@ -296,14 +296,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) | |||
296 | extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); | 296 | extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); |
297 | 297 | ||
298 | /** | 298 | /** |
299 | * iwl4965_rate_scale_init - Initialize the rate scale table based on assoc info | ||
300 | * | ||
301 | * The specific throughput table used is based on the type of network | ||
302 | * the associated with, including A, B, G, and G w/ TGG protection | ||
303 | */ | ||
304 | extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); | ||
305 | |||
306 | /** | ||
307 | * iwl4965_rate_control_register - Register the rate control algorithm callbacks | 299 | * iwl4965_rate_control_register - Register the rate control algorithm callbacks |
308 | * | 300 | * |
309 | * Since the rate control algorithm is hardware specific, there is no need | 301 | * Since the rate control algorithm is hardware specific, there is no need |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ab5027345a01..8c93f8d56a70 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -555,8 +555,6 @@ out: | |||
555 | return ret; | 555 | return ret; |
556 | } | 556 | } |
557 | 557 | ||
558 | #define REG_RECALIB_PERIOD (60) | ||
559 | |||
560 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. | 558 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. |
561 | * Called after every association, but this runs only once! | 559 | * Called after every association, but this runs only once! |
562 | * ... once chain noise is calibrated the first time, it's good forever. */ | 560 | * ... once chain noise is calibrated the first time, it's good forever. */ |
@@ -839,17 +837,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
839 | 837 | ||
840 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 838 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
841 | priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE; | 839 | priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE; |
842 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; | ||
843 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
844 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
845 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
846 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | ||
847 | else | ||
848 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | ||
849 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | ||
850 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 840 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
851 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 841 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
852 | |||
853 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; | 842 | priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; |
854 | priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; | 843 | priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; |
855 | priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; | 844 | priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; |
@@ -1890,87 +1879,10 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) | |||
1890 | return 1; | 1879 | return 1; |
1891 | } | 1880 | } |
1892 | 1881 | ||
1893 | /* Calculate noise level, based on measurements during network silence just | 1882 | static void iwl4965_temperature_calib(struct iwl_priv *priv) |
1894 | * before arriving beacon. This measurement can be done only if we know | ||
1895 | * exactly when to expect beacons, therefore only when we're associated. */ | ||
1896 | static void iwl4965_rx_calc_noise(struct iwl_priv *priv) | ||
1897 | { | ||
1898 | struct statistics_rx_non_phy *rx_info | ||
1899 | = &(priv->statistics.rx.general); | ||
1900 | int num_active_rx = 0; | ||
1901 | int total_silence = 0; | ||
1902 | int bcn_silence_a = | ||
1903 | le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; | ||
1904 | int bcn_silence_b = | ||
1905 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | ||
1906 | int bcn_silence_c = | ||
1907 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | ||
1908 | |||
1909 | if (bcn_silence_a) { | ||
1910 | total_silence += bcn_silence_a; | ||
1911 | num_active_rx++; | ||
1912 | } | ||
1913 | if (bcn_silence_b) { | ||
1914 | total_silence += bcn_silence_b; | ||
1915 | num_active_rx++; | ||
1916 | } | ||
1917 | if (bcn_silence_c) { | ||
1918 | total_silence += bcn_silence_c; | ||
1919 | num_active_rx++; | ||
1920 | } | ||
1921 | |||
1922 | /* Average among active antennas */ | ||
1923 | if (num_active_rx) | ||
1924 | priv->last_rx_noise = (total_silence / num_active_rx) - 107; | ||
1925 | else | ||
1926 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1927 | |||
1928 | IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", | ||
1929 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | ||
1930 | priv->last_rx_noise); | ||
1931 | } | ||
1932 | |||
1933 | void iwl4965_hw_rx_statistics(struct iwl_priv *priv, | ||
1934 | struct iwl_rx_mem_buffer *rxb) | ||
1935 | { | 1883 | { |
1936 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1937 | int change; | ||
1938 | s32 temp; | 1884 | s32 temp; |
1939 | 1885 | ||
1940 | IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", | ||
1941 | (int)sizeof(priv->statistics), pkt->len); | ||
1942 | |||
1943 | change = ((priv->statistics.general.temperature != | ||
1944 | pkt->u.stats.general.temperature) || | ||
1945 | ((priv->statistics.flag & | ||
1946 | STATISTICS_REPLY_FLG_FAT_MODE_MSK) != | ||
1947 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK))); | ||
1948 | |||
1949 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | ||
1950 | |||
1951 | set_bit(STATUS_STATISTICS, &priv->status); | ||
1952 | |||
1953 | /* Reschedule the statistics timer to occur in | ||
1954 | * REG_RECALIB_PERIOD seconds to ensure we get a | ||
1955 | * thermal update even if the uCode doesn't give | ||
1956 | * us one */ | ||
1957 | mod_timer(&priv->statistics_periodic, jiffies + | ||
1958 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | ||
1959 | |||
1960 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | ||
1961 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | ||
1962 | iwl4965_rx_calc_noise(priv); | ||
1963 | queue_work(priv->workqueue, &priv->run_time_calib_work); | ||
1964 | } | ||
1965 | |||
1966 | iwl_leds_background(priv); | ||
1967 | |||
1968 | /* If the hardware hasn't reported a change in | ||
1969 | * temperature then don't bother computing a | ||
1970 | * calibrated temperature value */ | ||
1971 | if (!change) | ||
1972 | return; | ||
1973 | |||
1974 | temp = iwl4965_hw_get_temperature(priv); | 1886 | temp = iwl4965_hw_get_temperature(priv); |
1975 | if (temp < 0) | 1887 | if (temp < 0) |
1976 | return; | 1888 | return; |
@@ -1996,775 +1908,6 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, | |||
1996 | queue_work(priv->workqueue, &priv->txpower_work); | 1908 | queue_work(priv->workqueue, &priv->txpower_work); |
1997 | } | 1909 | } |
1998 | 1910 | ||
1999 | static void iwl4965_add_radiotap(struct iwl_priv *priv, | ||
2000 | struct sk_buff *skb, | ||
2001 | struct iwl4965_rx_phy_res *rx_start, | ||
2002 | struct ieee80211_rx_status *stats, | ||
2003 | u32 ampdu_status) | ||
2004 | { | ||
2005 | s8 signal = stats->signal; | ||
2006 | s8 noise = 0; | ||
2007 | int rate = stats->rate_idx; | ||
2008 | u64 tsf = stats->mactime; | ||
2009 | __le16 antenna; | ||
2010 | __le16 phy_flags_hw = rx_start->phy_flags; | ||
2011 | struct iwl4965_rt_rx_hdr { | ||
2012 | struct ieee80211_radiotap_header rt_hdr; | ||
2013 | __le64 rt_tsf; /* TSF */ | ||
2014 | u8 rt_flags; /* radiotap packet flags */ | ||
2015 | u8 rt_rate; /* rate in 500kb/s */ | ||
2016 | __le16 rt_channelMHz; /* channel in MHz */ | ||
2017 | __le16 rt_chbitmask; /* channel bitfield */ | ||
2018 | s8 rt_dbmsignal; /* signal in dBm, kluged to signed */ | ||
2019 | s8 rt_dbmnoise; | ||
2020 | u8 rt_antenna; /* antenna number */ | ||
2021 | } __attribute__ ((packed)) *iwl4965_rt; | ||
2022 | |||
2023 | /* TODO: We won't have enough headroom for HT frames. Fix it later. */ | ||
2024 | if (skb_headroom(skb) < sizeof(*iwl4965_rt)) { | ||
2025 | if (net_ratelimit()) | ||
2026 | printk(KERN_ERR "not enough headroom [%d] for " | ||
2027 | "radiotap head [%zd]\n", | ||
2028 | skb_headroom(skb), sizeof(*iwl4965_rt)); | ||
2029 | return; | ||
2030 | } | ||
2031 | |||
2032 | /* put radiotap header in front of 802.11 header and data */ | ||
2033 | iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt)); | ||
2034 | |||
2035 | /* initialise radiotap header */ | ||
2036 | iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
2037 | iwl4965_rt->rt_hdr.it_pad = 0; | ||
2038 | |||
2039 | /* total header + data */ | ||
2040 | put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), | ||
2041 | &iwl4965_rt->rt_hdr.it_len); | ||
2042 | |||
2043 | /* Indicate all the fields we add to the radiotap header */ | ||
2044 | put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | ||
2045 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
2046 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
2047 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
2048 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
2049 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
2050 | (1 << IEEE80211_RADIOTAP_ANTENNA)), | ||
2051 | &iwl4965_rt->rt_hdr.it_present); | ||
2052 | |||
2053 | /* Zero the flags, we'll add to them as we go */ | ||
2054 | iwl4965_rt->rt_flags = 0; | ||
2055 | |||
2056 | put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); | ||
2057 | |||
2058 | iwl4965_rt->rt_dbmsignal = signal; | ||
2059 | iwl4965_rt->rt_dbmnoise = noise; | ||
2060 | |||
2061 | /* Convert the channel frequency and set the flags */ | ||
2062 | put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); | ||
2063 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) | ||
2064 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
2065 | IEEE80211_CHAN_5GHZ), | ||
2066 | &iwl4965_rt->rt_chbitmask); | ||
2067 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) | ||
2068 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | | ||
2069 | IEEE80211_CHAN_2GHZ), | ||
2070 | &iwl4965_rt->rt_chbitmask); | ||
2071 | else /* 802.11g */ | ||
2072 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
2073 | IEEE80211_CHAN_2GHZ), | ||
2074 | &iwl4965_rt->rt_chbitmask); | ||
2075 | |||
2076 | if (rate == -1) | ||
2077 | iwl4965_rt->rt_rate = 0; | ||
2078 | else | ||
2079 | iwl4965_rt->rt_rate = iwl_rates[rate].ieee; | ||
2080 | |||
2081 | /* | ||
2082 | * "antenna number" | ||
2083 | * | ||
2084 | * It seems that the antenna field in the phy flags value | ||
2085 | * is actually a bitfield. This is undefined by radiotap, | ||
2086 | * it wants an actual antenna number but I always get "7" | ||
2087 | * for most legacy frames I receive indicating that the | ||
2088 | * same frame was received on all three RX chains. | ||
2089 | * | ||
2090 | * I think this field should be removed in favour of a | ||
2091 | * new 802.11n radiotap field "RX chains" that is defined | ||
2092 | * as a bitmask. | ||
2093 | */ | ||
2094 | antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; | ||
2095 | iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4; | ||
2096 | |||
2097 | /* set the preamble flag if appropriate */ | ||
2098 | if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
2099 | iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
2100 | |||
2101 | stats->flag |= RX_FLAG_RADIOTAP; | ||
2102 | } | ||
2103 | |||
2104 | static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | ||
2105 | { | ||
2106 | /* 0 - mgmt, 1 - cnt, 2 - data */ | ||
2107 | int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; | ||
2108 | priv->rx_stats[idx].cnt++; | ||
2109 | priv->rx_stats[idx].bytes += len; | ||
2110 | } | ||
2111 | |||
2112 | /* | ||
2113 | * returns non-zero if packet should be dropped | ||
2114 | */ | ||
2115 | static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | ||
2116 | struct ieee80211_hdr *hdr, | ||
2117 | u32 decrypt_res, | ||
2118 | struct ieee80211_rx_status *stats) | ||
2119 | { | ||
2120 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
2121 | |||
2122 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
2123 | return 0; | ||
2124 | |||
2125 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
2126 | return 0; | ||
2127 | |||
2128 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
2129 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2130 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2131 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2132 | * Decryption will be done in SW. */ | ||
2133 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2134 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2135 | break; | ||
2136 | |||
2137 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2138 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2139 | RX_RES_STATUS_BAD_ICV_MIC) { | ||
2140 | /* bad ICV, the packet is destroyed since the | ||
2141 | * decryption is inplace, drop it */ | ||
2142 | IWL_DEBUG_RX("Packet destroyed\n"); | ||
2143 | return -1; | ||
2144 | } | ||
2145 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2146 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2147 | RX_RES_STATUS_DECRYPT_OK) { | ||
2148 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
2149 | stats->flag |= RX_FLAG_DECRYPTED; | ||
2150 | } | ||
2151 | break; | ||
2152 | |||
2153 | default: | ||
2154 | break; | ||
2155 | } | ||
2156 | return 0; | ||
2157 | } | ||
2158 | |||
2159 | static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
2160 | { | ||
2161 | u32 decrypt_out = 0; | ||
2162 | |||
2163 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
2164 | RX_RES_STATUS_STATION_FOUND) | ||
2165 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
2166 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
2167 | |||
2168 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
2169 | |||
2170 | /* packet was not encrypted */ | ||
2171 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
2172 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
2173 | return decrypt_out; | ||
2174 | |||
2175 | /* packet was encrypted with unknown alg */ | ||
2176 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
2177 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
2178 | return decrypt_out; | ||
2179 | |||
2180 | /* decryption was not done in HW */ | ||
2181 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
2182 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
2183 | return decrypt_out; | ||
2184 | |||
2185 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2186 | |||
2187 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2188 | /* alg is CCM: check MIC only */ | ||
2189 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
2190 | /* Bad MIC */ | ||
2191 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
2192 | else | ||
2193 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
2194 | |||
2195 | break; | ||
2196 | |||
2197 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2198 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
2199 | /* Bad TTAK */ | ||
2200 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
2201 | break; | ||
2202 | } | ||
2203 | /* fall through if TTAK OK */ | ||
2204 | default: | ||
2205 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
2206 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
2207 | else | ||
2208 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
2209 | break; | ||
2210 | }; | ||
2211 | |||
2212 | IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
2213 | decrypt_in, decrypt_out); | ||
2214 | |||
2215 | return decrypt_out; | ||
2216 | } | ||
2217 | |||
2218 | static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | ||
2219 | int include_phy, | ||
2220 | struct iwl_rx_mem_buffer *rxb, | ||
2221 | struct ieee80211_rx_status *stats) | ||
2222 | { | ||
2223 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
2224 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
2225 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL; | ||
2226 | struct ieee80211_hdr *hdr; | ||
2227 | u16 len; | ||
2228 | __le32 *rx_end; | ||
2229 | unsigned int skblen; | ||
2230 | u32 ampdu_status; | ||
2231 | u32 ampdu_status_legacy; | ||
2232 | |||
2233 | if (!include_phy && priv->last_phy_res[0]) | ||
2234 | rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
2235 | |||
2236 | if (!rx_start) { | ||
2237 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
2238 | return; | ||
2239 | } | ||
2240 | if (include_phy) { | ||
2241 | hdr = (struct ieee80211_hdr *)((u8 *) & rx_start[1] + | ||
2242 | rx_start->cfg_phy_cnt); | ||
2243 | |||
2244 | len = le16_to_cpu(rx_start->byte_count); | ||
2245 | |||
2246 | rx_end = (__le32 *) ((u8 *) & pkt->u.raw[0] + | ||
2247 | sizeof(struct iwl4965_rx_phy_res) + | ||
2248 | rx_start->cfg_phy_cnt + len); | ||
2249 | |||
2250 | } else { | ||
2251 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
2252 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
2253 | |||
2254 | hdr = (struct ieee80211_hdr *)(pkt->u.raw + | ||
2255 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
2256 | len = le16_to_cpu(amsdu->byte_count); | ||
2257 | rx_start->byte_count = amsdu->byte_count; | ||
2258 | rx_end = (__le32 *) (((u8 *) hdr) + len); | ||
2259 | } | ||
2260 | /* In monitor mode allow 802.11 ACk frames (10 bytes) */ | ||
2261 | if (len > priv->hw_params.max_pkt_size || | ||
2262 | len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) { | ||
2263 | IWL_WARNING("byte count out of range [16,4K] : %d\n", len); | ||
2264 | return; | ||
2265 | } | ||
2266 | |||
2267 | ampdu_status = le32_to_cpu(*rx_end); | ||
2268 | skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32); | ||
2269 | |||
2270 | if (!include_phy) { | ||
2271 | /* New status scheme, need to translate */ | ||
2272 | ampdu_status_legacy = ampdu_status; | ||
2273 | ampdu_status = iwl4965_translate_rx_status(priv, ampdu_status); | ||
2274 | } | ||
2275 | |||
2276 | /* start from MAC */ | ||
2277 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); | ||
2278 | skb_put(rxb->skb, len); /* end where data ends */ | ||
2279 | |||
2280 | /* We only process data packets if the interface is open */ | ||
2281 | if (unlikely(!priv->is_open)) { | ||
2282 | IWL_DEBUG_DROP_LIMIT | ||
2283 | ("Dropping packet while interface is not open.\n"); | ||
2284 | return; | ||
2285 | } | ||
2286 | |||
2287 | stats->flag = 0; | ||
2288 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | ||
2289 | |||
2290 | /* in case of HW accelerated crypto and bad decryption, drop */ | ||
2291 | if (!priv->hw_params.sw_crypto && | ||
2292 | iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
2293 | return; | ||
2294 | |||
2295 | if (priv->add_radiotap) | ||
2296 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); | ||
2297 | |||
2298 | iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); | ||
2299 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); | ||
2300 | priv->alloc_rxb_skb--; | ||
2301 | rxb->skb = NULL; | ||
2302 | } | ||
2303 | |||
2304 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
2305 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | ||
2306 | struct iwl4965_rx_phy_res *rx_resp) | ||
2307 | { | ||
2308 | /* data from PHY/DSP regarding signal strength, etc., | ||
2309 | * contents are always there, not configurable by host. */ | ||
2310 | struct iwl4965_rx_non_cfg_phy *ncphy = | ||
2311 | (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy; | ||
2312 | u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK) | ||
2313 | >> IWL_AGC_DB_POS; | ||
2314 | |||
2315 | u32 valid_antennae = | ||
2316 | (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) | ||
2317 | >> RX_PHY_FLAGS_ANTENNAE_OFFSET; | ||
2318 | u8 max_rssi = 0; | ||
2319 | u32 i; | ||
2320 | |||
2321 | /* Find max rssi among 3 possible receivers. | ||
2322 | * These values are measured by the digital signal processor (DSP). | ||
2323 | * They should stay fairly constant even as the signal strength varies, | ||
2324 | * if the radio's automatic gain control (AGC) is working right. | ||
2325 | * AGC value (see below) will provide the "interesting" info. */ | ||
2326 | for (i = 0; i < 3; i++) | ||
2327 | if (valid_antennae & (1 << i)) | ||
2328 | max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); | ||
2329 | |||
2330 | IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
2331 | ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], | ||
2332 | max_rssi, agc); | ||
2333 | |||
2334 | /* dBm = max_rssi dB - agc dB - constant. | ||
2335 | * Higher AGC (higher radio gain) means lower signal. */ | ||
2336 | return (max_rssi - agc - IWL_RSSI_OFFSET); | ||
2337 | } | ||
2338 | |||
2339 | static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||
2340 | { | ||
2341 | unsigned long flags; | ||
2342 | |||
2343 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2344 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | ||
2345 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | ||
2346 | priv->stations[sta_id].sta.sta.modify_mask = 0; | ||
2347 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
2348 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2349 | |||
2350 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
2351 | } | ||
2352 | |||
2353 | static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | ||
2354 | { | ||
2355 | /* FIXME: need locking over ps_status ??? */ | ||
2356 | u8 sta_id = iwl_find_station(priv, addr); | ||
2357 | |||
2358 | if (sta_id != IWL_INVALID_STATION) { | ||
2359 | u8 sta_awake = priv->stations[sta_id]. | ||
2360 | ps_status == STA_PS_STATUS_WAKE; | ||
2361 | |||
2362 | if (sta_awake && ps_bit) | ||
2363 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
2364 | else if (!sta_awake && !ps_bit) { | ||
2365 | iwl4965_sta_modify_ps_wake(priv, sta_id); | ||
2366 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
2367 | } | ||
2368 | } | ||
2369 | } | ||
2370 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2371 | |||
2372 | /** | ||
2373 | * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions | ||
2374 | * | ||
2375 | * You may hack this function to show different aspects of received frames, | ||
2376 | * including selective frame dumps. | ||
2377 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
2378 | * | ||
2379 | * TODO: This was originally written for 3945, need to audit for | ||
2380 | * proper operation with 4965. | ||
2381 | */ | ||
2382 | static void iwl4965_dbg_report_frame(struct iwl_priv *priv, | ||
2383 | struct iwl_rx_packet *pkt, | ||
2384 | struct ieee80211_hdr *header, int group100) | ||
2385 | { | ||
2386 | u32 to_us; | ||
2387 | u32 print_summary = 0; | ||
2388 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
2389 | u32 hundred = 0; | ||
2390 | u32 dataframe = 0; | ||
2391 | __le16 fc; | ||
2392 | u16 seq_ctl; | ||
2393 | u16 channel; | ||
2394 | u16 phy_flags; | ||
2395 | int rate_sym; | ||
2396 | u16 length; | ||
2397 | u16 status; | ||
2398 | u16 bcn_tmr; | ||
2399 | u32 tsf_low; | ||
2400 | u64 tsf; | ||
2401 | u8 rssi; | ||
2402 | u8 agc; | ||
2403 | u16 sig_avg; | ||
2404 | u16 noise_diff; | ||
2405 | struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
2406 | struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
2407 | struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
2408 | u8 *data = IWL_RX_DATA(pkt); | ||
2409 | |||
2410 | if (likely(!(priv->debug_level & IWL_DL_RX))) | ||
2411 | return; | ||
2412 | |||
2413 | /* MAC header */ | ||
2414 | fc = header->frame_control; | ||
2415 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
2416 | |||
2417 | /* metadata */ | ||
2418 | channel = le16_to_cpu(rx_hdr->channel); | ||
2419 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
2420 | rate_sym = rx_hdr->rate; | ||
2421 | length = le16_to_cpu(rx_hdr->len); | ||
2422 | |||
2423 | /* end-of-frame status and timestamp */ | ||
2424 | status = le32_to_cpu(rx_end->status); | ||
2425 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
2426 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
2427 | tsf = le64_to_cpu(rx_end->timestamp); | ||
2428 | |||
2429 | /* signal statistics */ | ||
2430 | rssi = rx_stats->rssi; | ||
2431 | agc = rx_stats->agc; | ||
2432 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
2433 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
2434 | |||
2435 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2436 | |||
2437 | /* if data frame is to us and all is good, | ||
2438 | * (optionally) print summary for only 1 out of every 100 */ | ||
2439 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
2440 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
2441 | dataframe = 1; | ||
2442 | if (!group100) | ||
2443 | print_summary = 1; /* print each frame */ | ||
2444 | else if (priv->framecnt_to_us < 100) { | ||
2445 | priv->framecnt_to_us++; | ||
2446 | print_summary = 0; | ||
2447 | } else { | ||
2448 | priv->framecnt_to_us = 0; | ||
2449 | print_summary = 1; | ||
2450 | hundred = 1; | ||
2451 | } | ||
2452 | } else { | ||
2453 | /* print summary for all other frames */ | ||
2454 | print_summary = 1; | ||
2455 | } | ||
2456 | |||
2457 | if (print_summary) { | ||
2458 | char *title; | ||
2459 | int rate_idx; | ||
2460 | u32 bitrate; | ||
2461 | |||
2462 | if (hundred) | ||
2463 | title = "100Frames"; | ||
2464 | else if (ieee80211_has_retry(fc)) | ||
2465 | title = "Retry"; | ||
2466 | else if (ieee80211_is_assoc_resp(fc)) | ||
2467 | title = "AscRsp"; | ||
2468 | else if (ieee80211_is_reassoc_resp(fc)) | ||
2469 | title = "RasRsp"; | ||
2470 | else if (ieee80211_is_probe_resp(fc)) { | ||
2471 | title = "PrbRsp"; | ||
2472 | print_dump = 1; /* dump frame contents */ | ||
2473 | } else if (ieee80211_is_beacon(fc)) { | ||
2474 | title = "Beacon"; | ||
2475 | print_dump = 1; /* dump frame contents */ | ||
2476 | } else if (ieee80211_is_atim(fc)) | ||
2477 | title = "ATIM"; | ||
2478 | else if (ieee80211_is_auth(fc)) | ||
2479 | title = "Auth"; | ||
2480 | else if (ieee80211_is_deauth(fc)) | ||
2481 | title = "DeAuth"; | ||
2482 | else if (ieee80211_is_disassoc(fc)) | ||
2483 | title = "DisAssoc"; | ||
2484 | else | ||
2485 | title = "Frame"; | ||
2486 | |||
2487 | rate_idx = iwl_hwrate_to_plcp_idx(rate_sym); | ||
2488 | if (unlikely(rate_idx == -1)) | ||
2489 | bitrate = 0; | ||
2490 | else | ||
2491 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
2492 | |||
2493 | /* print frame summary. | ||
2494 | * MAC addresses show just the last byte (for brevity), | ||
2495 | * but you can hack it to show more, if you'd like to. */ | ||
2496 | if (dataframe) | ||
2497 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
2498 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
2499 | title, le16_to_cpu(fc), header->addr1[5], | ||
2500 | length, rssi, channel, bitrate); | ||
2501 | else { | ||
2502 | /* src/dst addresses assume managed mode */ | ||
2503 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
2504 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
2505 | "phy=0x%02x, chnl=%d\n", | ||
2506 | title, le16_to_cpu(fc), header->addr1[5], | ||
2507 | header->addr3[5], rssi, | ||
2508 | tsf_low - priv->scan_start_tsf, | ||
2509 | phy_flags, channel); | ||
2510 | } | ||
2511 | } | ||
2512 | if (print_dump) | ||
2513 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | ||
2514 | } | ||
2515 | #else | ||
2516 | static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, | ||
2517 | struct iwl_rx_packet *pkt, | ||
2518 | struct ieee80211_hdr *header, | ||
2519 | int group100) | ||
2520 | { | ||
2521 | } | ||
2522 | #endif | ||
2523 | |||
2524 | |||
2525 | |||
2526 | /* Called for REPLY_RX (legacy ABG frames), or | ||
2527 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
2528 | void iwl4965_rx_reply_rx(struct iwl_priv *priv, | ||
2529 | struct iwl_rx_mem_buffer *rxb) | ||
2530 | { | ||
2531 | struct ieee80211_hdr *header; | ||
2532 | struct ieee80211_rx_status rx_status; | ||
2533 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
2534 | /* Use phy data (Rx signal strength, etc.) contained within | ||
2535 | * this rx packet for legacy frames, | ||
2536 | * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ | ||
2537 | int include_phy = (pkt->hdr.cmd == REPLY_RX); | ||
2538 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
2539 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : | ||
2540 | (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
2541 | __le32 *rx_end; | ||
2542 | unsigned int len = 0; | ||
2543 | u16 fc; | ||
2544 | u8 network_packet; | ||
2545 | |||
2546 | rx_status.mactime = le64_to_cpu(rx_start->timestamp); | ||
2547 | rx_status.freq = | ||
2548 | ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); | ||
2549 | rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
2550 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
2551 | rx_status.rate_idx = | ||
2552 | iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); | ||
2553 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
2554 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
2555 | |||
2556 | rx_status.antenna = 0; | ||
2557 | rx_status.flag = 0; | ||
2558 | |||
2559 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { | ||
2560 | IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", | ||
2561 | rx_start->cfg_phy_cnt); | ||
2562 | return; | ||
2563 | } | ||
2564 | |||
2565 | if (!include_phy) { | ||
2566 | if (priv->last_phy_res[0]) | ||
2567 | rx_start = (struct iwl4965_rx_phy_res *) | ||
2568 | &priv->last_phy_res[1]; | ||
2569 | else | ||
2570 | rx_start = NULL; | ||
2571 | } | ||
2572 | |||
2573 | if (!rx_start) { | ||
2574 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
2575 | return; | ||
2576 | } | ||
2577 | |||
2578 | if (include_phy) { | ||
2579 | header = (struct ieee80211_hdr *)((u8 *) & rx_start[1] | ||
2580 | + rx_start->cfg_phy_cnt); | ||
2581 | |||
2582 | len = le16_to_cpu(rx_start->byte_count); | ||
2583 | rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + | ||
2584 | sizeof(struct iwl4965_rx_phy_res) + len); | ||
2585 | } else { | ||
2586 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
2587 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
2588 | |||
2589 | header = (void *)(pkt->u.raw + | ||
2590 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
2591 | len = le16_to_cpu(amsdu->byte_count); | ||
2592 | rx_end = (__le32 *) (pkt->u.raw + | ||
2593 | sizeof(struct iwl4965_rx_mpdu_res_start) + len); | ||
2594 | } | ||
2595 | |||
2596 | if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
2597 | !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
2598 | IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n", | ||
2599 | le32_to_cpu(*rx_end)); | ||
2600 | return; | ||
2601 | } | ||
2602 | |||
2603 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); | ||
2604 | |||
2605 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
2606 | rx_status.signal = iwl4965_calc_rssi(priv, rx_start); | ||
2607 | |||
2608 | /* Meaningful noise values are available only from beacon statistics, | ||
2609 | * which are gathered only when associated, and indicate noise | ||
2610 | * only for the associated network channel ... | ||
2611 | * Ignore these noise values while scanning (other channels) */ | ||
2612 | if (iwl_is_associated(priv) && | ||
2613 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
2614 | rx_status.noise = priv->last_rx_noise; | ||
2615 | rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, | ||
2616 | rx_status.noise); | ||
2617 | } else { | ||
2618 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
2619 | rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, 0); | ||
2620 | } | ||
2621 | |||
2622 | /* Reset beacon noise level if not associated. */ | ||
2623 | if (!iwl_is_associated(priv)) | ||
2624 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
2625 | |||
2626 | /* Set "1" to report good data frames in groups of 100 */ | ||
2627 | /* FIXME: need to optimze the call: */ | ||
2628 | iwl4965_dbg_report_frame(priv, pkt, header, 1); | ||
2629 | |||
2630 | IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", | ||
2631 | rx_status.signal, rx_status.noise, rx_status.signal, | ||
2632 | (unsigned long long)rx_status.mactime); | ||
2633 | |||
2634 | |||
2635 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | ||
2636 | iwl4965_handle_data_packet(priv, 1, include_phy, | ||
2637 | rxb, &rx_status); | ||
2638 | return; | ||
2639 | } | ||
2640 | |||
2641 | network_packet = iwl4965_is_network_packet(priv, header); | ||
2642 | if (network_packet) { | ||
2643 | priv->last_rx_rssi = rx_status.signal; | ||
2644 | priv->last_beacon_time = priv->ucode_beacon_time; | ||
2645 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); | ||
2646 | } | ||
2647 | |||
2648 | fc = le16_to_cpu(header->frame_control); | ||
2649 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
2650 | case IEEE80211_FTYPE_MGMT: | ||
2651 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
2652 | iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
2653 | header->addr2); | ||
2654 | iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); | ||
2655 | break; | ||
2656 | |||
2657 | case IEEE80211_FTYPE_CTL: | ||
2658 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
2659 | case IEEE80211_STYPE_BACK_REQ: | ||
2660 | IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); | ||
2661 | iwl4965_handle_data_packet(priv, 0, include_phy, | ||
2662 | rxb, &rx_status); | ||
2663 | break; | ||
2664 | default: | ||
2665 | break; | ||
2666 | } | ||
2667 | break; | ||
2668 | |||
2669 | case IEEE80211_FTYPE_DATA: { | ||
2670 | DECLARE_MAC_BUF(mac1); | ||
2671 | DECLARE_MAC_BUF(mac2); | ||
2672 | DECLARE_MAC_BUF(mac3); | ||
2673 | |||
2674 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
2675 | iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
2676 | header->addr2); | ||
2677 | |||
2678 | if (unlikely(!network_packet)) | ||
2679 | IWL_DEBUG_DROP("Dropping (non network): " | ||
2680 | "%s, %s, %s\n", | ||
2681 | print_mac(mac1, header->addr1), | ||
2682 | print_mac(mac2, header->addr2), | ||
2683 | print_mac(mac3, header->addr3)); | ||
2684 | else if (unlikely(iwl4965_is_duplicate_packet(priv, header))) | ||
2685 | IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", | ||
2686 | print_mac(mac1, header->addr1), | ||
2687 | print_mac(mac2, header->addr2), | ||
2688 | print_mac(mac3, header->addr3)); | ||
2689 | else | ||
2690 | iwl4965_handle_data_packet(priv, 1, include_phy, rxb, | ||
2691 | &rx_status); | ||
2692 | break; | ||
2693 | } | ||
2694 | default: | ||
2695 | break; | ||
2696 | |||
2697 | } | ||
2698 | } | ||
2699 | |||
2700 | /** | ||
2701 | * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
2702 | * | ||
2703 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
2704 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
2705 | */ | ||
2706 | static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
2707 | struct iwl_ht_agg *agg, | ||
2708 | struct iwl4965_compressed_ba_resp* | ||
2709 | ba_resp) | ||
2710 | |||
2711 | { | ||
2712 | int i, sh, ack; | ||
2713 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
2714 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
2715 | u64 bitmap; | ||
2716 | int successes = 0; | ||
2717 | struct ieee80211_tx_info *info; | ||
2718 | |||
2719 | if (unlikely(!agg->wait_for_ba)) { | ||
2720 | IWL_ERROR("Received BA when not expected\n"); | ||
2721 | return -EINVAL; | ||
2722 | } | ||
2723 | |||
2724 | /* Mark that the expected block-ack response arrived */ | ||
2725 | agg->wait_for_ba = 0; | ||
2726 | IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
2727 | |||
2728 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
2729 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4); | ||
2730 | if (sh < 0) /* tbw something is wrong with indices */ | ||
2731 | sh += 0x100; | ||
2732 | |||
2733 | /* don't use 64-bit values for now */ | ||
2734 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
2735 | |||
2736 | if (agg->frame_count > (64 - sh)) { | ||
2737 | IWL_DEBUG_TX_REPLY("more frames than bitmap size"); | ||
2738 | return -1; | ||
2739 | } | ||
2740 | |||
2741 | /* check for success or failure according to the | ||
2742 | * transmitted bitmap and block-ack bitmap */ | ||
2743 | bitmap &= agg->bitmap; | ||
2744 | |||
2745 | /* For each frame attempted in aggregation, | ||
2746 | * update driver's record of tx frame's status. */ | ||
2747 | for (i = 0; i < agg->frame_count ; i++) { | ||
2748 | ack = bitmap & (1 << i); | ||
2749 | successes += !!ack; | ||
2750 | IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", | ||
2751 | ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, | ||
2752 | agg->start_idx + i); | ||
2753 | } | ||
2754 | |||
2755 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
2756 | memset(&info->status, 0, sizeof(info->status)); | ||
2757 | info->flags = IEEE80211_TX_STAT_ACK; | ||
2758 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
2759 | info->status.ampdu_ack_map = successes; | ||
2760 | info->status.ampdu_ack_len = agg->frame_count; | ||
2761 | iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
2762 | |||
2763 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); | ||
2764 | |||
2765 | return 0; | ||
2766 | } | ||
2767 | |||
2768 | /** | 1911 | /** |
2769 | * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration | 1912 | * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration |
2770 | */ | 1913 | */ |
@@ -2816,82 +1959,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
2816 | return 0; | 1959 | return 0; |
2817 | } | 1960 | } |
2818 | 1961 | ||
2819 | |||
2820 | /** | ||
2821 | * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
2822 | * | ||
2823 | * Handles block-acknowledge notification from device, which reports success | ||
2824 | * of frames sent via aggregation. | ||
2825 | */ | ||
2826 | static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
2827 | struct iwl_rx_mem_buffer *rxb) | ||
2828 | { | ||
2829 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
2830 | struct iwl4965_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
2831 | int index; | ||
2832 | struct iwl_tx_queue *txq = NULL; | ||
2833 | struct iwl_ht_agg *agg; | ||
2834 | DECLARE_MAC_BUF(mac); | ||
2835 | |||
2836 | /* "flow" corresponds to Tx queue */ | ||
2837 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
2838 | |||
2839 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
2840 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
2841 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
2842 | |||
2843 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
2844 | IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); | ||
2845 | return; | ||
2846 | } | ||
2847 | |||
2848 | txq = &priv->txq[scd_flow]; | ||
2849 | agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; | ||
2850 | |||
2851 | /* Find index just before block-ack window */ | ||
2852 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
2853 | |||
2854 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
2855 | |||
2856 | IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, " | ||
2857 | "sta_id = %d\n", | ||
2858 | agg->wait_for_ba, | ||
2859 | print_mac(mac, (u8*) &ba_resp->sta_addr_lo32), | ||
2860 | ba_resp->sta_id); | ||
2861 | IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
2862 | "%d, scd_ssn = %d\n", | ||
2863 | ba_resp->tid, | ||
2864 | ba_resp->seq_ctl, | ||
2865 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
2866 | ba_resp->scd_flow, | ||
2867 | ba_resp->scd_ssn); | ||
2868 | IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", | ||
2869 | agg->start_idx, | ||
2870 | (unsigned long long)agg->bitmap); | ||
2871 | |||
2872 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
2873 | iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
2874 | |||
2875 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
2876 | * block-ack window (we assume that they've been successfully | ||
2877 | * transmitted ... if not, it's too late anyway). */ | ||
2878 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
2879 | /* calculate mac80211 ampdu sw queue to wake */ | ||
2880 | int ampdu_q = | ||
2881 | scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues; | ||
2882 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | ||
2883 | priv->stations[ba_resp->sta_id]. | ||
2884 | tid[ba_resp->tid].tfds_in_queue -= freed; | ||
2885 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && | ||
2886 | priv->mac80211_registered && | ||
2887 | agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
2888 | ieee80211_wake_queue(priv->hw, ampdu_q); | ||
2889 | |||
2890 | iwl_txq_check_empty(priv, ba_resp->sta_id, | ||
2891 | ba_resp->tid, scd_flow); | ||
2892 | } | ||
2893 | } | ||
2894 | |||
2895 | /** | 1962 | /** |
2896 | * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue | 1963 | * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue |
2897 | */ | 1964 | */ |
@@ -2986,49 +2053,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
2986 | return 0; | 2053 | return 0; |
2987 | } | 2054 | } |
2988 | 2055 | ||
2989 | static int iwl4965_rx_agg_start(struct iwl_priv *priv, | ||
2990 | const u8 *addr, int tid, u16 ssn) | ||
2991 | { | ||
2992 | unsigned long flags; | ||
2993 | int sta_id; | ||
2994 | |||
2995 | sta_id = iwl_find_station(priv, addr); | ||
2996 | if (sta_id == IWL_INVALID_STATION) | ||
2997 | return -ENXIO; | ||
2998 | |||
2999 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
3000 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
3001 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; | ||
3002 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; | ||
3003 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); | ||
3004 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
3005 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
3006 | |||
3007 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
3008 | CMD_ASYNC); | ||
3009 | } | ||
3010 | |||
3011 | static int iwl4965_rx_agg_stop(struct iwl_priv *priv, | ||
3012 | const u8 *addr, int tid) | ||
3013 | { | ||
3014 | unsigned long flags; | ||
3015 | int sta_id; | ||
3016 | |||
3017 | sta_id = iwl_find_station(priv, addr); | ||
3018 | if (sta_id == IWL_INVALID_STATION) | ||
3019 | return -ENXIO; | ||
3020 | |||
3021 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
3022 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
3023 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | ||
3024 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | ||
3025 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
3026 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
3027 | |||
3028 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
3029 | CMD_ASYNC); | ||
3030 | } | ||
3031 | |||
3032 | int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | 2056 | int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, |
3033 | enum ieee80211_ampdu_mlme_action action, | 2057 | enum ieee80211_ampdu_mlme_action action, |
3034 | const u8 *addr, u16 tid, u16 *ssn) | 2058 | const u8 *addr, u16 tid, u16 *ssn) |
@@ -3039,13 +2063,16 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3039 | IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", | 2063 | IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", |
3040 | print_mac(mac, addr), tid); | 2064 | print_mac(mac, addr), tid); |
3041 | 2065 | ||
2066 | if (!(priv->cfg->sku & IWL_SKU_N)) | ||
2067 | return -EACCES; | ||
2068 | |||
3042 | switch (action) { | 2069 | switch (action) { |
3043 | case IEEE80211_AMPDU_RX_START: | 2070 | case IEEE80211_AMPDU_RX_START: |
3044 | IWL_DEBUG_HT("start Rx\n"); | 2071 | IWL_DEBUG_HT("start Rx\n"); |
3045 | return iwl4965_rx_agg_start(priv, addr, tid, *ssn); | 2072 | return iwl_rx_agg_start(priv, addr, tid, *ssn); |
3046 | case IEEE80211_AMPDU_RX_STOP: | 2073 | case IEEE80211_AMPDU_RX_STOP: |
3047 | IWL_DEBUG_HT("stop Rx\n"); | 2074 | IWL_DEBUG_HT("stop Rx\n"); |
3048 | return iwl4965_rx_agg_stop(priv, addr, tid); | 2075 | return iwl_rx_agg_stop(priv, addr, tid); |
3049 | case IEEE80211_AMPDU_TX_START: | 2076 | case IEEE80211_AMPDU_TX_START: |
3050 | IWL_DEBUG_HT("start Tx\n"); | 2077 | IWL_DEBUG_HT("start Tx\n"); |
3051 | return iwl_tx_agg_start(priv, addr, tid, ssn); | 2078 | return iwl_tx_agg_start(priv, addr, tid, ssn); |
@@ -3320,11 +2347,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
3320 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2347 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
3321 | { | 2348 | { |
3322 | /* Legacy Rx frames */ | 2349 | /* Legacy Rx frames */ |
3323 | priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; | 2350 | priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; |
3324 | /* Tx response */ | 2351 | /* Tx response */ |
3325 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2352 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
3326 | /* block ack */ | ||
3327 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba; | ||
3328 | } | 2353 | } |
3329 | 2354 | ||
3330 | static void iwl4965_setup_deferred_work(struct iwl_priv *priv) | 2355 | static void iwl4965_setup_deferred_work(struct iwl_priv *priv) |
@@ -3391,6 +2416,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
3391 | .set_power = iwl4965_set_power, | 2416 | .set_power = iwl4965_set_power, |
3392 | .send_tx_power = iwl4965_send_tx_power, | 2417 | .send_tx_power = iwl4965_send_tx_power, |
3393 | .update_chain_flags = iwl4965_update_chain_flags, | 2418 | .update_chain_flags = iwl4965_update_chain_flags, |
2419 | .temperature = iwl4965_temperature_calib, | ||
3394 | }; | 2420 | }; |
3395 | 2421 | ||
3396 | static struct iwl_ops iwl4965_ops = { | 2422 | static struct iwl_ops iwl4965_ops = { |
@@ -3422,11 +2448,14 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | |||
3422 | 2448 | ||
3423 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); | 2449 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); |
3424 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | 2450 | MODULE_PARM_DESC(queues_num, "number of hw queues."); |
3425 | |||
3426 | /* QoS */ | 2451 | /* QoS */ |
3427 | module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444); | 2452 | module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444); |
3428 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); | 2453 | MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); |
2454 | /* 11n */ | ||
2455 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444); | ||
2456 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
3429 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); | 2457 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); |
3430 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 2458 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); |
2459 | |||
3431 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); | 2460 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); |
3432 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | 2461 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 438c3812c390..7cc73e9a711c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -675,7 +675,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv) | |||
675 | goto restart; | 675 | goto restart; |
676 | } | 676 | } |
677 | 677 | ||
678 | iwlcore_clear_stations_table(priv); | 678 | iwl_clear_stations_table(priv); |
679 | ret = priv->cfg->ops->lib->alive_notify(priv); | 679 | ret = priv->cfg->ops->lib->alive_notify(priv); |
680 | if (ret) { | 680 | if (ret) { |
681 | IWL_WARNING("Could not complete ALIVE transition: %d\n", ret); | 681 | IWL_WARNING("Could not complete ALIVE transition: %d\n", ret); |
@@ -807,11 +807,8 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) | |||
807 | 807 | ||
808 | iwl5000_send_Xtal_calib(priv); | 808 | iwl5000_send_Xtal_calib(priv); |
809 | 809 | ||
810 | if (priv->ucode_type == UCODE_RT) { | 810 | if (priv->ucode_type == UCODE_RT) |
811 | iwl5000_send_calib_results(priv); | 811 | iwl5000_send_calib_results(priv); |
812 | set_bit(STATUS_READY, &priv->status); | ||
813 | priv->is_open = 1; | ||
814 | } | ||
815 | 812 | ||
816 | return 0; | 813 | return 0; |
817 | } | 814 | } |
@@ -827,19 +824,11 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
827 | 824 | ||
828 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 825 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
829 | priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE; | 826 | priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE; |
830 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; | ||
831 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
832 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
833 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
834 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | ||
835 | else | ||
836 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | ||
837 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | ||
838 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 827 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
839 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 828 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
840 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 829 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; |
841 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 830 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; |
842 | priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; | 831 | priv->hw_params.max_bsm_size = 0; |
843 | priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | | 832 | priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | |
844 | BIT(IEEE80211_BAND_5GHZ); | 833 | BIT(IEEE80211_BAND_5GHZ); |
845 | priv->hw_params.sens = &iwl5000_sensitivity; | 834 | priv->hw_params.sens = &iwl5000_sensitivity; |
@@ -1426,13 +1415,18 @@ static int iwl5000_send_tx_power(struct iwl_priv *priv) | |||
1426 | 1415 | ||
1427 | /* half dBm need to multiply */ | 1416 | /* half dBm need to multiply */ |
1428 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 1417 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); |
1429 | tx_power_cmd.flags = 0; | 1418 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; |
1430 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | 1419 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; |
1431 | return iwl_send_cmd_pdu_async(priv, REPLY_TX_POWER_DBM_CMD, | 1420 | return iwl_send_cmd_pdu_async(priv, REPLY_TX_POWER_DBM_CMD, |
1432 | sizeof(tx_power_cmd), &tx_power_cmd, | 1421 | sizeof(tx_power_cmd), &tx_power_cmd, |
1433 | NULL); | 1422 | NULL); |
1434 | } | 1423 | } |
1435 | 1424 | ||
1425 | static void iwl5000_temperature(struct iwl_priv *priv) | ||
1426 | { | ||
1427 | /* store temperature from statistics (in Celsius) */ | ||
1428 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
1429 | } | ||
1436 | 1430 | ||
1437 | static struct iwl_hcmd_ops iwl5000_hcmd = { | 1431 | static struct iwl_hcmd_ops iwl5000_hcmd = { |
1438 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1432 | .rxon_assoc = iwl5000_send_rxon_assoc, |
@@ -1462,6 +1456,7 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
1462 | .init_alive_start = iwl5000_init_alive_start, | 1456 | .init_alive_start = iwl5000_init_alive_start, |
1463 | .alive_notify = iwl5000_alive_notify, | 1457 | .alive_notify = iwl5000_alive_notify, |
1464 | .send_tx_power = iwl5000_send_tx_power, | 1458 | .send_tx_power = iwl5000_send_tx_power, |
1459 | .temperature = iwl5000_temperature, | ||
1465 | .apm_ops = { | 1460 | .apm_ops = { |
1466 | .init = iwl5000_apm_init, | 1461 | .init = iwl5000_apm_init, |
1467 | .reset = iwl5000_apm_reset, | 1462 | .reset = iwl5000_apm_reset, |
@@ -1541,6 +1536,8 @@ module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | |||
1541 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | 1536 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); |
1542 | module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444); | 1537 | module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444); |
1543 | MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality"); | 1538 | MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality"); |
1539 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); | ||
1540 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | ||
1544 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); | 1541 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); |
1545 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | 1542 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); |
1546 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); | 1543 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 48f58000b64b..ef49440bd7f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -470,7 +470,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
470 | EXPORT_SYMBOL(iwl_init_sensitivity); | 470 | EXPORT_SYMBOL(iwl_init_sensitivity); |
471 | 471 | ||
472 | void iwl_sensitivity_calibration(struct iwl_priv *priv, | 472 | void iwl_sensitivity_calibration(struct iwl_priv *priv, |
473 | struct iwl4965_notif_statistics *resp) | 473 | struct iwl_notif_statistics *resp) |
474 | { | 474 | { |
475 | u32 rx_enable_time; | 475 | u32 rx_enable_time; |
476 | u32 fa_cck; | 476 | u32 fa_cck; |
@@ -584,7 +584,7 @@ EXPORT_SYMBOL(iwl_sensitivity_calibration); | |||
584 | * 2) Differential rx gain settings to balance the 3 receivers. | 584 | * 2) Differential rx gain settings to balance the 3 receivers. |
585 | */ | 585 | */ |
586 | void iwl_chain_noise_calibration(struct iwl_priv *priv, | 586 | void iwl_chain_noise_calibration(struct iwl_priv *priv, |
587 | struct iwl4965_notif_statistics *stat_resp) | 587 | struct iwl_notif_statistics *stat_resp) |
588 | { | 588 | { |
589 | struct iwl_chain_noise_data *data = NULL; | 589 | struct iwl_chain_noise_data *data = NULL; |
590 | 590 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index 5524a29e22d8..94c8e316382a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h | |||
@@ -67,9 +67,9 @@ | |||
67 | #include "iwl-commands.h" | 67 | #include "iwl-commands.h" |
68 | 68 | ||
69 | void iwl_chain_noise_calibration(struct iwl_priv *priv, | 69 | void iwl_chain_noise_calibration(struct iwl_priv *priv, |
70 | struct iwl4965_notif_statistics *stat_resp); | 70 | struct iwl_notif_statistics *stat_resp); |
71 | void iwl_sensitivity_calibration(struct iwl_priv *priv, | 71 | void iwl_sensitivity_calibration(struct iwl_priv *priv, |
72 | struct iwl4965_notif_statistics *resp); | 72 | struct iwl_notif_statistics *resp); |
73 | 73 | ||
74 | void iwl_init_sensitivity(struct iwl_priv *priv); | 74 | void iwl_init_sensitivity(struct iwl_priv *priv); |
75 | void iwl_reset_run_time_calib(struct iwl_priv *priv); | 75 | void iwl_reset_run_time_calib(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 920dfc1b2db2..fe05d60ebe63 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -336,6 +336,8 @@ struct iwl4965_tx_power_db { | |||
336 | * struct iwl5000_tx_power_dbm_cmd | 336 | * struct iwl5000_tx_power_dbm_cmd |
337 | */ | 337 | */ |
338 | #define IWL50_TX_POWER_AUTO 0x7f | 338 | #define IWL50_TX_POWER_AUTO 0x7f |
339 | #define IWL50_TX_POWER_NO_CLOSED (0x1 << 6) | ||
340 | |||
339 | struct iwl5000_tx_power_dbm_cmd { | 341 | struct iwl5000_tx_power_dbm_cmd { |
340 | s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ | 342 | s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ |
341 | u8 flags; | 343 | u8 flags; |
@@ -1534,7 +1536,7 @@ struct iwl5000_tx_resp { | |||
1534 | * | 1536 | * |
1535 | * Reports Block-Acknowledge from recipient station | 1537 | * Reports Block-Acknowledge from recipient station |
1536 | */ | 1538 | */ |
1537 | struct iwl4965_compressed_ba_resp { | 1539 | struct iwl_compressed_ba_resp { |
1538 | __le32 sta_addr_lo32; | 1540 | __le32 sta_addr_lo32; |
1539 | __le16 sta_addr_hi16; | 1541 | __le16 sta_addr_hi16; |
1540 | __le16 reserved; | 1542 | __le16 reserved; |
@@ -2504,7 +2506,7 @@ struct statistics_general { | |||
2504 | */ | 2506 | */ |
2505 | #define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */ | 2507 | #define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */ |
2506 | #define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */ | 2508 | #define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */ |
2507 | struct iwl4965_statistics_cmd { | 2509 | struct iwl_statistics_cmd { |
2508 | __le32 configuration_flags; /* IWL_STATS_CONF_* */ | 2510 | __le32 configuration_flags; /* IWL_STATS_CONF_* */ |
2509 | } __attribute__ ((packed)); | 2511 | } __attribute__ ((packed)); |
2510 | 2512 | ||
@@ -2525,7 +2527,7 @@ struct iwl4965_statistics_cmd { | |||
2525 | */ | 2527 | */ |
2526 | #define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2) | 2528 | #define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2) |
2527 | #define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8) | 2529 | #define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8) |
2528 | struct iwl4965_notif_statistics { | 2530 | struct iwl_notif_statistics { |
2529 | __le32 flag; | 2531 | __le32 flag; |
2530 | struct statistics_rx rx; | 2532 | struct statistics_rx rx; |
2531 | struct statistics_tx tx; | 2533 | struct statistics_tx tx; |
@@ -2998,8 +3000,8 @@ struct iwl_rx_packet { | |||
2998 | struct iwl_rem_sta_resp rem_sta; | 3000 | struct iwl_rem_sta_resp rem_sta; |
2999 | struct iwl4965_sleep_notification sleep_notif; | 3001 | struct iwl4965_sleep_notification sleep_notif; |
3000 | struct iwl4965_spectrum_resp spectrum; | 3002 | struct iwl4965_spectrum_resp spectrum; |
3001 | struct iwl4965_notif_statistics stats; | 3003 | struct iwl_notif_statistics stats; |
3002 | struct iwl4965_compressed_ba_resp compressed_ba; | 3004 | struct iwl_compressed_ba_resp compressed_ba; |
3003 | struct iwl4965_missed_beacon_notif missed_beacon; | 3005 | struct iwl4965_missed_beacon_notif missed_beacon; |
3004 | struct iwl5000_calibration calib; | 3006 | struct iwl5000_calibration calib; |
3005 | __le32 status; | 3007 | __le32 status; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eb74a40a62eb..eee220cf52a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -273,22 +273,27 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
273 | EXPORT_SYMBOL(iwl_hw_nic_init); | 273 | EXPORT_SYMBOL(iwl_hw_nic_init); |
274 | 274 | ||
275 | /** | 275 | /** |
276 | * iwlcore_clear_stations_table - Clear the driver's station table | 276 | * iwl_clear_stations_table - Clear the driver's station table |
277 | * | 277 | * |
278 | * NOTE: This does not clear or otherwise alter the device's station table. | 278 | * NOTE: This does not clear or otherwise alter the device's station table. |
279 | */ | 279 | */ |
280 | void iwlcore_clear_stations_table(struct iwl_priv *priv) | 280 | void iwl_clear_stations_table(struct iwl_priv *priv) |
281 | { | 281 | { |
282 | unsigned long flags; | 282 | unsigned long flags; |
283 | 283 | ||
284 | spin_lock_irqsave(&priv->sta_lock, flags); | 284 | spin_lock_irqsave(&priv->sta_lock, flags); |
285 | 285 | ||
286 | if (iwl_is_alive(priv) && | ||
287 | !test_bit(STATUS_EXIT_PENDING, &priv->status) && | ||
288 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) | ||
289 | IWL_ERROR("Couldn't clear the station table\n"); | ||
290 | |||
286 | priv->num_stations = 0; | 291 | priv->num_stations = 0; |
287 | memset(priv->stations, 0, sizeof(priv->stations)); | 292 | memset(priv->stations, 0, sizeof(priv->stations)); |
288 | 293 | ||
289 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 294 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
290 | } | 295 | } |
291 | EXPORT_SYMBOL(iwlcore_clear_stations_table); | 296 | EXPORT_SYMBOL(iwl_clear_stations_table); |
292 | 297 | ||
293 | void iwl_reset_qos(struct iwl_priv *priv) | 298 | void iwl_reset_qos(struct iwl_priv *priv) |
294 | { | 299 | { |
@@ -490,7 +495,9 @@ static int iwlcore_init_geos(struct iwl_priv *priv) | |||
490 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | 495 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; |
491 | sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; | 496 | sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; |
492 | 497 | ||
493 | iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ); | 498 | if (priv->cfg->sku & IWL_SKU_N) |
499 | iwlcore_init_ht_hw_capab(priv, &sband->ht_info, | ||
500 | IEEE80211_BAND_5GHZ); | ||
494 | 501 | ||
495 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | 502 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; |
496 | sband->channels = channels; | 503 | sband->channels = channels; |
@@ -498,7 +505,9 @@ static int iwlcore_init_geos(struct iwl_priv *priv) | |||
498 | sband->bitrates = rates; | 505 | sband->bitrates = rates; |
499 | sband->n_bitrates = IWL_RATE_COUNT; | 506 | sband->n_bitrates = IWL_RATE_COUNT; |
500 | 507 | ||
501 | iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ); | 508 | if (priv->cfg->sku & IWL_SKU_N) |
509 | iwlcore_init_ht_hw_capab(priv, &sband->ht_info, | ||
510 | IEEE80211_BAND_2GHZ); | ||
502 | 511 | ||
503 | priv->ieee_channels = channels; | 512 | priv->ieee_channels = channels; |
504 | priv->ieee_rates = rates; | 513 | priv->ieee_rates = rates; |
@@ -814,8 +823,9 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
814 | IEEE80211_HW_NOISE_DBM; | 823 | IEEE80211_HW_NOISE_DBM; |
815 | /* Default value; 4 EDCA QOS priorities */ | 824 | /* Default value; 4 EDCA QOS priorities */ |
816 | hw->queues = 4; | 825 | hw->queues = 4; |
817 | /* Enhanced value; more queues, to support 11n aggregation */ | 826 | /* queues to support 11n aggregation */ |
818 | hw->ampdu_queues = 12; | 827 | if (priv->cfg->sku & IWL_SKU_N) |
828 | hw->ampdu_queues = 12; | ||
819 | 829 | ||
820 | hw->conf.beacon_int = 100; | 830 | hw->conf.beacon_int = 100; |
821 | 831 | ||
@@ -837,11 +847,28 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
837 | } | 847 | } |
838 | EXPORT_SYMBOL(iwl_setup_mac); | 848 | EXPORT_SYMBOL(iwl_setup_mac); |
839 | 849 | ||
850 | int iwl_set_hw_params(struct iwl_priv *priv) | ||
851 | { | ||
852 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; | ||
853 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
854 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
855 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
856 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | ||
857 | else | ||
858 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | ||
859 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | ||
860 | |||
861 | if (priv->cfg->mod_params->disable_11n) | ||
862 | priv->cfg->sku &= ~IWL_SKU_N; | ||
863 | |||
864 | /* Device-specific setup */ | ||
865 | return priv->cfg->ops->lib->set_hw_params(priv); | ||
866 | } | ||
867 | EXPORT_SYMBOL(iwl_set_hw_params); | ||
840 | 868 | ||
841 | int iwl_init_drv(struct iwl_priv *priv) | 869 | int iwl_init_drv(struct iwl_priv *priv) |
842 | { | 870 | { |
843 | int ret; | 871 | int ret; |
844 | int i; | ||
845 | 872 | ||
846 | priv->retry_rate = 1; | 873 | priv->retry_rate = 1; |
847 | priv->ibss_beacon = NULL; | 874 | priv->ibss_beacon = NULL; |
@@ -852,15 +879,12 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
852 | spin_lock_init(&priv->hcmd_lock); | 879 | spin_lock_init(&priv->hcmd_lock); |
853 | spin_lock_init(&priv->lq_mngr.lock); | 880 | spin_lock_init(&priv->lq_mngr.lock); |
854 | 881 | ||
855 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) | ||
856 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | ||
857 | |||
858 | INIT_LIST_HEAD(&priv->free_frames); | 882 | INIT_LIST_HEAD(&priv->free_frames); |
859 | 883 | ||
860 | mutex_init(&priv->mutex); | 884 | mutex_init(&priv->mutex); |
861 | 885 | ||
862 | /* Clear the driver's (not device's) station table */ | 886 | /* Clear the driver's (not device's) station table */ |
863 | iwlcore_clear_stations_table(priv); | 887 | iwl_clear_stations_table(priv); |
864 | 888 | ||
865 | priv->data_retry_limit = -1; | 889 | priv->data_retry_limit = -1; |
866 | priv->ieee_channels = NULL; | 890 | priv->ieee_channels = NULL; |
@@ -1383,7 +1407,14 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) | |||
1383 | spin_lock_irqsave(&priv->lock, flags); | 1407 | spin_lock_irqsave(&priv->lock, flags); |
1384 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | 1408 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); |
1385 | 1409 | ||
1386 | clear_bit(STATUS_RF_KILL_SW, &priv->status); | 1410 | /* If the driver is up it will receive CARD_STATE_NOTIFICATION |
1411 | * notification where it will clear SW rfkill status. | ||
1412 | * Setting it here would break the handler. Only if the | ||
1413 | * interface is down we can set here since we don't | ||
1414 | * receive any further notification. | ||
1415 | */ | ||
1416 | if (!priv->is_open) | ||
1417 | clear_bit(STATUS_RF_KILL_SW, &priv->status); | ||
1387 | spin_unlock_irqrestore(&priv->lock, flags); | 1418 | spin_unlock_irqrestore(&priv->lock, flags); |
1388 | 1419 | ||
1389 | /* wake up ucode */ | 1420 | /* wake up ucode */ |
@@ -1401,8 +1432,10 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv) | |||
1401 | return 0; | 1432 | return 0; |
1402 | } | 1433 | } |
1403 | 1434 | ||
1404 | if (priv->is_open) | 1435 | /* If the driver is already loaded, it will receive |
1405 | queue_work(priv->workqueue, &priv->restart); | 1436 | * CARD_STATE_NOTIFICATION notifications and the handler will |
1437 | * call restart to reload the driver. | ||
1438 | */ | ||
1406 | return 1; | 1439 | return 1; |
1407 | } | 1440 | } |
1408 | EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); | 1441 | EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 2838093b4459..eb4abe1ebbdb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -140,6 +140,7 @@ struct iwl_lib_ops { | |||
140 | int (*set_power)(struct iwl_priv *priv, void *cmd); | 140 | int (*set_power)(struct iwl_priv *priv, void *cmd); |
141 | int (*send_tx_power) (struct iwl_priv *priv); | 141 | int (*send_tx_power) (struct iwl_priv *priv); |
142 | void (*update_chain_flags)(struct iwl_priv *priv); | 142 | void (*update_chain_flags)(struct iwl_priv *priv); |
143 | void (*temperature) (struct iwl_priv *priv); | ||
143 | /* eeprom operations (as defined in iwl-eeprom.h) */ | 144 | /* eeprom operations (as defined in iwl-eeprom.h) */ |
144 | struct iwl_eeprom_ops eeprom_ops; | 145 | struct iwl_eeprom_ops eeprom_ops; |
145 | }; | 146 | }; |
@@ -157,6 +158,7 @@ struct iwl_mod_params { | |||
157 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 158 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
158 | int num_of_queues; /* def: HW dependent */ | 159 | int num_of_queues; /* def: HW dependent */ |
159 | int enable_qos; /* def: 1 = use quality of service */ | 160 | int enable_qos; /* def: 1 = use quality of service */ |
161 | int disable_11n; /* def: 0 = disable 11n capabilities */ | ||
160 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ | 162 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ |
161 | int antenna; /* def: 0 = both antennas (use diversity) */ | 163 | int antenna; /* def: 0 = both antennas (use diversity) */ |
162 | int restart_fw; /* def: 1 = restart firmware */ | 164 | int restart_fw; /* def: 1 = restart firmware */ |
@@ -179,7 +181,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | |||
179 | struct ieee80211_ops *hw_ops); | 181 | struct ieee80211_ops *hw_ops); |
180 | void iwl_hw_detect(struct iwl_priv *priv); | 182 | void iwl_hw_detect(struct iwl_priv *priv); |
181 | 183 | ||
182 | void iwlcore_clear_stations_table(struct iwl_priv *priv); | 184 | void iwl_clear_stations_table(struct iwl_priv *priv); |
183 | void iwl_free_calib_results(struct iwl_priv *priv); | 185 | void iwl_free_calib_results(struct iwl_priv *priv); |
184 | void iwl_reset_qos(struct iwl_priv *priv); | 186 | void iwl_reset_qos(struct iwl_priv *priv); |
185 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 187 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
@@ -191,6 +193,7 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, | |||
191 | struct ieee80211_ht_info *sta_ht_inf); | 193 | struct ieee80211_ht_info *sta_ht_inf); |
192 | int iwl_hw_nic_init(struct iwl_priv *priv); | 194 | int iwl_hw_nic_init(struct iwl_priv *priv); |
193 | int iwl_setup_mac(struct iwl_priv *priv); | 195 | int iwl_setup_mac(struct iwl_priv *priv); |
196 | int iwl_set_hw_params(struct iwl_priv *priv); | ||
194 | int iwl_init_drv(struct iwl_priv *priv); | 197 | int iwl_init_drv(struct iwl_priv *priv); |
195 | void iwl_uninit_drv(struct iwl_priv *priv); | 198 | void iwl_uninit_drv(struct iwl_priv *priv); |
196 | /* "keep warm" functions */ | 199 | /* "keep warm" functions */ |
@@ -209,6 +212,8 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | |||
209 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 212 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
210 | void iwl_rx_replenish(struct iwl_priv *priv); | 213 | void iwl_rx_replenish(struct iwl_priv *priv); |
211 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 214 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
215 | int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn); | ||
216 | int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | ||
212 | /* FIXME: remove when TX is moved to iwl core */ | 217 | /* FIXME: remove when TX is moved to iwl core */ |
213 | int iwl_rx_queue_restock(struct iwl_priv *priv); | 218 | int iwl_rx_queue_restock(struct iwl_priv *priv); |
214 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 219 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
@@ -218,6 +223,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | |||
218 | /* Handlers */ | 223 | /* Handlers */ |
219 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 224 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
220 | struct iwl_rx_mem_buffer *rxb); | 225 | struct iwl_rx_mem_buffer *rxb); |
226 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
227 | struct iwl_rx_mem_buffer *rxb); | ||
221 | 228 | ||
222 | /* TX helpers */ | 229 | /* TX helpers */ |
223 | 230 | ||
@@ -368,7 +375,13 @@ extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | |||
368 | extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); | 375 | extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); |
369 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 376 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
370 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 377 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
371 | struct iwl_link_quality_cmd *lq, u8 flags); | 378 | struct iwl_link_quality_cmd *lq, u8 flags); |
379 | extern void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
380 | struct iwl_rx_mem_buffer *rxb); | ||
381 | extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
382 | struct iwl_rx_mem_buffer *rxb); | ||
383 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
384 | struct iwl_rx_mem_buffer *rxb); | ||
372 | 385 | ||
373 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 386 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
374 | { | 387 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 81ff4c2c6a5a..d1289cfc213c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -591,11 +591,6 @@ extern int iwl_send_add_sta(struct iwl_priv *priv, | |||
591 | struct iwl_addsta_cmd *sta, u8 flags); | 591 | struct iwl_addsta_cmd *sta, u8 flags); |
592 | u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, | 592 | u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, |
593 | u8 flags, struct ieee80211_ht_info *ht_info); | 593 | u8 flags, struct ieee80211_ht_info *ht_info); |
594 | extern int iwl4965_is_network_packet(struct iwl_priv *priv, | ||
595 | struct ieee80211_hdr *header); | ||
596 | extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv, | ||
597 | struct ieee80211_hdr *header); | ||
598 | extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm); | ||
599 | extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, | 594 | extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, |
600 | struct ieee80211_hdr *hdr, | 595 | struct ieee80211_hdr *hdr, |
601 | const u8 *dest, int left); | 596 | const u8 *dest, int left); |
@@ -624,11 +619,7 @@ extern int iwl_rxq_stop(struct iwl_priv *priv); | |||
624 | extern void iwl_txq_ctx_stop(struct iwl_priv *priv); | 619 | extern void iwl_txq_ctx_stop(struct iwl_priv *priv); |
625 | extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | 620 | extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, |
626 | struct iwl_frame *frame, u8 rate); | 621 | struct iwl_frame *frame, u8 rate); |
627 | extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv, | ||
628 | struct iwl_rx_mem_buffer *rxb); | ||
629 | extern void iwl4965_disable_events(struct iwl_priv *priv); | 622 | extern void iwl4965_disable_events(struct iwl_priv *priv); |
630 | extern void iwl4965_rx_reply_rx(struct iwl_priv *priv, | ||
631 | struct iwl_rx_mem_buffer *rxb); | ||
632 | 623 | ||
633 | extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); | 624 | extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); |
634 | extern int iwl_queue_space(const struct iwl_queue *q); | 625 | extern int iwl_queue_space(const struct iwl_queue *q); |
@@ -702,7 +693,6 @@ struct iwl4965_lq_mngr { | |||
702 | unsigned long stamp_last; | 693 | unsigned long stamp_last; |
703 | u32 flush_time; | 694 | u32 flush_time; |
704 | u32 tx_packets; | 695 | u32 tx_packets; |
705 | u8 lq_ready; | ||
706 | }; | 696 | }; |
707 | 697 | ||
708 | /* Sensitivity and chain noise calibration */ | 698 | /* Sensitivity and chain noise calibration */ |
@@ -994,7 +984,7 @@ struct iwl_priv { | |||
994 | 984 | ||
995 | struct iwl_power_mgr power_data; | 985 | struct iwl_power_mgr power_data; |
996 | 986 | ||
997 | struct iwl4965_notif_statistics statistics; | 987 | struct iwl_notif_statistics statistics; |
998 | unsigned long last_statistics_time; | 988 | unsigned long last_statistics_time; |
999 | 989 | ||
1000 | /* context information */ | 990 | /* context information */ |
@@ -1026,14 +1016,6 @@ struct iwl_priv { | |||
1026 | u32 last_beacon_time; | 1016 | u32 last_beacon_time; |
1027 | u64 last_tsf; | 1017 | u64 last_tsf; |
1028 | 1018 | ||
1029 | /* Duplicate packet detection */ | ||
1030 | u16 last_seq_num; | ||
1031 | u16 last_frag_num; | ||
1032 | unsigned long last_packet_time; | ||
1033 | |||
1034 | /* Hash table for finding stations in IBSS network */ | ||
1035 | struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; | ||
1036 | |||
1037 | /* eeprom */ | 1019 | /* eeprom */ |
1038 | u8 *eeprom; | 1020 | u8 *eeprom; |
1039 | struct iwl_eeprom_calib_info *calib_info; | 1021 | struct iwl_eeprom_calib_info *calib_info; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 6c537360820b..8fa991b7202a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -93,6 +93,7 @@ const char *get_cmd_string(u8 cmd) | |||
93 | IWL_CMD(CALIBRATION_CFG_CMD); | 93 | IWL_CMD(CALIBRATION_CFG_CMD); |
94 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); | 94 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); |
95 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); | 95 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); |
96 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); | ||
96 | default: | 97 | default: |
97 | return "UNKNOWN"; | 98 | return "UNKNOWN"; |
98 | 99 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index ffefbb487e12..aa9f31eadab2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -50,7 +50,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
51 | return 0; | 51 | return 0; |
52 | 52 | ||
53 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | 53 | IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state); |
54 | mutex_lock(&priv->mutex); | 54 | mutex_lock(&priv->mutex); |
55 | 55 | ||
56 | switch (state) { | 56 | switch (state) { |
@@ -98,36 +98,11 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
98 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | 98 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; |
99 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | 99 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; |
100 | 100 | ||
101 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
102 | priv->rfkill_mngr.input_dev = input_allocate_device(); | ||
103 | if (!priv->rfkill_mngr.input_dev) { | ||
104 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | ||
105 | ret = -ENOMEM; | ||
106 | goto freed_rfkill; | ||
107 | } | ||
108 | |||
109 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | ||
110 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
111 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
112 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
113 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
114 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
115 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
116 | #endif | ||
117 | |||
118 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | 101 | ret = rfkill_register(priv->rfkill_mngr.rfkill); |
119 | if (ret) { | 102 | if (ret) { |
120 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | 103 | IWL_ERROR("Unable to register rfkill: %d\n", ret); |
121 | goto free_input_dev; | ||
122 | } | ||
123 | |||
124 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
125 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
126 | if (ret) { | ||
127 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | ||
128 | goto unregister_rfkill; | 104 | goto unregister_rfkill; |
129 | } | 105 | } |
130 | #endif | ||
131 | 106 | ||
132 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 107 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
133 | return ret; | 108 | return ret; |
@@ -136,12 +111,6 @@ unregister_rfkill: | |||
136 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 111 | rfkill_unregister(priv->rfkill_mngr.rfkill); |
137 | priv->rfkill_mngr.rfkill = NULL; | 112 | priv->rfkill_mngr.rfkill = NULL; |
138 | 113 | ||
139 | free_input_dev: | ||
140 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
141 | input_free_device(priv->rfkill_mngr.input_dev); | ||
142 | priv->rfkill_mngr.input_dev = NULL; | ||
143 | #endif | ||
144 | |||
145 | freed_rfkill: | 114 | freed_rfkill: |
146 | if (priv->rfkill_mngr.rfkill != NULL) | 115 | if (priv->rfkill_mngr.rfkill != NULL) |
147 | rfkill_free(priv->rfkill_mngr.rfkill); | 116 | rfkill_free(priv->rfkill_mngr.rfkill); |
@@ -156,13 +125,6 @@ EXPORT_SYMBOL(iwl_rfkill_init); | |||
156 | void iwl_rfkill_unregister(struct iwl_priv *priv) | 125 | void iwl_rfkill_unregister(struct iwl_priv *priv) |
157 | { | 126 | { |
158 | 127 | ||
159 | #if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) | ||
160 | if (priv->rfkill_mngr.input_dev) | ||
161 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
162 | input_free_device(priv->rfkill_mngr.input_dev); | ||
163 | priv->rfkill_mngr.input_dev = NULL; | ||
164 | #endif | ||
165 | |||
166 | if (priv->rfkill_mngr.rfkill) | 128 | if (priv->rfkill_mngr.rfkill) |
167 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 129 | rfkill_unregister(priv->rfkill_mngr.rfkill); |
168 | 130 | ||
@@ -173,7 +135,6 @@ EXPORT_SYMBOL(iwl_rfkill_unregister); | |||
173 | /* set rf-kill to the right state. */ | 135 | /* set rf-kill to the right state. */ |
174 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) | 136 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) |
175 | { | 137 | { |
176 | |||
177 | if (!priv->rfkill_mngr.rfkill) | 138 | if (!priv->rfkill_mngr.rfkill) |
178 | return; | 139 | return; |
179 | 140 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index b3c04dba45cf..00692d2e9bd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h | |||
@@ -31,12 +31,10 @@ | |||
31 | struct iwl_priv; | 31 | struct iwl_priv; |
32 | 32 | ||
33 | #include <linux/rfkill.h> | 33 | #include <linux/rfkill.h> |
34 | #include <linux/input.h> | ||
35 | 34 | ||
36 | #ifdef CONFIG_IWLWIFI_RFKILL | 35 | #ifdef CONFIG_IWLWIFI_RFKILL |
37 | struct iwl_rfkill_mngr { | 36 | struct iwl_rfkill_mngr { |
38 | struct rfkill *rfkill; | 37 | struct rfkill *rfkill; |
39 | struct input_dev *input_dev; | ||
40 | }; | 38 | }; |
41 | 39 | ||
42 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); | 40 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index c24844802a88..3e8500ecf598 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * | 27 | * |
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | 29 | ||
30 | #include <linux/etherdevice.h> | ||
30 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
31 | #include "iwl-eeprom.h" | 32 | #include "iwl-eeprom.h" |
32 | #include "iwl-dev.h" | 33 | #include "iwl-dev.h" |
@@ -466,3 +467,858 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
466 | } | 467 | } |
467 | } | 468 | } |
468 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | 469 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); |
470 | |||
471 | int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn) | ||
472 | { | ||
473 | unsigned long flags; | ||
474 | int sta_id; | ||
475 | |||
476 | sta_id = iwl_find_station(priv, addr); | ||
477 | if (sta_id == IWL_INVALID_STATION) | ||
478 | return -ENXIO; | ||
479 | |||
480 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
481 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
482 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; | ||
483 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; | ||
484 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); | ||
485 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
486 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
487 | |||
488 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
489 | CMD_ASYNC); | ||
490 | } | ||
491 | EXPORT_SYMBOL(iwl_rx_agg_start); | ||
492 | |||
493 | int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | ||
494 | { | ||
495 | unsigned long flags; | ||
496 | int sta_id; | ||
497 | |||
498 | sta_id = iwl_find_station(priv, addr); | ||
499 | if (sta_id == IWL_INVALID_STATION) | ||
500 | return -ENXIO; | ||
501 | |||
502 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
503 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
504 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | ||
505 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | ||
506 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
507 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
508 | |||
509 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
510 | CMD_ASYNC); | ||
511 | } | ||
512 | EXPORT_SYMBOL(iwl_rx_agg_stop); | ||
513 | |||
514 | |||
515 | /* Calculate noise level, based on measurements during network silence just | ||
516 | * before arriving beacon. This measurement can be done only if we know | ||
517 | * exactly when to expect beacons, therefore only when we're associated. */ | ||
518 | static void iwl_rx_calc_noise(struct iwl_priv *priv) | ||
519 | { | ||
520 | struct statistics_rx_non_phy *rx_info | ||
521 | = &(priv->statistics.rx.general); | ||
522 | int num_active_rx = 0; | ||
523 | int total_silence = 0; | ||
524 | int bcn_silence_a = | ||
525 | le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; | ||
526 | int bcn_silence_b = | ||
527 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | ||
528 | int bcn_silence_c = | ||
529 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | ||
530 | |||
531 | if (bcn_silence_a) { | ||
532 | total_silence += bcn_silence_a; | ||
533 | num_active_rx++; | ||
534 | } | ||
535 | if (bcn_silence_b) { | ||
536 | total_silence += bcn_silence_b; | ||
537 | num_active_rx++; | ||
538 | } | ||
539 | if (bcn_silence_c) { | ||
540 | total_silence += bcn_silence_c; | ||
541 | num_active_rx++; | ||
542 | } | ||
543 | |||
544 | /* Average among active antennas */ | ||
545 | if (num_active_rx) | ||
546 | priv->last_rx_noise = (total_silence / num_active_rx) - 107; | ||
547 | else | ||
548 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
549 | |||
550 | IWL_DEBUG_CALIB("inband silence a %u, b %u, c %u, dBm %d\n", | ||
551 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | ||
552 | priv->last_rx_noise); | ||
553 | } | ||
554 | |||
555 | #define REG_RECALIB_PERIOD (60) | ||
556 | |||
557 | void iwl_rx_statistics(struct iwl_priv *priv, | ||
558 | struct iwl_rx_mem_buffer *rxb) | ||
559 | { | ||
560 | int change; | ||
561 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
562 | |||
563 | IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n", | ||
564 | (int)sizeof(priv->statistics), pkt->len); | ||
565 | |||
566 | change = ((priv->statistics.general.temperature != | ||
567 | pkt->u.stats.general.temperature) || | ||
568 | ((priv->statistics.flag & | ||
569 | STATISTICS_REPLY_FLG_FAT_MODE_MSK) != | ||
570 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK))); | ||
571 | |||
572 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | ||
573 | |||
574 | set_bit(STATUS_STATISTICS, &priv->status); | ||
575 | |||
576 | /* Reschedule the statistics timer to occur in | ||
577 | * REG_RECALIB_PERIOD seconds to ensure we get a | ||
578 | * thermal update even if the uCode doesn't give | ||
579 | * us one */ | ||
580 | mod_timer(&priv->statistics_periodic, jiffies + | ||
581 | msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); | ||
582 | |||
583 | if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && | ||
584 | (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { | ||
585 | iwl_rx_calc_noise(priv); | ||
586 | queue_work(priv->workqueue, &priv->run_time_calib_work); | ||
587 | } | ||
588 | |||
589 | iwl_leds_background(priv); | ||
590 | |||
591 | if (priv->cfg->ops->lib->temperature && change) | ||
592 | priv->cfg->ops->lib->temperature(priv); | ||
593 | } | ||
594 | EXPORT_SYMBOL(iwl_rx_statistics); | ||
595 | |||
596 | #define PERFECT_RSSI (-20) /* dBm */ | ||
597 | #define WORST_RSSI (-95) /* dBm */ | ||
598 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
599 | |||
600 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
601 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
602 | * about formulas used below. */ | ||
603 | static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
604 | { | ||
605 | int sig_qual; | ||
606 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
607 | |||
608 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
609 | * as indicator; formula is (signal dbm - noise dbm). | ||
610 | * SNR at or above 40 is a great signal (100%). | ||
611 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
612 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
613 | if (noise_dbm) { | ||
614 | if (rssi_dbm - noise_dbm >= 40) | ||
615 | return 100; | ||
616 | else if (rssi_dbm < noise_dbm) | ||
617 | return 0; | ||
618 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
619 | |||
620 | /* Else use just the signal level. | ||
621 | * This formula is a least squares fit of data points collected and | ||
622 | * compared with a reference system that had a percentage (%) display | ||
623 | * for signal quality. */ | ||
624 | } else | ||
625 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
626 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
627 | (RSSI_RANGE * RSSI_RANGE); | ||
628 | |||
629 | if (sig_qual > 100) | ||
630 | sig_qual = 100; | ||
631 | else if (sig_qual < 1) | ||
632 | sig_qual = 0; | ||
633 | |||
634 | return sig_qual; | ||
635 | } | ||
636 | |||
637 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
638 | |||
639 | /** | ||
640 | * iwl_dbg_report_frame - dump frame to syslog during debug sessions | ||
641 | * | ||
642 | * You may hack this function to show different aspects of received frames, | ||
643 | * including selective frame dumps. | ||
644 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
645 | * | ||
646 | * TODO: This was originally written for 3945, need to audit for | ||
647 | * proper operation with 4965. | ||
648 | */ | ||
649 | static void iwl_dbg_report_frame(struct iwl_priv *priv, | ||
650 | struct iwl_rx_packet *pkt, | ||
651 | struct ieee80211_hdr *header, int group100) | ||
652 | { | ||
653 | u32 to_us; | ||
654 | u32 print_summary = 0; | ||
655 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
656 | u32 hundred = 0; | ||
657 | u32 dataframe = 0; | ||
658 | __le16 fc; | ||
659 | u16 seq_ctl; | ||
660 | u16 channel; | ||
661 | u16 phy_flags; | ||
662 | int rate_sym; | ||
663 | u16 length; | ||
664 | u16 status; | ||
665 | u16 bcn_tmr; | ||
666 | u32 tsf_low; | ||
667 | u64 tsf; | ||
668 | u8 rssi; | ||
669 | u8 agc; | ||
670 | u16 sig_avg; | ||
671 | u16 noise_diff; | ||
672 | struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
673 | struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
674 | struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
675 | u8 *data = IWL_RX_DATA(pkt); | ||
676 | |||
677 | if (likely(!(priv->debug_level & IWL_DL_RX))) | ||
678 | return; | ||
679 | |||
680 | /* MAC header */ | ||
681 | fc = header->frame_control; | ||
682 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
683 | |||
684 | /* metadata */ | ||
685 | channel = le16_to_cpu(rx_hdr->channel); | ||
686 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
687 | rate_sym = rx_hdr->rate; | ||
688 | length = le16_to_cpu(rx_hdr->len); | ||
689 | |||
690 | /* end-of-frame status and timestamp */ | ||
691 | status = le32_to_cpu(rx_end->status); | ||
692 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
693 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
694 | tsf = le64_to_cpu(rx_end->timestamp); | ||
695 | |||
696 | /* signal statistics */ | ||
697 | rssi = rx_stats->rssi; | ||
698 | agc = rx_stats->agc; | ||
699 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
700 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
701 | |||
702 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
703 | |||
704 | /* if data frame is to us and all is good, | ||
705 | * (optionally) print summary for only 1 out of every 100 */ | ||
706 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
707 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
708 | dataframe = 1; | ||
709 | if (!group100) | ||
710 | print_summary = 1; /* print each frame */ | ||
711 | else if (priv->framecnt_to_us < 100) { | ||
712 | priv->framecnt_to_us++; | ||
713 | print_summary = 0; | ||
714 | } else { | ||
715 | priv->framecnt_to_us = 0; | ||
716 | print_summary = 1; | ||
717 | hundred = 1; | ||
718 | } | ||
719 | } else { | ||
720 | /* print summary for all other frames */ | ||
721 | print_summary = 1; | ||
722 | } | ||
723 | |||
724 | if (print_summary) { | ||
725 | char *title; | ||
726 | int rate_idx; | ||
727 | u32 bitrate; | ||
728 | |||
729 | if (hundred) | ||
730 | title = "100Frames"; | ||
731 | else if (ieee80211_has_retry(fc)) | ||
732 | title = "Retry"; | ||
733 | else if (ieee80211_is_assoc_resp(fc)) | ||
734 | title = "AscRsp"; | ||
735 | else if (ieee80211_is_reassoc_resp(fc)) | ||
736 | title = "RasRsp"; | ||
737 | else if (ieee80211_is_probe_resp(fc)) { | ||
738 | title = "PrbRsp"; | ||
739 | print_dump = 1; /* dump frame contents */ | ||
740 | } else if (ieee80211_is_beacon(fc)) { | ||
741 | title = "Beacon"; | ||
742 | print_dump = 1; /* dump frame contents */ | ||
743 | } else if (ieee80211_is_atim(fc)) | ||
744 | title = "ATIM"; | ||
745 | else if (ieee80211_is_auth(fc)) | ||
746 | title = "Auth"; | ||
747 | else if (ieee80211_is_deauth(fc)) | ||
748 | title = "DeAuth"; | ||
749 | else if (ieee80211_is_disassoc(fc)) | ||
750 | title = "DisAssoc"; | ||
751 | else | ||
752 | title = "Frame"; | ||
753 | |||
754 | rate_idx = iwl_hwrate_to_plcp_idx(rate_sym); | ||
755 | if (unlikely(rate_idx == -1)) | ||
756 | bitrate = 0; | ||
757 | else | ||
758 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
759 | |||
760 | /* print frame summary. | ||
761 | * MAC addresses show just the last byte (for brevity), | ||
762 | * but you can hack it to show more, if you'd like to. */ | ||
763 | if (dataframe) | ||
764 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
765 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
766 | title, le16_to_cpu(fc), header->addr1[5], | ||
767 | length, rssi, channel, bitrate); | ||
768 | else { | ||
769 | /* src/dst addresses assume managed mode */ | ||
770 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
771 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
772 | "phy=0x%02x, chnl=%d\n", | ||
773 | title, le16_to_cpu(fc), header->addr1[5], | ||
774 | header->addr3[5], rssi, | ||
775 | tsf_low - priv->scan_start_tsf, | ||
776 | phy_flags, channel); | ||
777 | } | ||
778 | } | ||
779 | if (print_dump) | ||
780 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | ||
781 | } | ||
782 | #else | ||
783 | static inline void iwl_dbg_report_frame(struct iwl_priv *priv, | ||
784 | struct iwl_rx_packet *pkt, | ||
785 | struct ieee80211_hdr *header, | ||
786 | int group100) | ||
787 | { | ||
788 | } | ||
789 | #endif | ||
790 | |||
791 | static void iwl_add_radiotap(struct iwl_priv *priv, | ||
792 | struct sk_buff *skb, | ||
793 | struct iwl4965_rx_phy_res *rx_start, | ||
794 | struct ieee80211_rx_status *stats, | ||
795 | u32 ampdu_status) | ||
796 | { | ||
797 | s8 signal = stats->signal; | ||
798 | s8 noise = 0; | ||
799 | int rate = stats->rate_idx; | ||
800 | u64 tsf = stats->mactime; | ||
801 | __le16 antenna; | ||
802 | __le16 phy_flags_hw = rx_start->phy_flags; | ||
803 | struct iwl4965_rt_rx_hdr { | ||
804 | struct ieee80211_radiotap_header rt_hdr; | ||
805 | __le64 rt_tsf; /* TSF */ | ||
806 | u8 rt_flags; /* radiotap packet flags */ | ||
807 | u8 rt_rate; /* rate in 500kb/s */ | ||
808 | __le16 rt_channelMHz; /* channel in MHz */ | ||
809 | __le16 rt_chbitmask; /* channel bitfield */ | ||
810 | s8 rt_dbmsignal; /* signal in dBm, kluged to signed */ | ||
811 | s8 rt_dbmnoise; | ||
812 | u8 rt_antenna; /* antenna number */ | ||
813 | } __attribute__ ((packed)) *iwl4965_rt; | ||
814 | |||
815 | /* TODO: We won't have enough headroom for HT frames. Fix it later. */ | ||
816 | if (skb_headroom(skb) < sizeof(*iwl4965_rt)) { | ||
817 | if (net_ratelimit()) | ||
818 | printk(KERN_ERR "not enough headroom [%d] for " | ||
819 | "radiotap head [%zd]\n", | ||
820 | skb_headroom(skb), sizeof(*iwl4965_rt)); | ||
821 | return; | ||
822 | } | ||
823 | |||
824 | /* put radiotap header in front of 802.11 header and data */ | ||
825 | iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt)); | ||
826 | |||
827 | /* initialise radiotap header */ | ||
828 | iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
829 | iwl4965_rt->rt_hdr.it_pad = 0; | ||
830 | |||
831 | /* total header + data */ | ||
832 | put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), | ||
833 | &iwl4965_rt->rt_hdr.it_len); | ||
834 | |||
835 | /* Indicate all the fields we add to the radiotap header */ | ||
836 | put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | ||
837 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
838 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
839 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
840 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
841 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
842 | (1 << IEEE80211_RADIOTAP_ANTENNA)), | ||
843 | &iwl4965_rt->rt_hdr.it_present); | ||
844 | |||
845 | /* Zero the flags, we'll add to them as we go */ | ||
846 | iwl4965_rt->rt_flags = 0; | ||
847 | |||
848 | put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); | ||
849 | |||
850 | iwl4965_rt->rt_dbmsignal = signal; | ||
851 | iwl4965_rt->rt_dbmnoise = noise; | ||
852 | |||
853 | /* Convert the channel frequency and set the flags */ | ||
854 | put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); | ||
855 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) | ||
856 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
857 | IEEE80211_CHAN_5GHZ), | ||
858 | &iwl4965_rt->rt_chbitmask); | ||
859 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) | ||
860 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | | ||
861 | IEEE80211_CHAN_2GHZ), | ||
862 | &iwl4965_rt->rt_chbitmask); | ||
863 | else /* 802.11g */ | ||
864 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
865 | IEEE80211_CHAN_2GHZ), | ||
866 | &iwl4965_rt->rt_chbitmask); | ||
867 | |||
868 | if (rate == -1) | ||
869 | iwl4965_rt->rt_rate = 0; | ||
870 | else | ||
871 | iwl4965_rt->rt_rate = iwl_rates[rate].ieee; | ||
872 | |||
873 | /* | ||
874 | * "antenna number" | ||
875 | * | ||
876 | * It seems that the antenna field in the phy flags value | ||
877 | * is actually a bitfield. This is undefined by radiotap, | ||
878 | * it wants an actual antenna number but I always get "7" | ||
879 | * for most legacy frames I receive indicating that the | ||
880 | * same frame was received on all three RX chains. | ||
881 | * | ||
882 | * I think this field should be removed in favour of a | ||
883 | * new 802.11n radiotap field "RX chains" that is defined | ||
884 | * as a bitmask. | ||
885 | */ | ||
886 | antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; | ||
887 | iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4; | ||
888 | |||
889 | /* set the preamble flag if appropriate */ | ||
890 | if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
891 | iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
892 | |||
893 | stats->flag |= RX_FLAG_RADIOTAP; | ||
894 | } | ||
895 | |||
896 | static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | ||
897 | { | ||
898 | /* 0 - mgmt, 1 - cnt, 2 - data */ | ||
899 | int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; | ||
900 | priv->rx_stats[idx].cnt++; | ||
901 | priv->rx_stats[idx].bytes += len; | ||
902 | } | ||
903 | |||
904 | /* | ||
905 | * returns non-zero if packet should be dropped | ||
906 | */ | ||
907 | static int iwl_set_decrypted_flag(struct iwl_priv *priv, | ||
908 | struct ieee80211_hdr *hdr, | ||
909 | u32 decrypt_res, | ||
910 | struct ieee80211_rx_status *stats) | ||
911 | { | ||
912 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
913 | |||
914 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
915 | return 0; | ||
916 | |||
917 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
918 | return 0; | ||
919 | |||
920 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
921 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
922 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
923 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
924 | * Decryption will be done in SW. */ | ||
925 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
926 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
927 | break; | ||
928 | |||
929 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
930 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
931 | RX_RES_STATUS_BAD_ICV_MIC) { | ||
932 | /* bad ICV, the packet is destroyed since the | ||
933 | * decryption is inplace, drop it */ | ||
934 | IWL_DEBUG_RX("Packet destroyed\n"); | ||
935 | return -1; | ||
936 | } | ||
937 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
938 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
939 | RX_RES_STATUS_DECRYPT_OK) { | ||
940 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
941 | stats->flag |= RX_FLAG_DECRYPTED; | ||
942 | } | ||
943 | break; | ||
944 | |||
945 | default: | ||
946 | break; | ||
947 | } | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
952 | { | ||
953 | u32 decrypt_out = 0; | ||
954 | |||
955 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
956 | RX_RES_STATUS_STATION_FOUND) | ||
957 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
958 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
959 | |||
960 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
961 | |||
962 | /* packet was not encrypted */ | ||
963 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
964 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
965 | return decrypt_out; | ||
966 | |||
967 | /* packet was encrypted with unknown alg */ | ||
968 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
969 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
970 | return decrypt_out; | ||
971 | |||
972 | /* decryption was not done in HW */ | ||
973 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
974 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
975 | return decrypt_out; | ||
976 | |||
977 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
978 | |||
979 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
980 | /* alg is CCM: check MIC only */ | ||
981 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
982 | /* Bad MIC */ | ||
983 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
984 | else | ||
985 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
986 | |||
987 | break; | ||
988 | |||
989 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
990 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
991 | /* Bad TTAK */ | ||
992 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
993 | break; | ||
994 | } | ||
995 | /* fall through if TTAK OK */ | ||
996 | default: | ||
997 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
998 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
999 | else | ||
1000 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1001 | break; | ||
1002 | }; | ||
1003 | |||
1004 | IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
1005 | decrypt_in, decrypt_out); | ||
1006 | |||
1007 | return decrypt_out; | ||
1008 | } | ||
1009 | |||
1010 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
1011 | int include_phy, | ||
1012 | struct iwl_rx_mem_buffer *rxb, | ||
1013 | struct ieee80211_rx_status *stats) | ||
1014 | { | ||
1015 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1016 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
1017 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL; | ||
1018 | struct ieee80211_hdr *hdr; | ||
1019 | u16 len; | ||
1020 | __le32 *rx_end; | ||
1021 | unsigned int skblen; | ||
1022 | u32 ampdu_status; | ||
1023 | u32 ampdu_status_legacy; | ||
1024 | |||
1025 | if (!include_phy && priv->last_phy_res[0]) | ||
1026 | rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
1027 | |||
1028 | if (!rx_start) { | ||
1029 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
1030 | return; | ||
1031 | } | ||
1032 | if (include_phy) { | ||
1033 | hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] + | ||
1034 | rx_start->cfg_phy_cnt); | ||
1035 | |||
1036 | len = le16_to_cpu(rx_start->byte_count); | ||
1037 | |||
1038 | rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] + | ||
1039 | sizeof(struct iwl4965_rx_phy_res) + | ||
1040 | rx_start->cfg_phy_cnt + len); | ||
1041 | |||
1042 | } else { | ||
1043 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
1044 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1045 | |||
1046 | hdr = (struct ieee80211_hdr *)(pkt->u.raw + | ||
1047 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
1048 | len = le16_to_cpu(amsdu->byte_count); | ||
1049 | rx_start->byte_count = amsdu->byte_count; | ||
1050 | rx_end = (__le32 *) (((u8 *) hdr) + len); | ||
1051 | } | ||
1052 | |||
1053 | ampdu_status = le32_to_cpu(*rx_end); | ||
1054 | skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32); | ||
1055 | |||
1056 | if (!include_phy) { | ||
1057 | /* New status scheme, need to translate */ | ||
1058 | ampdu_status_legacy = ampdu_status; | ||
1059 | ampdu_status = iwl_translate_rx_status(priv, ampdu_status); | ||
1060 | } | ||
1061 | |||
1062 | /* start from MAC */ | ||
1063 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); | ||
1064 | skb_put(rxb->skb, len); /* end where data ends */ | ||
1065 | |||
1066 | /* We only process data packets if the interface is open */ | ||
1067 | if (unlikely(!priv->is_open)) { | ||
1068 | IWL_DEBUG_DROP_LIMIT | ||
1069 | ("Dropping packet while interface is not open.\n"); | ||
1070 | return; | ||
1071 | } | ||
1072 | |||
1073 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | ||
1074 | |||
1075 | /* in case of HW accelerated crypto and bad decryption, drop */ | ||
1076 | if (!priv->hw_params.sw_crypto && | ||
1077 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
1078 | return; | ||
1079 | |||
1080 | if (priv->add_radiotap) | ||
1081 | iwl_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); | ||
1082 | |||
1083 | iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); | ||
1084 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); | ||
1085 | priv->alloc_rxb_skb--; | ||
1086 | rxb->skb = NULL; | ||
1087 | } | ||
1088 | |||
1089 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
1090 | static int iwl_calc_rssi(struct iwl_priv *priv, | ||
1091 | struct iwl4965_rx_phy_res *rx_resp) | ||
1092 | { | ||
1093 | /* data from PHY/DSP regarding signal strength, etc., | ||
1094 | * contents are always there, not configurable by host. */ | ||
1095 | struct iwl4965_rx_non_cfg_phy *ncphy = | ||
1096 | (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy; | ||
1097 | u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK) | ||
1098 | >> IWL_AGC_DB_POS; | ||
1099 | |||
1100 | u32 valid_antennae = | ||
1101 | (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) | ||
1102 | >> RX_PHY_FLAGS_ANTENNAE_OFFSET; | ||
1103 | u8 max_rssi = 0; | ||
1104 | u32 i; | ||
1105 | |||
1106 | /* Find max rssi among 3 possible receivers. | ||
1107 | * These values are measured by the digital signal processor (DSP). | ||
1108 | * They should stay fairly constant even as the signal strength varies, | ||
1109 | * if the radio's automatic gain control (AGC) is working right. | ||
1110 | * AGC value (see below) will provide the "interesting" info. */ | ||
1111 | for (i = 0; i < 3; i++) | ||
1112 | if (valid_antennae & (1 << i)) | ||
1113 | max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); | ||
1114 | |||
1115 | IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
1116 | ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], | ||
1117 | max_rssi, agc); | ||
1118 | |||
1119 | /* dBm = max_rssi dB - agc dB - constant. | ||
1120 | * Higher AGC (higher radio gain) means lower signal. */ | ||
1121 | return max_rssi - agc - IWL_RSSI_OFFSET; | ||
1122 | } | ||
1123 | |||
1124 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||
1125 | { | ||
1126 | unsigned long flags; | ||
1127 | |||
1128 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1129 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | ||
1130 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | ||
1131 | priv->stations[sta_id].sta.sta.modify_mask = 0; | ||
1132 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1133 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1134 | |||
1135 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1136 | } | ||
1137 | |||
1138 | static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | ||
1139 | { | ||
1140 | /* FIXME: need locking over ps_status ??? */ | ||
1141 | u8 sta_id = iwl_find_station(priv, addr); | ||
1142 | |||
1143 | if (sta_id != IWL_INVALID_STATION) { | ||
1144 | u8 sta_awake = priv->stations[sta_id]. | ||
1145 | ps_status == STA_PS_STATUS_WAKE; | ||
1146 | |||
1147 | if (sta_awake && ps_bit) | ||
1148 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1149 | else if (!sta_awake && !ps_bit) { | ||
1150 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1151 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1152 | } | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | /* This is necessary only for a number of statistics, see the caller. */ | ||
1157 | static int iwl_is_network_packet(struct iwl_priv *priv, | ||
1158 | struct ieee80211_hdr *header) | ||
1159 | { | ||
1160 | /* Filter incoming packets to determine if they are targeted toward | ||
1161 | * this network, discarding packets coming from ourselves */ | ||
1162 | switch (priv->iw_mode) { | ||
1163 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | ||
1164 | /* packets to our IBSS update information */ | ||
1165 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
1166 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | ||
1167 | /* packets to our IBSS update information */ | ||
1168 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
1169 | default: | ||
1170 | return 1; | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1174 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1175 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1176 | void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
1177 | struct iwl_rx_mem_buffer *rxb) | ||
1178 | { | ||
1179 | struct ieee80211_hdr *header; | ||
1180 | struct ieee80211_rx_status rx_status; | ||
1181 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1182 | /* Use phy data (Rx signal strength, etc.) contained within | ||
1183 | * this rx packet for legacy frames, | ||
1184 | * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ | ||
1185 | int include_phy = (pkt->hdr.cmd == REPLY_RX); | ||
1186 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
1187 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : | ||
1188 | (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
1189 | __le32 *rx_end; | ||
1190 | unsigned int len = 0; | ||
1191 | u16 fc; | ||
1192 | u8 network_packet; | ||
1193 | |||
1194 | rx_status.mactime = le64_to_cpu(rx_start->timestamp); | ||
1195 | rx_status.freq = | ||
1196 | ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); | ||
1197 | rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1198 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1199 | rx_status.rate_idx = | ||
1200 | iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); | ||
1201 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
1202 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
1203 | |||
1204 | rx_status.antenna = 0; | ||
1205 | rx_status.flag = 0; | ||
1206 | rx_status.flag |= RX_FLAG_TSFT; | ||
1207 | |||
1208 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { | ||
1209 | IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", | ||
1210 | rx_start->cfg_phy_cnt); | ||
1211 | return; | ||
1212 | } | ||
1213 | |||
1214 | if (!include_phy) { | ||
1215 | if (priv->last_phy_res[0]) | ||
1216 | rx_start = (struct iwl4965_rx_phy_res *) | ||
1217 | &priv->last_phy_res[1]; | ||
1218 | else | ||
1219 | rx_start = NULL; | ||
1220 | } | ||
1221 | |||
1222 | if (!rx_start) { | ||
1223 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
1224 | return; | ||
1225 | } | ||
1226 | |||
1227 | if (include_phy) { | ||
1228 | header = (struct ieee80211_hdr *)((u8 *) &rx_start[1] | ||
1229 | + rx_start->cfg_phy_cnt); | ||
1230 | |||
1231 | len = le16_to_cpu(rx_start->byte_count); | ||
1232 | rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + | ||
1233 | sizeof(struct iwl4965_rx_phy_res) + len); | ||
1234 | } else { | ||
1235 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
1236 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1237 | |||
1238 | header = (void *)(pkt->u.raw + | ||
1239 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
1240 | len = le16_to_cpu(amsdu->byte_count); | ||
1241 | rx_end = (__le32 *) (pkt->u.raw + | ||
1242 | sizeof(struct iwl4965_rx_mpdu_res_start) + len); | ||
1243 | } | ||
1244 | |||
1245 | if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1246 | !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1247 | IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n", | ||
1248 | le32_to_cpu(*rx_end)); | ||
1249 | return; | ||
1250 | } | ||
1251 | |||
1252 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); | ||
1253 | |||
1254 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1255 | rx_status.signal = iwl_calc_rssi(priv, rx_start); | ||
1256 | |||
1257 | /* Meaningful noise values are available only from beacon statistics, | ||
1258 | * which are gathered only when associated, and indicate noise | ||
1259 | * only for the associated network channel ... | ||
1260 | * Ignore these noise values while scanning (other channels) */ | ||
1261 | if (iwl_is_associated(priv) && | ||
1262 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
1263 | rx_status.noise = priv->last_rx_noise; | ||
1264 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, | ||
1265 | rx_status.noise); | ||
1266 | } else { | ||
1267 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1268 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); | ||
1269 | } | ||
1270 | |||
1271 | /* Reset beacon noise level if not associated. */ | ||
1272 | if (!iwl_is_associated(priv)) | ||
1273 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1274 | |||
1275 | /* Set "1" to report good data frames in groups of 100 */ | ||
1276 | /* FIXME: need to optimze the call: */ | ||
1277 | iwl_dbg_report_frame(priv, pkt, header, 1); | ||
1278 | |||
1279 | IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", | ||
1280 | rx_status.signal, rx_status.noise, rx_status.signal, | ||
1281 | (unsigned long long)rx_status.mactime); | ||
1282 | |||
1283 | /* Take shortcut when only in monitor mode */ | ||
1284 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | ||
1285 | iwl_pass_packet_to_mac80211(priv, include_phy, | ||
1286 | rxb, &rx_status); | ||
1287 | return; | ||
1288 | } | ||
1289 | |||
1290 | network_packet = iwl_is_network_packet(priv, header); | ||
1291 | if (network_packet) { | ||
1292 | priv->last_rx_rssi = rx_status.signal; | ||
1293 | priv->last_beacon_time = priv->ucode_beacon_time; | ||
1294 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); | ||
1295 | } | ||
1296 | |||
1297 | fc = le16_to_cpu(header->frame_control); | ||
1298 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
1299 | case IEEE80211_FTYPE_MGMT: | ||
1300 | case IEEE80211_FTYPE_DATA: | ||
1301 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
1302 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
1303 | header->addr2); | ||
1304 | /* fall through */ | ||
1305 | default: | ||
1306 | iwl_pass_packet_to_mac80211(priv, include_phy, rxb, | ||
1307 | &rx_status); | ||
1308 | break; | ||
1309 | |||
1310 | } | ||
1311 | } | ||
1312 | EXPORT_SYMBOL(iwl_rx_reply_rx); | ||
1313 | |||
1314 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1315 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1316 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1317 | struct iwl_rx_mem_buffer *rxb) | ||
1318 | { | ||
1319 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1320 | priv->last_phy_res[0] = 1; | ||
1321 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1322 | sizeof(struct iwl4965_rx_phy_res)); | ||
1323 | } | ||
1324 | EXPORT_SYMBOL(iwl_rx_reply_rx_phy); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index f874e7d7b225..6d1467d0bd9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -36,8 +36,8 @@ | |||
36 | #include "iwl-helpers.h" | 36 | #include "iwl-helpers.h" |
37 | 37 | ||
38 | 38 | ||
39 | #define IWL_STA_DRIVER_ACTIVE 0x1 /* ucode entry is active */ | 39 | #define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ |
40 | #define IWL_STA_UCODE_ACTIVE 0x2 /* ucode entry is active */ | 40 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ |
41 | 41 | ||
42 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | 42 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) |
43 | { | 43 | { |
@@ -83,10 +83,28 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | 84 | EXPORT_SYMBOL(iwl_get_ra_sta_id); |
85 | 85 | ||
86 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | ||
87 | { | ||
88 | unsigned long flags; | ||
89 | DECLARE_MAC_BUF(mac); | ||
90 | |||
91 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
92 | |||
93 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) | ||
94 | IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id); | ||
95 | |||
96 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
97 | IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n", | ||
98 | print_mac(mac, priv->stations[sta_id].sta.sta.addr)); | ||
99 | |||
100 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
101 | } | ||
102 | |||
86 | static int iwl_add_sta_callback(struct iwl_priv *priv, | 103 | static int iwl_add_sta_callback(struct iwl_priv *priv, |
87 | struct iwl_cmd *cmd, struct sk_buff *skb) | 104 | struct iwl_cmd *cmd, struct sk_buff *skb) |
88 | { | 105 | { |
89 | struct iwl_rx_packet *res = NULL; | 106 | struct iwl_rx_packet *res = NULL; |
107 | u8 sta_id = cmd->cmd.addsta.sta.sta_id; | ||
90 | 108 | ||
91 | if (!skb) { | 109 | if (!skb) { |
92 | IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n"); | 110 | IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n"); |
@@ -102,8 +120,8 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, | |||
102 | 120 | ||
103 | switch (res->u.add_sta.status) { | 121 | switch (res->u.add_sta.status) { |
104 | case ADD_STA_SUCCESS_MSK: | 122 | case ADD_STA_SUCCESS_MSK: |
105 | /* FIXME: implement iwl_sta_ucode_activate(priv, addr); */ | 123 | iwl_sta_ucode_activate(priv, sta_id); |
106 | /* fail through */ | 124 | /* fall through */ |
107 | default: | 125 | default: |
108 | IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n", | 126 | IWL_DEBUG_HC("Received REPLY_ADD_STA:(0x%08X)\n", |
109 | res->u.add_sta.status); | 127 | res->u.add_sta.status); |
@@ -147,6 +165,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
147 | if (ret == 0) { | 165 | if (ret == 0) { |
148 | switch (res->u.add_sta.status) { | 166 | switch (res->u.add_sta.status) { |
149 | case ADD_STA_SUCCESS_MSK: | 167 | case ADD_STA_SUCCESS_MSK: |
168 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); | ||
150 | IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n"); | 169 | IWL_DEBUG_INFO("REPLY_ADD_STA PASSED\n"); |
151 | break; | 170 | break; |
152 | default: | 171 | default: |
@@ -215,88 +234,92 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, | |||
215 | u8 flags, struct ieee80211_ht_info *ht_info) | 234 | u8 flags, struct ieee80211_ht_info *ht_info) |
216 | { | 235 | { |
217 | int i; | 236 | int i; |
218 | int index = IWL_INVALID_STATION; | 237 | int sta_id = IWL_INVALID_STATION; |
219 | struct iwl_station_entry *station; | 238 | struct iwl_station_entry *station; |
220 | unsigned long flags_spin; | 239 | unsigned long flags_spin; |
221 | DECLARE_MAC_BUF(mac); | 240 | DECLARE_MAC_BUF(mac); |
222 | 241 | ||
223 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 242 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
224 | if (is_ap) | 243 | if (is_ap) |
225 | index = IWL_AP_ID; | 244 | sta_id = IWL_AP_ID; |
226 | else if (is_broadcast_ether_addr(addr)) | 245 | else if (is_broadcast_ether_addr(addr)) |
227 | index = priv->hw_params.bcast_sta_id; | 246 | sta_id = priv->hw_params.bcast_sta_id; |
228 | else | 247 | else |
229 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { | 248 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { |
230 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, | 249 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, |
231 | addr)) { | 250 | addr)) { |
232 | index = i; | 251 | sta_id = i; |
233 | break; | 252 | break; |
234 | } | 253 | } |
235 | 254 | ||
236 | if (!priv->stations[i].used && | 255 | if (!priv->stations[i].used && |
237 | index == IWL_INVALID_STATION) | 256 | sta_id == IWL_INVALID_STATION) |
238 | index = i; | 257 | sta_id = i; |
239 | } | 258 | } |
240 | 259 | ||
241 | |||
242 | /* These two conditions have the same outcome, but keep them separate | 260 | /* These two conditions have the same outcome, but keep them separate |
243 | since they have different meanings */ | 261 | since they have different meanings */ |
244 | if (unlikely(index == IWL_INVALID_STATION)) { | 262 | if (unlikely(sta_id == IWL_INVALID_STATION)) { |
245 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 263 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
246 | return index; | 264 | return sta_id; |
247 | } | 265 | } |
248 | 266 | ||
249 | if (priv->stations[index].used && | 267 | if (priv->stations[sta_id].used && |
250 | !compare_ether_addr(priv->stations[index].sta.sta.addr, addr)) { | 268 | !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { |
251 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 269 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
252 | return index; | 270 | return sta_id; |
253 | } | 271 | } |
254 | 272 | ||
255 | 273 | ||
256 | IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr)); | 274 | station = &priv->stations[sta_id]; |
257 | station = &priv->stations[index]; | 275 | station->used = IWL_STA_DRIVER_ACTIVE; |
258 | station->used = 1; | 276 | IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n", |
277 | sta_id, print_mac(mac, addr)); | ||
259 | priv->num_stations++; | 278 | priv->num_stations++; |
260 | 279 | ||
261 | /* Set up the REPLY_ADD_STA command to send to device */ | 280 | /* Set up the REPLY_ADD_STA command to send to device */ |
262 | memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd)); | 281 | memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd)); |
263 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); | 282 | memcpy(station->sta.sta.addr, addr, ETH_ALEN); |
264 | station->sta.mode = 0; | 283 | station->sta.mode = 0; |
265 | station->sta.sta.sta_id = index; | 284 | station->sta.sta.sta_id = sta_id; |
266 | station->sta.station_flags = 0; | 285 | station->sta.station_flags = 0; |
267 | 286 | ||
268 | /* BCAST station and IBSS stations do not work in HT mode */ | 287 | /* BCAST station and IBSS stations do not work in HT mode */ |
269 | if (index != priv->hw_params.bcast_sta_id && | 288 | if (sta_id != priv->hw_params.bcast_sta_id && |
270 | priv->iw_mode != IEEE80211_IF_TYPE_IBSS) | 289 | priv->iw_mode != IEEE80211_IF_TYPE_IBSS) |
271 | iwl_set_ht_add_station(priv, index, ht_info); | 290 | iwl_set_ht_add_station(priv, sta_id, ht_info); |
272 | 291 | ||
273 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 292 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
274 | 293 | ||
275 | /* Add station to device's station table */ | 294 | /* Add station to device's station table */ |
276 | iwl_send_add_sta(priv, &station->sta, flags); | 295 | iwl_send_add_sta(priv, &station->sta, flags); |
277 | return index; | 296 | return sta_id; |
278 | 297 | ||
279 | } | 298 | } |
280 | EXPORT_SYMBOL(iwl_add_station_flags); | 299 | EXPORT_SYMBOL(iwl_add_station_flags); |
281 | 300 | ||
282 | static int iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | 301 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) |
283 | { | 302 | { |
284 | unsigned long flags; | 303 | unsigned long flags; |
285 | u8 sta_id; | ||
286 | DECLARE_MAC_BUF(mac); | 304 | DECLARE_MAC_BUF(mac); |
287 | 305 | ||
288 | sta_id = iwl_find_station(priv, addr); | 306 | u8 sta_id = iwl_find_station(priv, addr); |
289 | if (sta_id != IWL_INVALID_STATION) { | 307 | |
290 | IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n", | 308 | BUG_ON(sta_id == IWL_INVALID_STATION); |
291 | print_mac(mac, addr)); | 309 | |
292 | spin_lock_irqsave(&priv->sta_lock, flags); | 310 | IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n", |
293 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | 311 | print_mac(mac, addr)); |
294 | memset(&priv->stations[sta_id], 0, | 312 | |
295 | sizeof(struct iwl_station_entry)); | 313 | spin_lock_irqsave(&priv->sta_lock, flags); |
296 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 314 | |
297 | return 0; | 315 | /* Ucode must be active and driver must be non active */ |
298 | } | 316 | if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) |
299 | return -EINVAL; | 317 | IWL_ERROR("removed non active STA %d\n", sta_id); |
318 | |||
319 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | ||
320 | |||
321 | memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); | ||
322 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
300 | } | 323 | } |
301 | 324 | ||
302 | static int iwl_remove_sta_callback(struct iwl_priv *priv, | 325 | static int iwl_remove_sta_callback(struct iwl_priv *priv, |
@@ -322,6 +345,7 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv, | |||
322 | iwl_sta_ucode_deactivate(priv, addr); | 345 | iwl_sta_ucode_deactivate(priv, addr); |
323 | break; | 346 | break; |
324 | default: | 347 | default: |
348 | IWL_ERROR("REPLY_REMOVE_STA failed\n"); | ||
325 | break; | 349 | break; |
326 | } | 350 | } |
327 | 351 | ||
@@ -386,44 +410,63 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
386 | /** | 410 | /** |
387 | * iwl_remove_station - Remove driver's knowledge of station. | 411 | * iwl_remove_station - Remove driver's knowledge of station. |
388 | */ | 412 | */ |
389 | u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) | 413 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) |
390 | { | 414 | { |
391 | int index = IWL_INVALID_STATION; | 415 | int sta_id = IWL_INVALID_STATION; |
392 | int i; | 416 | int i, ret = -EINVAL; |
393 | unsigned long flags; | 417 | unsigned long flags; |
418 | DECLARE_MAC_BUF(mac); | ||
394 | 419 | ||
395 | spin_lock_irqsave(&priv->sta_lock, flags); | 420 | spin_lock_irqsave(&priv->sta_lock, flags); |
396 | 421 | ||
397 | if (is_ap) | 422 | if (is_ap) |
398 | index = IWL_AP_ID; | 423 | sta_id = IWL_AP_ID; |
399 | else if (is_broadcast_ether_addr(addr)) | 424 | else if (is_broadcast_ether_addr(addr)) |
400 | index = priv->hw_params.bcast_sta_id; | 425 | sta_id = priv->hw_params.bcast_sta_id; |
401 | else | 426 | else |
402 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) | 427 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) |
403 | if (priv->stations[i].used && | 428 | if (priv->stations[i].used && |
404 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | 429 | !compare_ether_addr(priv->stations[i].sta.sta.addr, |
405 | addr)) { | 430 | addr)) { |
406 | index = i; | 431 | sta_id = i; |
407 | break; | 432 | break; |
408 | } | 433 | } |
409 | 434 | ||
410 | if (unlikely(index == IWL_INVALID_STATION)) | 435 | if (unlikely(sta_id == IWL_INVALID_STATION)) |
411 | goto out; | 436 | goto out; |
412 | 437 | ||
413 | if (priv->stations[index].used) { | 438 | IWL_DEBUG_ASSOC("Removing STA from driver:%d %s\n", |
414 | priv->stations[index].used = 0; | 439 | sta_id, print_mac(mac, addr)); |
415 | priv->num_stations--; | 440 | |
441 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | ||
442 | IWL_ERROR("Removing %s but non DRIVER active\n", | ||
443 | print_mac(mac, addr)); | ||
444 | goto out; | ||
445 | } | ||
446 | |||
447 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | ||
448 | IWL_ERROR("Removing %s but non UCODE active\n", | ||
449 | print_mac(mac, addr)); | ||
450 | goto out; | ||
416 | } | 451 | } |
417 | 452 | ||
453 | |||
454 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | ||
455 | |||
456 | priv->num_stations--; | ||
457 | |||
418 | BUG_ON(priv->num_stations < 0); | 458 | BUG_ON(priv->num_stations < 0); |
459 | |||
419 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 460 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
420 | iwl_send_remove_station(priv, addr, CMD_ASYNC); | 461 | |
421 | return index; | 462 | ret = iwl_send_remove_station(priv, addr, CMD_ASYNC); |
463 | return ret; | ||
422 | out: | 464 | out: |
423 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 465 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
424 | return 0; | 466 | return ret; |
425 | } | 467 | } |
426 | EXPORT_SYMBOL(iwl_remove_station); | 468 | EXPORT_SYMBOL(iwl_remove_station); |
469 | |||
427 | static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | 470 | static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) |
428 | { | 471 | { |
429 | int i; | 472 | int i; |
@@ -782,8 +825,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
782 | 825 | ||
783 | iwl_dump_lq_cmd(priv,lq); | 826 | iwl_dump_lq_cmd(priv,lq); |
784 | 827 | ||
785 | if (iwl_is_associated(priv) && priv->assoc_station_added && | 828 | if (iwl_is_associated(priv) && priv->assoc_station_added) |
786 | priv->lq_mngr.lq_ready) | ||
787 | return iwl_send_cmd(priv, &cmd); | 829 | return iwl_send_cmd(priv, &cmd); |
788 | 830 | ||
789 | return 0; | 831 | return 0; |
@@ -845,6 +887,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap) | |||
845 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | 887 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, |
846 | sizeof(link_cmd), &link_cmd, NULL); | 888 | sizeof(link_cmd), &link_cmd, NULL); |
847 | } | 889 | } |
890 | |||
848 | /** | 891 | /** |
849 | * iwl_rxon_add_station - add station into station table. | 892 | * iwl_rxon_add_station - add station into station table. |
850 | * | 893 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index b6bb209fdd58..221b93e670a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -48,7 +48,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
49 | struct ieee80211_key_conf *key, u8 sta_id); | 49 | struct ieee80211_key_conf *key, u8 sta_id); |
50 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); | 50 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); |
51 | u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); | 51 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); |
52 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 52 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
53 | void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid); | 53 | void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid); |
54 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 54 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7296e2846ec3..032641d4c7d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -1350,6 +1350,149 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | |||
1350 | } | 1350 | } |
1351 | EXPORT_SYMBOL(iwl_txq_check_empty); | 1351 | EXPORT_SYMBOL(iwl_txq_check_empty); |
1352 | 1352 | ||
1353 | /** | ||
1354 | * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1355 | * | ||
1356 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1357 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1358 | */ | ||
1359 | static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1360 | struct iwl_ht_agg *agg, | ||
1361 | struct iwl_compressed_ba_resp *ba_resp) | ||
1362 | |||
1363 | { | ||
1364 | int i, sh, ack; | ||
1365 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1366 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1367 | u64 bitmap; | ||
1368 | int successes = 0; | ||
1369 | struct ieee80211_tx_info *info; | ||
1370 | |||
1371 | if (unlikely(!agg->wait_for_ba)) { | ||
1372 | IWL_ERROR("Received BA when not expected\n"); | ||
1373 | return -EINVAL; | ||
1374 | } | ||
1375 | |||
1376 | /* Mark that the expected block-ack response arrived */ | ||
1377 | agg->wait_for_ba = 0; | ||
1378 | IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1379 | |||
1380 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1381 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4); | ||
1382 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1383 | sh += 0x100; | ||
1384 | |||
1385 | /* don't use 64-bit values for now */ | ||
1386 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1387 | |||
1388 | if (agg->frame_count > (64 - sh)) { | ||
1389 | IWL_DEBUG_TX_REPLY("more frames than bitmap size"); | ||
1390 | return -1; | ||
1391 | } | ||
1392 | |||
1393 | /* check for success or failure according to the | ||
1394 | * transmitted bitmap and block-ack bitmap */ | ||
1395 | bitmap &= agg->bitmap; | ||
1396 | |||
1397 | /* For each frame attempted in aggregation, | ||
1398 | * update driver's record of tx frame's status. */ | ||
1399 | for (i = 0; i < agg->frame_count ; i++) { | ||
1400 | ack = bitmap & (1 << i); | ||
1401 | successes += !!ack; | ||
1402 | IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", | ||
1403 | ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, | ||
1404 | agg->start_idx + i); | ||
1405 | } | ||
1406 | |||
1407 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1408 | memset(&info->status, 0, sizeof(info->status)); | ||
1409 | info->flags = IEEE80211_TX_STAT_ACK; | ||
1410 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1411 | info->status.ampdu_ack_map = successes; | ||
1412 | info->status.ampdu_ack_len = agg->frame_count; | ||
1413 | iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1414 | |||
1415 | IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | /** | ||
1421 | * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1422 | * | ||
1423 | * Handles block-acknowledge notification from device, which reports success | ||
1424 | * of frames sent via aggregation. | ||
1425 | */ | ||
1426 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1427 | struct iwl_rx_mem_buffer *rxb) | ||
1428 | { | ||
1429 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1430 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1431 | int index; | ||
1432 | struct iwl_tx_queue *txq = NULL; | ||
1433 | struct iwl_ht_agg *agg; | ||
1434 | DECLARE_MAC_BUF(mac); | ||
1435 | |||
1436 | /* "flow" corresponds to Tx queue */ | ||
1437 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1438 | |||
1439 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1440 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1441 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1442 | |||
1443 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1444 | IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); | ||
1445 | return; | ||
1446 | } | ||
1447 | |||
1448 | txq = &priv->txq[scd_flow]; | ||
1449 | agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; | ||
1450 | |||
1451 | /* Find index just before block-ack window */ | ||
1452 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1453 | |||
1454 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1455 | |||
1456 | IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, " | ||
1457 | "sta_id = %d\n", | ||
1458 | agg->wait_for_ba, | ||
1459 | print_mac(mac, (u8 *) &ba_resp->sta_addr_lo32), | ||
1460 | ba_resp->sta_id); | ||
1461 | IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1462 | "%d, scd_ssn = %d\n", | ||
1463 | ba_resp->tid, | ||
1464 | ba_resp->seq_ctl, | ||
1465 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1466 | ba_resp->scd_flow, | ||
1467 | ba_resp->scd_ssn); | ||
1468 | IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", | ||
1469 | agg->start_idx, | ||
1470 | (unsigned long long)agg->bitmap); | ||
1471 | |||
1472 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1473 | iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1474 | |||
1475 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1476 | * block-ack window (we assume that they've been successfully | ||
1477 | * transmitted ... if not, it's too late anyway). */ | ||
1478 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1479 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1480 | int ampdu_q = | ||
1481 | scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues; | ||
1482 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | ||
1483 | priv->stations[ba_resp->sta_id]. | ||
1484 | tid[ba_resp->tid].tfds_in_queue -= freed; | ||
1485 | if (iwl_queue_space(&txq->q) > txq->q.low_mark && | ||
1486 | priv->mac80211_registered && | ||
1487 | agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) | ||
1488 | ieee80211_wake_queue(priv->hw, ampdu_q); | ||
1489 | |||
1490 | iwl_txq_check_empty(priv, ba_resp->sta_id, | ||
1491 | ba_resp->tid, scd_flow); | ||
1492 | } | ||
1493 | } | ||
1494 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); | ||
1495 | |||
1353 | #ifdef CONFIG_IWLWIF_DEBUG | 1496 | #ifdef CONFIG_IWLWIF_DEBUG |
1354 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 1497 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x |
1355 | 1498 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 92d1b2e312d4..3bc2644039f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -970,7 +970,7 @@ static int iwl3945_full_rxon_required(struct iwl3945_priv *priv) | |||
970 | { | 970 | { |
971 | 971 | ||
972 | /* These items are only settable from the full RXON command */ | 972 | /* These items are only settable from the full RXON command */ |
973 | if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) || | 973 | if (!(iwl3945_is_associated(priv)) || |
974 | compare_ether_addr(priv->staging_rxon.bssid_addr, | 974 | compare_ether_addr(priv->staging_rxon.bssid_addr, |
975 | priv->active_rxon.bssid_addr) || | 975 | priv->active_rxon.bssid_addr) || |
976 | compare_ether_addr(priv->staging_rxon.node_addr, | 976 | compare_ether_addr(priv->staging_rxon.node_addr, |
@@ -2312,7 +2312,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) | |||
2312 | #endif | 2312 | #endif |
2313 | 2313 | ||
2314 | ch_info = iwl3945_get_channel_info(priv, priv->band, | 2314 | ch_info = iwl3945_get_channel_info(priv, priv->band, |
2315 | le16_to_cpu(priv->staging_rxon.channel)); | 2315 | le16_to_cpu(priv->active_rxon.channel)); |
2316 | 2316 | ||
2317 | if (!ch_info) | 2317 | if (!ch_info) |
2318 | ch_info = &priv->channel_info[0]; | 2318 | ch_info = &priv->channel_info[0]; |
@@ -2539,6 +2539,11 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h | |||
2539 | iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | 2539 | iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); |
2540 | return priv->hw_setting.bcast_sta_id; | 2540 | return priv->hw_setting.bcast_sta_id; |
2541 | } | 2541 | } |
2542 | /* If we are in monitor mode, use BCAST. This is required for | ||
2543 | * packet injection. */ | ||
2544 | case IEEE80211_IF_TYPE_MNTR: | ||
2545 | return priv->hw_setting.bcast_sta_id; | ||
2546 | |||
2542 | default: | 2547 | default: |
2543 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); | 2548 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); |
2544 | return priv->hw_setting.bcast_sta_id; | 2549 | return priv->hw_setting.bcast_sta_id; |
@@ -2578,11 +2583,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) | |||
2578 | goto drop_unlock; | 2583 | goto drop_unlock; |
2579 | } | 2584 | } |
2580 | 2585 | ||
2581 | if (!priv->vif) { | ||
2582 | IWL_DEBUG_DROP("Dropping - !priv->vif\n"); | ||
2583 | goto drop_unlock; | ||
2584 | } | ||
2585 | |||
2586 | if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { | 2586 | if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { |
2587 | IWL_ERROR("ERROR: No TX rate available.\n"); | 2587 | IWL_ERROR("ERROR: No TX rate available.\n"); |
2588 | goto drop_unlock; | 2588 | goto drop_unlock; |
@@ -2603,9 +2603,10 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) | |||
2603 | #endif | 2603 | #endif |
2604 | 2604 | ||
2605 | /* drop all data frame if we are not associated */ | 2605 | /* drop all data frame if we are not associated */ |
2606 | if ((!iwl3945_is_associated(priv) || | 2606 | if (ieee80211_is_data(fc) && |
2607 | ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && | 2607 | (priv->iw_mode != IEEE80211_IF_TYPE_MNTR) && /* packet injection */ |
2608 | ieee80211_is_data(fc)) { | 2608 | (!iwl3945_is_associated(priv) || |
2609 | ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id))) { | ||
2609 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); | 2610 | IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); |
2610 | goto drop_unlock; | 2611 | goto drop_unlock; |
2611 | } | 2612 | } |
@@ -5921,7 +5922,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5921 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | 5922 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |
5922 | STATUS_GEO_CONFIGURED | | 5923 | STATUS_GEO_CONFIGURED | |
5923 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5924 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5924 | STATUS_IN_SUSPEND; | 5925 | STATUS_IN_SUSPEND | |
5926 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5927 | STATUS_EXIT_PENDING; | ||
5925 | goto exit; | 5928 | goto exit; |
5926 | } | 5929 | } |
5927 | 5930 | ||
@@ -5936,7 +5939,9 @@ static void __iwl3945_down(struct iwl3945_priv *priv) | |||
5936 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 5939 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
5937 | STATUS_IN_SUSPEND | | 5940 | STATUS_IN_SUSPEND | |
5938 | test_bit(STATUS_FW_ERROR, &priv->status) << | 5941 | test_bit(STATUS_FW_ERROR, &priv->status) << |
5939 | STATUS_FW_ERROR; | 5942 | STATUS_FW_ERROR | |
5943 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
5944 | STATUS_EXIT_PENDING; | ||
5940 | 5945 | ||
5941 | spin_lock_irqsave(&priv->lock, flags); | 5946 | spin_lock_irqsave(&priv->lock, flags); |
5942 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 5947 | iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
@@ -6008,11 +6013,12 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6008 | else { | 6013 | else { |
6009 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 6014 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
6010 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 6015 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { |
6016 | iwl3945_rfkill_set_hw_state(priv); | ||
6011 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 6017 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); |
6012 | return -ENODEV; | 6018 | return -ENODEV; |
6013 | } | 6019 | } |
6014 | } | 6020 | } |
6015 | 6021 | iwl3945_rfkill_set_hw_state(priv); | |
6016 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); | 6022 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); |
6017 | 6023 | ||
6018 | rc = iwl3945_hw_nic_init(priv); | 6024 | rc = iwl3945_hw_nic_init(priv); |
@@ -6068,6 +6074,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6068 | 6074 | ||
6069 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 6075 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
6070 | __iwl3945_down(priv); | 6076 | __iwl3945_down(priv); |
6077 | clear_bit(STATUS_EXIT_PENDING, &priv->status); | ||
6071 | 6078 | ||
6072 | /* tried to restart and config the device for as long as our | 6079 | /* tried to restart and config the device for as long as our |
6073 | * patience could withstand */ | 6080 | * patience could withstand */ |
@@ -6135,6 +6142,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
6135 | "Kill switch must be turned off for " | 6142 | "Kill switch must be turned off for " |
6136 | "wireless networking to work.\n"); | 6143 | "wireless networking to work.\n"); |
6137 | } | 6144 | } |
6145 | |||
6146 | iwl3945_rfkill_set_hw_state(priv); | ||
6138 | mutex_unlock(&priv->mutex); | 6147 | mutex_unlock(&priv->mutex); |
6139 | } | 6148 | } |
6140 | 6149 | ||
@@ -6685,11 +6694,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
6685 | 6694 | ||
6686 | IWL_DEBUG_MAC80211("enter\n"); | 6695 | IWL_DEBUG_MAC80211("enter\n"); |
6687 | 6696 | ||
6688 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | ||
6689 | IWL_DEBUG_MAC80211("leave - monitor\n"); | ||
6690 | return -1; | ||
6691 | } | ||
6692 | |||
6693 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 6697 | IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
6694 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | 6698 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); |
6695 | 6699 | ||
@@ -6836,7 +6840,7 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
6836 | return; | 6840 | return; |
6837 | 6841 | ||
6838 | /* The following should be done only at AP bring up */ | 6842 | /* The following should be done only at AP bring up */ |
6839 | if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) { | 6843 | if (!(iwl3945_is_associated(priv))) { |
6840 | 6844 | ||
6841 | /* RXON - unassoc (to set timing command) */ | 6845 | /* RXON - unassoc (to set timing command) */ |
6842 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 6846 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
@@ -6998,26 +7002,18 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, | |||
6998 | unsigned int *total_flags, | 7002 | unsigned int *total_flags, |
6999 | int mc_count, struct dev_addr_list *mc_list) | 7003 | int mc_count, struct dev_addr_list *mc_list) |
7000 | { | 7004 | { |
7001 | /* | ||
7002 | * XXX: dummy | ||
7003 | * see also iwl3945_connection_init_rx_config | ||
7004 | */ | ||
7005 | struct iwl3945_priv *priv = hw->priv; | 7005 | struct iwl3945_priv *priv = hw->priv; |
7006 | int new_flags = 0; | 7006 | |
7007 | if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | 7007 | if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { |
7008 | if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | 7008 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", |
7009 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", | 7009 | IEEE80211_IF_TYPE_MNTR, |
7010 | IEEE80211_IF_TYPE_MNTR, | 7010 | changed_flags, *total_flags); |
7011 | changed_flags, *total_flags); | 7011 | /* queue work 'cuz mac80211 is holding a lock which |
7012 | /* queue work 'cuz mac80211 is holding a lock which | 7012 | * prevents us from issuing (synchronous) f/w cmds */ |
7013 | * prevents us from issuing (synchronous) f/w cmds */ | 7013 | queue_work(priv->workqueue, &priv->set_monitor); |
7014 | queue_work(priv->workqueue, &priv->set_monitor); | ||
7015 | new_flags &= FIF_PROMISC_IN_BSS | | ||
7016 | FIF_OTHER_BSS | | ||
7017 | FIF_ALLMULTI; | ||
7018 | } | ||
7019 | } | 7014 | } |
7020 | *total_flags = new_flags; | 7015 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | |
7016 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
7021 | } | 7017 | } |
7022 | 7018 | ||
7023 | static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, | 7019 | static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw, |
@@ -7412,37 +7408,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, | |||
7412 | 7408 | ||
7413 | #endif /* CONFIG_IWL3945_DEBUG */ | 7409 | #endif /* CONFIG_IWL3945_DEBUG */ |
7414 | 7410 | ||
7415 | static ssize_t show_rf_kill(struct device *d, | ||
7416 | struct device_attribute *attr, char *buf) | ||
7417 | { | ||
7418 | /* | ||
7419 | * 0 - RF kill not enabled | ||
7420 | * 1 - SW based RF kill active (sysfs) | ||
7421 | * 2 - HW based RF kill active | ||
7422 | * 3 - Both HW and SW based RF kill active | ||
7423 | */ | ||
7424 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7425 | int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | | ||
7426 | (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); | ||
7427 | |||
7428 | return sprintf(buf, "%i\n", val); | ||
7429 | } | ||
7430 | |||
7431 | static ssize_t store_rf_kill(struct device *d, | ||
7432 | struct device_attribute *attr, | ||
7433 | const char *buf, size_t count) | ||
7434 | { | ||
7435 | struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; | ||
7436 | |||
7437 | mutex_lock(&priv->mutex); | ||
7438 | iwl3945_radio_kill_sw(priv, buf[0] == '1'); | ||
7439 | mutex_unlock(&priv->mutex); | ||
7440 | |||
7441 | return count; | ||
7442 | } | ||
7443 | |||
7444 | static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); | ||
7445 | |||
7446 | static ssize_t show_temperature(struct device *d, | 7411 | static ssize_t show_temperature(struct device *d, |
7447 | struct device_attribute *attr, char *buf) | 7412 | struct device_attribute *attr, char *buf) |
7448 | { | 7413 | { |
@@ -7928,7 +7893,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { | |||
7928 | #endif | 7893 | #endif |
7929 | &dev_attr_power_level.attr, | 7894 | &dev_attr_power_level.attr, |
7930 | &dev_attr_retry_rate.attr, | 7895 | &dev_attr_retry_rate.attr, |
7931 | &dev_attr_rf_kill.attr, | ||
7932 | &dev_attr_rs_window.attr, | 7896 | &dev_attr_rs_window.attr, |
7933 | &dev_attr_statistics.attr, | 7897 | &dev_attr_statistics.attr, |
7934 | &dev_attr_status.attr, | 7898 | &dev_attr_status.attr, |
@@ -8169,6 +8133,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8169 | pci_save_state(pdev); | 8133 | pci_save_state(pdev); |
8170 | pci_disable_device(pdev); | 8134 | pci_disable_device(pdev); |
8171 | 8135 | ||
8136 | err = iwl3945_rfkill_init(priv); | ||
8137 | if (err) | ||
8138 | IWL_ERROR("Unable to initialize RFKILL system. " | ||
8139 | "Ignoring error: %d\n", err); | ||
8140 | |||
8172 | return 0; | 8141 | return 0; |
8173 | 8142 | ||
8174 | out_free_geos: | 8143 | out_free_geos: |
@@ -8231,6 +8200,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
8231 | 8200 | ||
8232 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 8201 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
8233 | 8202 | ||
8203 | iwl3945_rfkill_unregister(priv); | ||
8234 | iwl3945_dealloc_ucode_pci(priv); | 8204 | iwl3945_dealloc_ucode_pci(priv); |
8235 | 8205 | ||
8236 | if (priv->rxq.bd) | 8206 | if (priv->rxq.bd) |
@@ -8299,6 +8269,143 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
8299 | 8269 | ||
8300 | #endif /* CONFIG_PM */ | 8270 | #endif /* CONFIG_PM */ |
8301 | 8271 | ||
8272 | /*************** RFKILL FUNCTIONS **********/ | ||
8273 | #ifdef CONFIG_IWLWIFI_RFKILL | ||
8274 | /* software rf-kill from user */ | ||
8275 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | ||
8276 | { | ||
8277 | struct iwl3945_priv *priv = data; | ||
8278 | int err = 0; | ||
8279 | |||
8280 | if (!priv->rfkill_mngr.rfkill) | ||
8281 | return 0; | ||
8282 | |||
8283 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
8284 | return 0; | ||
8285 | |||
8286 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | ||
8287 | mutex_lock(&priv->mutex); | ||
8288 | |||
8289 | switch (state) { | ||
8290 | case RFKILL_STATE_UNBLOCKED: | ||
8291 | iwl3945_radio_kill_sw(priv, 0); | ||
8292 | /* if HW rf-kill is set dont allow ON state */ | ||
8293 | if (iwl3945_is_rfkill(priv)) | ||
8294 | err = -EBUSY; | ||
8295 | break; | ||
8296 | case RFKILL_STATE_SOFT_BLOCKED: | ||
8297 | iwl3945_radio_kill_sw(priv, 1); | ||
8298 | if (!iwl3945_is_rfkill(priv)) | ||
8299 | err = -EBUSY; | ||
8300 | break; | ||
8301 | default: | ||
8302 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | ||
8303 | break; | ||
8304 | } | ||
8305 | mutex_unlock(&priv->mutex); | ||
8306 | |||
8307 | return err; | ||
8308 | } | ||
8309 | |||
8310 | int iwl3945_rfkill_init(struct iwl3945_priv *priv) | ||
8311 | { | ||
8312 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
8313 | int ret = 0; | ||
8314 | |||
8315 | BUG_ON(device == NULL); | ||
8316 | |||
8317 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | ||
8318 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | ||
8319 | if (!priv->rfkill_mngr.rfkill) { | ||
8320 | IWL_ERROR("Unable to allocate rfkill device.\n"); | ||
8321 | ret = -ENOMEM; | ||
8322 | goto error; | ||
8323 | } | ||
8324 | |||
8325 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | ||
8326 | priv->rfkill_mngr.rfkill->data = priv; | ||
8327 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
8328 | priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; | ||
8329 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | ||
8330 | |||
8331 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | ||
8332 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | ||
8333 | |||
8334 | priv->rfkill_mngr.input_dev = input_allocate_device(); | ||
8335 | if (!priv->rfkill_mngr.input_dev) { | ||
8336 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | ||
8337 | ret = -ENOMEM; | ||
8338 | goto freed_rfkill; | ||
8339 | } | ||
8340 | |||
8341 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | ||
8342 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
8343 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
8344 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
8345 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
8346 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
8347 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
8348 | |||
8349 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | ||
8350 | if (ret) { | ||
8351 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | ||
8352 | goto free_input_dev; | ||
8353 | } | ||
8354 | |||
8355 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
8356 | if (ret) { | ||
8357 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | ||
8358 | goto unregister_rfkill; | ||
8359 | } | ||
8360 | |||
8361 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8362 | return ret; | ||
8363 | |||
8364 | unregister_rfkill: | ||
8365 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8366 | priv->rfkill_mngr.rfkill = NULL; | ||
8367 | |||
8368 | free_input_dev: | ||
8369 | input_free_device(priv->rfkill_mngr.input_dev); | ||
8370 | priv->rfkill_mngr.input_dev = NULL; | ||
8371 | |||
8372 | freed_rfkill: | ||
8373 | if (priv->rfkill_mngr.rfkill != NULL) | ||
8374 | rfkill_free(priv->rfkill_mngr.rfkill); | ||
8375 | priv->rfkill_mngr.rfkill = NULL; | ||
8376 | |||
8377 | error: | ||
8378 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | ||
8379 | return ret; | ||
8380 | } | ||
8381 | |||
8382 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | ||
8383 | { | ||
8384 | |||
8385 | if (priv->rfkill_mngr.input_dev) | ||
8386 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
8387 | |||
8388 | if (priv->rfkill_mngr.rfkill) | ||
8389 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8390 | |||
8391 | priv->rfkill_mngr.input_dev = NULL; | ||
8392 | priv->rfkill_mngr.rfkill = NULL; | ||
8393 | } | ||
8394 | |||
8395 | /* set rf-kill to the right state. */ | ||
8396 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | ||
8397 | { | ||
8398 | |||
8399 | if (!priv->rfkill_mngr.rfkill) | ||
8400 | return; | ||
8401 | |||
8402 | if (!iwl3945_is_rfkill(priv)) | ||
8403 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | ||
8404 | else | ||
8405 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | ||
8406 | } | ||
8407 | #endif | ||
8408 | |||
8302 | /***************************************************************************** | 8409 | /***************************************************************************** |
8303 | * | 8410 | * |
8304 | * driver and module entry point | 8411 | * driver and module entry point |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f5911687671b..ba0f28945eb1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -192,7 +192,7 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) | |||
192 | { | 192 | { |
193 | 193 | ||
194 | /* These items are only settable from the full RXON command */ | 194 | /* These items are only settable from the full RXON command */ |
195 | if (!(priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) || | 195 | if (!(iwl_is_associated(priv)) || |
196 | compare_ether_addr(priv->staging_rxon.bssid_addr, | 196 | compare_ether_addr(priv->staging_rxon.bssid_addr, |
197 | priv->active_rxon.bssid_addr) || | 197 | priv->active_rxon.bssid_addr) || |
198 | compare_ether_addr(priv->staging_rxon.node_addr, | 198 | compare_ether_addr(priv->staging_rxon.node_addr, |
@@ -241,16 +241,18 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
241 | /* cast away the const for active_rxon in this function */ | 241 | /* cast away the const for active_rxon in this function */ |
242 | struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; | 242 | struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; |
243 | DECLARE_MAC_BUF(mac); | 243 | DECLARE_MAC_BUF(mac); |
244 | int rc = 0; | 244 | int ret; |
245 | bool new_assoc = | ||
246 | !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); | ||
245 | 247 | ||
246 | if (!iwl_is_alive(priv)) | 248 | if (!iwl_is_alive(priv)) |
247 | return -1; | 249 | return -EBUSY; |
248 | 250 | ||
249 | /* always get timestamp with Rx frame */ | 251 | /* always get timestamp with Rx frame */ |
250 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; | 252 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; |
251 | 253 | ||
252 | rc = iwl4965_check_rxon_cmd(&priv->staging_rxon); | 254 | ret = iwl4965_check_rxon_cmd(&priv->staging_rxon); |
253 | if (rc) { | 255 | if (ret) { |
254 | IWL_ERROR("Invalid RXON configuration. Not committing.\n"); | 256 | IWL_ERROR("Invalid RXON configuration. Not committing.\n"); |
255 | return -EINVAL; | 257 | return -EINVAL; |
256 | } | 258 | } |
@@ -259,15 +261,13 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
259 | * iwl4965_rxon_assoc_cmd which is used to reconfigure filter | 261 | * iwl4965_rxon_assoc_cmd which is used to reconfigure filter |
260 | * and other flags for the current radio configuration. */ | 262 | * and other flags for the current radio configuration. */ |
261 | if (!iwl4965_full_rxon_required(priv)) { | 263 | if (!iwl4965_full_rxon_required(priv)) { |
262 | rc = iwl_send_rxon_assoc(priv); | 264 | ret = iwl_send_rxon_assoc(priv); |
263 | if (rc) { | 265 | if (ret) { |
264 | IWL_ERROR("Error setting RXON_ASSOC " | 266 | IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret); |
265 | "configuration (%d).\n", rc); | 267 | return ret; |
266 | return rc; | ||
267 | } | 268 | } |
268 | 269 | ||
269 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 270 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
270 | |||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
@@ -278,22 +278,20 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
278 | * an RXON_ASSOC and the new config wants the associated mask enabled, | 278 | * an RXON_ASSOC and the new config wants the associated mask enabled, |
279 | * we must clear the associated from the active configuration | 279 | * we must clear the associated from the active configuration |
280 | * before we apply the new config */ | 280 | * before we apply the new config */ |
281 | if (iwl_is_associated(priv) && | 281 | if (iwl_is_associated(priv) && new_assoc) { |
282 | (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) { | ||
283 | IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); | 282 | IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); |
284 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 283 | active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
285 | 284 | ||
286 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | 285 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, |
287 | sizeof(struct iwl_rxon_cmd), | 286 | sizeof(struct iwl_rxon_cmd), |
288 | &priv->active_rxon); | 287 | &priv->active_rxon); |
289 | 288 | ||
290 | /* If the mask clearing failed then we set | 289 | /* If the mask clearing failed then we set |
291 | * active_rxon back to what it was previously */ | 290 | * active_rxon back to what it was previously */ |
292 | if (rc) { | 291 | if (ret) { |
293 | active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; | 292 | active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; |
294 | IWL_ERROR("Error clearing ASSOC_MSK on current " | 293 | IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret); |
295 | "configuration (%d).\n", rc); | 294 | return ret; |
296 | return rc; | ||
297 | } | 295 | } |
298 | } | 296 | } |
299 | 297 | ||
@@ -301,58 +299,75 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
301 | "* with%s RXON_FILTER_ASSOC_MSK\n" | 299 | "* with%s RXON_FILTER_ASSOC_MSK\n" |
302 | "* channel = %d\n" | 300 | "* channel = %d\n" |
303 | "* bssid = %s\n", | 301 | "* bssid = %s\n", |
304 | ((priv->staging_rxon.filter_flags & | 302 | (new_assoc ? "" : "out"), |
305 | RXON_FILTER_ASSOC_MSK) ? "" : "out"), | ||
306 | le16_to_cpu(priv->staging_rxon.channel), | 303 | le16_to_cpu(priv->staging_rxon.channel), |
307 | print_mac(mac, priv->staging_rxon.bssid_addr)); | 304 | print_mac(mac, priv->staging_rxon.bssid_addr)); |
308 | 305 | ||
309 | iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); | 306 | iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); |
310 | /* Apply the new configuration */ | 307 | |
311 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | 308 | /* Apply the new configuration |
309 | * RXON unassoc clears the station table in uCode, send it before | ||
310 | * we add the bcast station. If assoc bit is set, we will send RXON | ||
311 | * after having added the bcast and bssid station. | ||
312 | */ | ||
313 | if (!new_assoc) { | ||
314 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
312 | sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); | 315 | sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); |
313 | if (rc) { | 316 | if (ret) { |
314 | IWL_ERROR("Error setting new configuration (%d).\n", rc); | 317 | IWL_ERROR("Error setting new RXON (%d)\n", ret); |
315 | return rc; | 318 | return ret; |
319 | } | ||
320 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | ||
316 | } | 321 | } |
317 | 322 | ||
318 | iwl_remove_station(priv, iwl_bcast_addr, 0); | 323 | iwl_clear_stations_table(priv); |
319 | iwlcore_clear_stations_table(priv); | ||
320 | 324 | ||
321 | if (!priv->error_recovering) | 325 | if (!priv->error_recovering) |
322 | priv->start_calib = 0; | 326 | priv->start_calib = 0; |
323 | 327 | ||
324 | iwl_init_sensitivity(priv); | 328 | iwl_init_sensitivity(priv); |
325 | 329 | ||
326 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | ||
327 | |||
328 | /* If we issue a new RXON command which required a tune then we must | 330 | /* If we issue a new RXON command which required a tune then we must |
329 | * send a new TXPOWER command or we won't be able to Tx any frames */ | 331 | * send a new TXPOWER command or we won't be able to Tx any frames */ |
330 | rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | 332 | ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); |
331 | if (rc) { | 333 | if (ret) { |
332 | IWL_ERROR("Error sending TX power (%d).\n", rc); | 334 | IWL_ERROR("Error sending TX power (%d)\n", ret); |
333 | return rc; | 335 | return ret; |
334 | } | 336 | } |
335 | 337 | ||
336 | /* Add the broadcast address so we can send broadcast frames */ | 338 | /* Add the broadcast address so we can send broadcast frames */ |
337 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == | 339 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == |
338 | IWL_INVALID_STATION) { | 340 | IWL_INVALID_STATION) { |
339 | IWL_ERROR("Error adding BROADCAST address for transmit.\n"); | 341 | IWL_ERROR("Error adding BROADCAST address for transmit.\n"); |
340 | return -EIO; | 342 | return -EIO; |
341 | } | 343 | } |
342 | 344 | ||
343 | /* If we have set the ASSOC_MSK and we are in BSS mode then | 345 | /* If we have set the ASSOC_MSK and we are in BSS mode then |
344 | * add the IWL_AP_ID to the station rate table */ | 346 | * add the IWL_AP_ID to the station rate table */ |
345 | if (iwl_is_associated(priv) && | 347 | if (new_assoc) { |
346 | (priv->iw_mode == IEEE80211_IF_TYPE_STA)) { | 348 | if (priv->iw_mode == IEEE80211_IF_TYPE_STA) { |
347 | if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1) | 349 | ret = iwl_rxon_add_station(priv, |
348 | == IWL_INVALID_STATION) { | 350 | priv->active_rxon.bssid_addr, 1); |
349 | IWL_ERROR("Error adding AP address for transmit.\n"); | 351 | if (ret == IWL_INVALID_STATION) { |
350 | return -EIO; | 352 | IWL_ERROR("Error adding AP address for TX.\n"); |
353 | return -EIO; | ||
354 | } | ||
355 | priv->assoc_station_added = 1; | ||
356 | if (priv->default_wep_key && | ||
357 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
358 | IWL_ERROR("Could not send WEP static key.\n"); | ||
351 | } | 359 | } |
352 | priv->assoc_station_added = 1; | 360 | |
353 | if (priv->default_wep_key && | 361 | /* Apply the new configuration |
354 | iwl_send_static_wepkey_cmd(priv, 0)) | 362 | * RXON assoc doesn't clear the station table in uCode, |
355 | IWL_ERROR("Could not send WEP static key.\n"); | 363 | */ |
364 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON, | ||
365 | sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); | ||
366 | if (ret) { | ||
367 | IWL_ERROR("Error setting new RXON (%d)\n", ret); | ||
368 | return ret; | ||
369 | } | ||
370 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | ||
356 | } | 371 | } |
357 | 372 | ||
358 | return 0; | 373 | return 0; |
@@ -601,50 +616,6 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) | |||
601 | } | 616 | } |
602 | } | 617 | } |
603 | 618 | ||
604 | int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) | ||
605 | { | ||
606 | /* Filter incoming packets to determine if they are targeted toward | ||
607 | * this network, discarding packets coming from ourselves */ | ||
608 | switch (priv->iw_mode) { | ||
609 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | ||
610 | /* packets from our adapter are dropped (echo) */ | ||
611 | if (!compare_ether_addr(header->addr2, priv->mac_addr)) | ||
612 | return 0; | ||
613 | /* {broad,multi}cast packets to our IBSS go through */ | ||
614 | if (is_multicast_ether_addr(header->addr1)) | ||
615 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
616 | /* packets to our adapter go through */ | ||
617 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
618 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | ||
619 | /* packets from our adapter are dropped (echo) */ | ||
620 | if (!compare_ether_addr(header->addr3, priv->mac_addr)) | ||
621 | return 0; | ||
622 | /* {broad,multi}cast packets to our BSS go through */ | ||
623 | if (is_multicast_ether_addr(header->addr1)) | ||
624 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
625 | /* packets to our adapter go through */ | ||
626 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
627 | default: | ||
628 | break; | ||
629 | } | ||
630 | |||
631 | return 1; | ||
632 | } | ||
633 | |||
634 | static void iwl4965_sequence_reset(struct iwl_priv *priv) | ||
635 | { | ||
636 | /* Reset ieee stats */ | ||
637 | |||
638 | /* We don't reset the net_device_stats (ieee->stats) on | ||
639 | * re-association */ | ||
640 | |||
641 | priv->last_seq_num = -1; | ||
642 | priv->last_frag_num = -1; | ||
643 | priv->last_packet_time = 0; | ||
644 | |||
645 | iwl_scan_cancel(priv); | ||
646 | } | ||
647 | |||
648 | #define MAX_UCODE_BEACON_INTERVAL 4096 | 619 | #define MAX_UCODE_BEACON_INTERVAL 4096 |
649 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) | 620 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) |
650 | 621 | ||
@@ -787,7 +758,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) | |||
787 | #endif | 758 | #endif |
788 | 759 | ||
789 | ch_info = iwl_get_channel_info(priv, priv->band, | 760 | ch_info = iwl_get_channel_info(priv, priv->band, |
790 | le16_to_cpu(priv->staging_rxon.channel)); | 761 | le16_to_cpu(priv->active_rxon.channel)); |
791 | 762 | ||
792 | if (!ch_info) | 763 | if (!ch_info) |
793 | ch_info = &priv->channel_info[0]; | 764 | ch_info = &priv->channel_info[0]; |
@@ -823,13 +794,10 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) | |||
823 | { | 794 | { |
824 | priv->iw_mode = mode; | 795 | priv->iw_mode = mode; |
825 | 796 | ||
826 | /* init channel/phymode to values given at driver init */ | ||
827 | iwl_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); | ||
828 | |||
829 | iwl4965_connection_init_rx_config(priv); | 797 | iwl4965_connection_init_rx_config(priv); |
830 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); | 798 | memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); |
831 | 799 | ||
832 | iwlcore_clear_stations_table(priv); | 800 | iwl_clear_stations_table(priv); |
833 | 801 | ||
834 | /* dont commit rxon if rf-kill is on*/ | 802 | /* dont commit rxon if rf-kill is on*/ |
835 | if (!iwl_is_ready_rf(priv)) | 803 | if (!iwl_is_ready_rf(priv)) |
@@ -894,72 +862,6 @@ static void iwl4965_set_rate(struct iwl_priv *priv) | |||
894 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 862 | (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
895 | } | 863 | } |
896 | 864 | ||
897 | #define IWL_PACKET_RETRY_TIME HZ | ||
898 | |||
899 | int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) | ||
900 | { | ||
901 | u16 sc = le16_to_cpu(header->seq_ctrl); | ||
902 | u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
903 | u16 frag = sc & IEEE80211_SCTL_FRAG; | ||
904 | u16 *last_seq, *last_frag; | ||
905 | unsigned long *last_time; | ||
906 | |||
907 | switch (priv->iw_mode) { | ||
908 | case IEEE80211_IF_TYPE_IBSS:{ | ||
909 | struct list_head *p; | ||
910 | struct iwl4965_ibss_seq *entry = NULL; | ||
911 | u8 *mac = header->addr2; | ||
912 | int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); | ||
913 | |||
914 | __list_for_each(p, &priv->ibss_mac_hash[index]) { | ||
915 | entry = list_entry(p, struct iwl4965_ibss_seq, list); | ||
916 | if (!compare_ether_addr(entry->mac, mac)) | ||
917 | break; | ||
918 | } | ||
919 | if (p == &priv->ibss_mac_hash[index]) { | ||
920 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | ||
921 | if (!entry) { | ||
922 | IWL_ERROR("Cannot malloc new mac entry\n"); | ||
923 | return 0; | ||
924 | } | ||
925 | memcpy(entry->mac, mac, ETH_ALEN); | ||
926 | entry->seq_num = seq; | ||
927 | entry->frag_num = frag; | ||
928 | entry->packet_time = jiffies; | ||
929 | list_add(&entry->list, &priv->ibss_mac_hash[index]); | ||
930 | return 0; | ||
931 | } | ||
932 | last_seq = &entry->seq_num; | ||
933 | last_frag = &entry->frag_num; | ||
934 | last_time = &entry->packet_time; | ||
935 | break; | ||
936 | } | ||
937 | case IEEE80211_IF_TYPE_STA: | ||
938 | last_seq = &priv->last_seq_num; | ||
939 | last_frag = &priv->last_frag_num; | ||
940 | last_time = &priv->last_packet_time; | ||
941 | break; | ||
942 | default: | ||
943 | return 0; | ||
944 | } | ||
945 | if ((*last_seq == seq) && | ||
946 | time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { | ||
947 | if (*last_frag == frag) | ||
948 | goto drop; | ||
949 | if (*last_frag + 1 != frag) | ||
950 | /* out-of-order fragment */ | ||
951 | goto drop; | ||
952 | } else | ||
953 | *last_seq = seq; | ||
954 | |||
955 | *last_frag = frag; | ||
956 | *last_time = jiffies; | ||
957 | return 0; | ||
958 | |||
959 | drop: | ||
960 | return 1; | ||
961 | } | ||
962 | |||
963 | #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT | 865 | #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT |
964 | 866 | ||
965 | #include "iwl-spectrum.h" | 867 | #include "iwl-spectrum.h" |
@@ -1338,17 +1240,6 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, | |||
1338 | wake_up_interruptible(&priv->wait_command_queue); | 1240 | wake_up_interruptible(&priv->wait_command_queue); |
1339 | } | 1241 | } |
1340 | 1242 | ||
1341 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1342 | * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1343 | static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1344 | struct iwl_rx_mem_buffer *rxb) | ||
1345 | { | ||
1346 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
1347 | priv->last_phy_res[0] = 1; | ||
1348 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1349 | sizeof(struct iwl4965_rx_phy_res)); | ||
1350 | } | ||
1351 | |||
1352 | /** | 1243 | /** |
1353 | * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks | 1244 | * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks |
1354 | * | 1245 | * |
@@ -1358,7 +1249,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv, | |||
1358 | * This function chains into the hardware specific files for them to setup | 1249 | * This function chains into the hardware specific files for them to setup |
1359 | * any hardware specific handlers as well. | 1250 | * any hardware specific handlers as well. |
1360 | */ | 1251 | */ |
1361 | static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) | 1252 | static void iwl_setup_rx_handlers(struct iwl_priv *priv) |
1362 | { | 1253 | { |
1363 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; | 1254 | priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; |
1364 | priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error; | 1255 | priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error; |
@@ -1375,8 +1266,8 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) | |||
1375 | * statistics request from the host as well as for the periodic | 1266 | * statistics request from the host as well as for the periodic |
1376 | * statistics notifications (after received beacons) from the uCode. | 1267 | * statistics notifications (after received beacons) from the uCode. |
1377 | */ | 1268 | */ |
1378 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics; | 1269 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; |
1379 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics; | 1270 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
1380 | 1271 | ||
1381 | iwl_setup_rx_scan_handlers(priv); | 1272 | iwl_setup_rx_scan_handlers(priv); |
1382 | 1273 | ||
@@ -1386,8 +1277,10 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) | |||
1386 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | 1277 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = |
1387 | iwl_rx_missed_beacon_notif; | 1278 | iwl_rx_missed_beacon_notif; |
1388 | /* Rx handlers */ | 1279 | /* Rx handlers */ |
1389 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy; | 1280 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; |
1390 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx; | 1281 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; |
1282 | /* block ack */ | ||
1283 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; | ||
1391 | /* Set up hardware specific Rx handlers */ | 1284 | /* Set up hardware specific Rx handlers */ |
1392 | priv->cfg->ops->lib->rx_handler_setup(priv); | 1285 | priv->cfg->ops->lib->rx_handler_setup(priv); |
1393 | } | 1286 | } |
@@ -1518,47 +1411,6 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1518 | iwl_rx_queue_restock(priv); | 1411 | iwl_rx_queue_restock(priv); |
1519 | } | 1412 | } |
1520 | 1413 | ||
1521 | #define PERFECT_RSSI (-20) /* dBm */ | ||
1522 | #define WORST_RSSI (-95) /* dBm */ | ||
1523 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
1524 | |||
1525 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
1526 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
1527 | * about formulas used below. */ | ||
1528 | int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
1529 | { | ||
1530 | int sig_qual; | ||
1531 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
1532 | |||
1533 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
1534 | * as indicator; formula is (signal dbm - noise dbm). | ||
1535 | * SNR at or above 40 is a great signal (100%). | ||
1536 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
1537 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
1538 | if (noise_dbm) { | ||
1539 | if (rssi_dbm - noise_dbm >= 40) | ||
1540 | return 100; | ||
1541 | else if (rssi_dbm < noise_dbm) | ||
1542 | return 0; | ||
1543 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
1544 | |||
1545 | /* Else use just the signal level. | ||
1546 | * This formula is a least squares fit of data points collected and | ||
1547 | * compared with a reference system that had a percentage (%) display | ||
1548 | * for signal quality. */ | ||
1549 | } else | ||
1550 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
1551 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
1552 | (RSSI_RANGE * RSSI_RANGE); | ||
1553 | |||
1554 | if (sig_qual > 100) | ||
1555 | sig_qual = 100; | ||
1556 | else if (sig_qual < 1) | ||
1557 | sig_qual = 0; | ||
1558 | |||
1559 | return sig_qual; | ||
1560 | } | ||
1561 | |||
1562 | #ifdef CONFIG_IWLWIFI_DEBUG | 1414 | #ifdef CONFIG_IWLWIFI_DEBUG |
1563 | static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv) | 1415 | static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv) |
1564 | { | 1416 | { |
@@ -1751,14 +1603,12 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) | |||
1751 | IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n", | 1603 | IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n", |
1752 | hw_rf_kill ? "disable radio":"enable radio"); | 1604 | hw_rf_kill ? "disable radio":"enable radio"); |
1753 | 1605 | ||
1754 | /* Queue restart only if RF_KILL switch was set to "kill" | 1606 | /* driver only loads ucode once setting the interface up. |
1755 | * when we loaded driver, and is now set to "enable". | 1607 | * the driver as well won't allow loading if RFKILL is set |
1756 | * After we're Alive, RF_KILL gets handled by | 1608 | * therefore no need to restart the driver from this handler |
1757 | * iwl4965_rx_card_state_notif() */ | 1609 | */ |
1758 | if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { | 1610 | if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) |
1759 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 1611 | clear_bit(STATUS_RF_KILL_HW, &priv->status); |
1760 | queue_work(priv->workqueue, &priv->restart); | ||
1761 | } | ||
1762 | 1612 | ||
1763 | handled |= CSR_INT_BIT_RF_KILL; | 1613 | handled |= CSR_INT_BIT_RF_KILL; |
1764 | } | 1614 | } |
@@ -2138,7 +1988,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2138 | goto restart; | 1988 | goto restart; |
2139 | } | 1989 | } |
2140 | 1990 | ||
2141 | iwlcore_clear_stations_table(priv); | 1991 | iwl_clear_stations_table(priv); |
2142 | ret = priv->cfg->ops->lib->alive_notify(priv); | 1992 | ret = priv->cfg->ops->lib->alive_notify(priv); |
2143 | if (ret) { | 1993 | if (ret) { |
2144 | IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", | 1994 | IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", |
@@ -2216,7 +2066,7 @@ static void __iwl4965_down(struct iwl_priv *priv) | |||
2216 | 2066 | ||
2217 | iwl_leds_unregister(priv); | 2067 | iwl_leds_unregister(priv); |
2218 | 2068 | ||
2219 | iwlcore_clear_stations_table(priv); | 2069 | iwl_clear_stations_table(priv); |
2220 | 2070 | ||
2221 | /* Unblock any waiting calls */ | 2071 | /* Unblock any waiting calls */ |
2222 | wake_up_interruptible_all(&priv->wait_command_queue); | 2072 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2248,7 +2098,9 @@ static void __iwl4965_down(struct iwl_priv *priv) | |||
2248 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | 2098 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |
2249 | STATUS_GEO_CONFIGURED | | 2099 | STATUS_GEO_CONFIGURED | |
2250 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 2100 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
2251 | STATUS_IN_SUSPEND; | 2101 | STATUS_IN_SUSPEND | |
2102 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
2103 | STATUS_EXIT_PENDING; | ||
2252 | goto exit; | 2104 | goto exit; |
2253 | } | 2105 | } |
2254 | 2106 | ||
@@ -2263,7 +2115,9 @@ static void __iwl4965_down(struct iwl_priv *priv) | |||
2263 | test_bit(STATUS_IN_SUSPEND, &priv->status) << | 2115 | test_bit(STATUS_IN_SUSPEND, &priv->status) << |
2264 | STATUS_IN_SUSPEND | | 2116 | STATUS_IN_SUSPEND | |
2265 | test_bit(STATUS_FW_ERROR, &priv->status) << | 2117 | test_bit(STATUS_FW_ERROR, &priv->status) << |
2266 | STATUS_FW_ERROR; | 2118 | STATUS_FW_ERROR | |
2119 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||
2120 | STATUS_EXIT_PENDING; | ||
2267 | 2121 | ||
2268 | spin_lock_irqsave(&priv->lock, flags); | 2122 | spin_lock_irqsave(&priv->lock, flags); |
2269 | iwl_clear_bit(priv, CSR_GP_CNTRL, | 2123 | iwl_clear_bit(priv, CSR_GP_CNTRL, |
@@ -2328,13 +2182,15 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
2328 | if (iwl_read32(priv, CSR_GP_CNTRL) & | 2182 | if (iwl_read32(priv, CSR_GP_CNTRL) & |
2329 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 2183 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) |
2330 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 2184 | clear_bit(STATUS_RF_KILL_HW, &priv->status); |
2331 | else { | 2185 | else |
2332 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 2186 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
2333 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 2187 | |
2334 | iwl_rfkill_set_hw_state(priv); | 2188 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && |
2335 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 2189 | iwl_is_rfkill(priv)) { |
2336 | return -ENODEV; | 2190 | iwl_rfkill_set_hw_state(priv); |
2337 | } | 2191 | IWL_WARNING("Radio disabled by %s RF Kill switch\n", |
2192 | test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); | ||
2193 | return -ENODEV; | ||
2338 | } | 2194 | } |
2339 | 2195 | ||
2340 | iwl_rfkill_set_hw_state(priv); | 2196 | iwl_rfkill_set_hw_state(priv); |
@@ -2378,7 +2234,7 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
2378 | 2234 | ||
2379 | for (i = 0; i < MAX_HW_RESTARTS; i++) { | 2235 | for (i = 0; i < MAX_HW_RESTARTS; i++) { |
2380 | 2236 | ||
2381 | iwlcore_clear_stations_table(priv); | 2237 | iwl_clear_stations_table(priv); |
2382 | 2238 | ||
2383 | /* load bootstrap state machine, | 2239 | /* load bootstrap state machine, |
2384 | * load bootstrap program into processor's memory, | 2240 | * load bootstrap program into processor's memory, |
@@ -2631,7 +2487,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2631 | 2487 | ||
2632 | switch (priv->iw_mode) { | 2488 | switch (priv->iw_mode) { |
2633 | case IEEE80211_IF_TYPE_STA: | 2489 | case IEEE80211_IF_TYPE_STA: |
2634 | iwl4965_rate_scale_init(priv->hw, IWL_AP_ID); | ||
2635 | break; | 2490 | break; |
2636 | 2491 | ||
2637 | case IEEE80211_IF_TYPE_IBSS: | 2492 | case IEEE80211_IF_TYPE_IBSS: |
@@ -2640,7 +2495,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2640 | priv->assoc_id = 1; | 2495 | priv->assoc_id = 1; |
2641 | 2496 | ||
2642 | iwl_rxon_add_station(priv, priv->bssid, 0); | 2497 | iwl_rxon_add_station(priv, priv->bssid, 0); |
2643 | iwl4965_rate_scale_init(priv->hw, IWL_STA_ID); | ||
2644 | iwl4965_send_beacon_cmd(priv); | 2498 | iwl4965_send_beacon_cmd(priv); |
2645 | 2499 | ||
2646 | break; | 2500 | break; |
@@ -2651,8 +2505,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2651 | break; | 2505 | break; |
2652 | } | 2506 | } |
2653 | 2507 | ||
2654 | iwl4965_sequence_reset(priv); | ||
2655 | |||
2656 | /* Enable Rx differential gain and sensitivity calibrations */ | 2508 | /* Enable Rx differential gain and sensitivity calibrations */ |
2657 | iwl_chain_noise_reset(priv); | 2509 | iwl_chain_noise_reset(priv); |
2658 | priv->start_calib = 1; | 2510 | priv->start_calib = 1; |
@@ -2709,7 +2561,7 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
2709 | * | 2561 | * |
2710 | *****************************************************************************/ | 2562 | *****************************************************************************/ |
2711 | 2563 | ||
2712 | #define UCODE_READY_TIMEOUT (2 * HZ) | 2564 | #define UCODE_READY_TIMEOUT (4 * HZ) |
2713 | 2565 | ||
2714 | static int iwl4965_mac_start(struct ieee80211_hw *hw) | 2566 | static int iwl4965_mac_start(struct ieee80211_hw *hw) |
2715 | { | 2567 | { |
@@ -2762,21 +2614,19 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) | |||
2762 | 2614 | ||
2763 | /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from | 2615 | /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from |
2764 | * mac80211 will not be run successfully. */ | 2616 | * mac80211 will not be run successfully. */ |
2765 | if (priv->ucode_type == UCODE_RT) { | 2617 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, |
2766 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | 2618 | test_bit(STATUS_READY, &priv->status), |
2767 | test_bit(STATUS_READY, &priv->status), | 2619 | UCODE_READY_TIMEOUT); |
2768 | UCODE_READY_TIMEOUT); | 2620 | if (!ret) { |
2769 | if (!ret) { | 2621 | if (!test_bit(STATUS_READY, &priv->status)) { |
2770 | if (!test_bit(STATUS_READY, &priv->status)) { | 2622 | IWL_ERROR("START_ALIVE timeout after %dms.\n", |
2771 | IWL_ERROR("START_ALIVE timeout after %dms.\n", | 2623 | jiffies_to_msecs(UCODE_READY_TIMEOUT)); |
2772 | jiffies_to_msecs(UCODE_READY_TIMEOUT)); | 2624 | ret = -ETIMEDOUT; |
2773 | ret = -ETIMEDOUT; | 2625 | goto out_release_irq; |
2774 | goto out_release_irq; | ||
2775 | } | ||
2776 | } | 2626 | } |
2777 | |||
2778 | priv->is_open = 1; | ||
2779 | } | 2627 | } |
2628 | |||
2629 | priv->is_open = 1; | ||
2780 | IWL_DEBUG_MAC80211("leave\n"); | 2630 | IWL_DEBUG_MAC80211("leave\n"); |
2781 | return 0; | 2631 | return 0; |
2782 | 2632 | ||
@@ -3009,7 +2859,7 @@ static void iwl4965_config_ap(struct iwl_priv *priv) | |||
3009 | return; | 2859 | return; |
3010 | 2860 | ||
3011 | /* The following should be done only at AP bring up */ | 2861 | /* The following should be done only at AP bring up */ |
3012 | if ((priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) == 0) { | 2862 | if (!(iwl_is_associated(priv))) { |
3013 | 2863 | ||
3014 | /* RXON - unassoc (to set timing command) */ | 2864 | /* RXON - unassoc (to set timing command) */ |
3015 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2865 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
@@ -3172,26 +3022,18 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw, | |||
3172 | unsigned int *total_flags, | 3022 | unsigned int *total_flags, |
3173 | int mc_count, struct dev_addr_list *mc_list) | 3023 | int mc_count, struct dev_addr_list *mc_list) |
3174 | { | 3024 | { |
3175 | /* | ||
3176 | * XXX: dummy | ||
3177 | * see also iwl4965_connection_init_rx_config | ||
3178 | */ | ||
3179 | struct iwl_priv *priv = hw->priv; | 3025 | struct iwl_priv *priv = hw->priv; |
3180 | int new_flags = 0; | 3026 | |
3181 | if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | 3027 | if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { |
3182 | if (*total_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | 3028 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", |
3183 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", | 3029 | IEEE80211_IF_TYPE_MNTR, |
3184 | IEEE80211_IF_TYPE_MNTR, | 3030 | changed_flags, *total_flags); |
3185 | changed_flags, *total_flags); | 3031 | /* queue work 'cuz mac80211 is holding a lock which |
3186 | /* queue work 'cuz mac80211 is holding a lock which | 3032 | * prevents us from issuing (synchronous) f/w cmds */ |
3187 | * prevents us from issuing (synchronous) f/w cmds */ | 3033 | queue_work(priv->workqueue, &priv->set_monitor); |
3188 | queue_work(priv->workqueue, &priv->set_monitor); | ||
3189 | new_flags &= FIF_PROMISC_IN_BSS | | ||
3190 | FIF_OTHER_BSS | | ||
3191 | FIF_ALLMULTI; | ||
3192 | } | ||
3193 | } | 3034 | } |
3194 | *total_flags = new_flags; | 3035 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | |
3036 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||
3195 | } | 3037 | } |
3196 | 3038 | ||
3197 | static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, | 3039 | static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, |
@@ -3556,17 +3398,6 @@ static int iwl4965_mac_get_stats(struct ieee80211_hw *hw, | |||
3556 | return 0; | 3398 | return 0; |
3557 | } | 3399 | } |
3558 | 3400 | ||
3559 | static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw) | ||
3560 | { | ||
3561 | struct iwl_priv *priv; | ||
3562 | |||
3563 | priv = hw->priv; | ||
3564 | IWL_DEBUG_MAC80211("enter\n"); | ||
3565 | IWL_DEBUG_MAC80211("leave\n"); | ||
3566 | |||
3567 | return 0; | ||
3568 | } | ||
3569 | |||
3570 | static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) | 3401 | static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) |
3571 | { | 3402 | { |
3572 | struct iwl_priv *priv = hw->priv; | 3403 | struct iwl_priv *priv = hw->priv; |
@@ -3575,7 +3406,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) | |||
3575 | mutex_lock(&priv->mutex); | 3406 | mutex_lock(&priv->mutex); |
3576 | IWL_DEBUG_MAC80211("enter\n"); | 3407 | IWL_DEBUG_MAC80211("enter\n"); |
3577 | 3408 | ||
3578 | priv->lq_mngr.lq_ready = 0; | ||
3579 | spin_lock_irqsave(&priv->lock, flags); | 3409 | spin_lock_irqsave(&priv->lock, flags); |
3580 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); | 3410 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); |
3581 | spin_unlock_irqrestore(&priv->lock, flags); | 3411 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -3638,6 +3468,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk | |||
3638 | { | 3468 | { |
3639 | struct iwl_priv *priv = hw->priv; | 3469 | struct iwl_priv *priv = hw->priv; |
3640 | unsigned long flags; | 3470 | unsigned long flags; |
3471 | __le64 timestamp; | ||
3641 | 3472 | ||
3642 | mutex_lock(&priv->mutex); | 3473 | mutex_lock(&priv->mutex); |
3643 | IWL_DEBUG_MAC80211("enter\n"); | 3474 | IWL_DEBUG_MAC80211("enter\n"); |
@@ -3662,6 +3493,8 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk | |||
3662 | priv->ibss_beacon = skb; | 3493 | priv->ibss_beacon = skb; |
3663 | 3494 | ||
3664 | priv->assoc_id = 0; | 3495 | priv->assoc_id = 0; |
3496 | timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | ||
3497 | priv->timestamp = le64_to_cpu(timestamp) + (priv->beacon_int * 1000); | ||
3665 | 3498 | ||
3666 | IWL_DEBUG_MAC80211("leave\n"); | 3499 | IWL_DEBUG_MAC80211("leave\n"); |
3667 | spin_unlock_irqrestore(&priv->lock, flags); | 3500 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -3728,16 +3561,28 @@ static ssize_t show_version(struct device *d, | |||
3728 | { | 3561 | { |
3729 | struct iwl_priv *priv = d->driver_data; | 3562 | struct iwl_priv *priv = d->driver_data; |
3730 | struct iwl_alive_resp *palive = &priv->card_alive; | 3563 | struct iwl_alive_resp *palive = &priv->card_alive; |
3564 | ssize_t pos = 0; | ||
3565 | u16 eeprom_ver; | ||
3731 | 3566 | ||
3732 | if (palive->is_valid) | 3567 | if (palive->is_valid) |
3733 | return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n" | 3568 | pos += sprintf(buf + pos, |
3734 | "fw type: 0x%01X 0x%01X\n", | 3569 | "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n" |
3570 | "fw type: 0x%01X 0x%01X\n", | ||
3735 | palive->ucode_major, palive->ucode_minor, | 3571 | palive->ucode_major, palive->ucode_minor, |
3736 | palive->sw_rev[0], palive->sw_rev[1], | 3572 | palive->sw_rev[0], palive->sw_rev[1], |
3737 | palive->ver_type, palive->ver_subtype); | 3573 | palive->ver_type, palive->ver_subtype); |
3738 | |||
3739 | else | 3574 | else |
3740 | return sprintf(buf, "fw not loaded\n"); | 3575 | pos += sprintf(buf + pos, "fw not loaded\n"); |
3576 | |||
3577 | if (priv->eeprom) { | ||
3578 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | ||
3579 | pos += sprintf(buf + pos, "EEPROM version: 0x%x\n", | ||
3580 | eeprom_ver); | ||
3581 | } else { | ||
3582 | pos += sprintf(buf + pos, "EEPROM not initialzed\n"); | ||
3583 | } | ||
3584 | |||
3585 | return pos; | ||
3741 | } | 3586 | } |
3742 | 3587 | ||
3743 | static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL); | 3588 | static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL); |
@@ -4106,7 +3951,7 @@ static ssize_t show_statistics(struct device *d, | |||
4106 | struct device_attribute *attr, char *buf) | 3951 | struct device_attribute *attr, char *buf) |
4107 | { | 3952 | { |
4108 | struct iwl_priv *priv = dev_get_drvdata(d); | 3953 | struct iwl_priv *priv = dev_get_drvdata(d); |
4109 | u32 size = sizeof(struct iwl4965_notif_statistics); | 3954 | u32 size = sizeof(struct iwl_notif_statistics); |
4110 | u32 len = 0, ofs = 0; | 3955 | u32 len = 0, ofs = 0; |
4111 | u8 *data = (u8 *) & priv->statistics; | 3956 | u8 *data = (u8 *) & priv->statistics; |
4112 | int rc = 0; | 3957 | int rc = 0; |
@@ -4243,7 +4088,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { | |||
4243 | .get_stats = iwl4965_mac_get_stats, | 4088 | .get_stats = iwl4965_mac_get_stats, |
4244 | .get_tx_stats = iwl4965_mac_get_tx_stats, | 4089 | .get_tx_stats = iwl4965_mac_get_tx_stats, |
4245 | .conf_tx = iwl4965_mac_conf_tx, | 4090 | .conf_tx = iwl4965_mac_conf_tx, |
4246 | .get_tsf = iwl4965_mac_get_tsf, | ||
4247 | .reset_tsf = iwl4965_mac_reset_tsf, | 4091 | .reset_tsf = iwl4965_mac_reset_tsf, |
4248 | .beacon_update = iwl4965_mac_beacon_update, | 4092 | .beacon_update = iwl4965_mac_beacon_update, |
4249 | .bss_info_changed = iwl4965_bss_info_changed, | 4093 | .bss_info_changed = iwl4965_bss_info_changed, |
@@ -4372,8 +4216,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4372 | /************************ | 4216 | /************************ |
4373 | * 5. Setup HW constants | 4217 | * 5. Setup HW constants |
4374 | ************************/ | 4218 | ************************/ |
4375 | /* Device-specific setup */ | 4219 | if (iwl_set_hw_params(priv)) { |
4376 | if (priv->cfg->ops->lib->set_hw_params(priv)) { | ||
4377 | IWL_ERROR("failed to set hw parameters\n"); | 4220 | IWL_ERROR("failed to set hw parameters\n"); |
4378 | goto out_free_eeprom; | 4221 | goto out_free_eeprom; |
4379 | } | 4222 | } |
@@ -4412,7 +4255,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4412 | 4255 | ||
4413 | 4256 | ||
4414 | iwl_setup_deferred_work(priv); | 4257 | iwl_setup_deferred_work(priv); |
4415 | iwl4965_setup_rx_handlers(priv); | 4258 | iwl_setup_rx_handlers(priv); |
4416 | 4259 | ||
4417 | /******************** | 4260 | /******************** |
4418 | * 9. Conclude | 4261 | * 9. Conclude |
@@ -4461,8 +4304,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4461 | static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | 4304 | static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) |
4462 | { | 4305 | { |
4463 | struct iwl_priv *priv = pci_get_drvdata(pdev); | 4306 | struct iwl_priv *priv = pci_get_drvdata(pdev); |
4464 | struct list_head *p, *q; | ||
4465 | int i; | ||
4466 | unsigned long flags; | 4307 | unsigned long flags; |
4467 | 4308 | ||
4468 | if (!priv) | 4309 | if (!priv) |
@@ -4491,14 +4332,6 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | |||
4491 | 4332 | ||
4492 | iwl_synchronize_irq(priv); | 4333 | iwl_synchronize_irq(priv); |
4493 | 4334 | ||
4494 | /* Free MAC hash list for ADHOC */ | ||
4495 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { | ||
4496 | list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { | ||
4497 | list_del(p); | ||
4498 | kfree(list_entry(p, struct iwl4965_ibss_seq, list)); | ||
4499 | } | ||
4500 | } | ||
4501 | |||
4502 | iwl_rfkill_unregister(priv); | 4335 | iwl_rfkill_unregister(priv); |
4503 | iwl4965_dealloc_ucode_pci(priv); | 4336 | iwl4965_dealloc_ucode_pci(priv); |
4504 | 4337 | ||
@@ -4506,7 +4339,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | |||
4506 | iwl_rx_queue_free(priv, &priv->rxq); | 4339 | iwl_rx_queue_free(priv, &priv->rxq); |
4507 | iwl_hw_txq_ctx_free(priv); | 4340 | iwl_hw_txq_ctx_free(priv); |
4508 | 4341 | ||
4509 | iwlcore_clear_stations_table(priv); | 4342 | iwl_clear_stations_table(priv); |
4510 | iwl_eeprom_free(priv); | 4343 | iwl_eeprom_free(priv); |
4511 | 4344 | ||
4512 | 4345 | ||
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 9f7224de6fd1..ffaf7a6b6810 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -357,6 +357,7 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
357 | 357 | ||
358 | rx_status.signal = hdr->rssi; | 358 | rx_status.signal = hdr->rssi; |
359 | /* XX correct? */ | 359 | /* XX correct? */ |
360 | rx_status.qual = (100 * hdr->rssi) / 127; | ||
360 | rx_status.rate_idx = hdr->rate & 0xf; | 361 | rx_status.rate_idx = hdr->rate & 0xf; |
361 | rx_status.freq = freq; | 362 | rx_status.freq = freq; |
362 | rx_status.band = IEEE80211_BAND_2GHZ; | 363 | rx_status.band = IEEE80211_BAND_2GHZ; |