diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 995 |
1 files changed, 12 insertions, 983 deletions
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"); |