diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-06-30 05:23:09 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-30 17:37:40 -0400 |
commit | 1781a07fbe9cce3dc1697288a5edd260ea7edc02 (patch) | |
tree | be06e824b69af8d43edfeab2c78a353f0bf7f8ce /drivers/net/wireless/iwlwifi/iwl-4965.c | |
parent | 37deb2a0baf1bb540b723cc8a3972b42ff2daac6 (diff) |
iwlwifi: move RX handlers to iwl-rx.c
This patch moves RX handlers to iwl-rx.c
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 703 |
1 files changed, 1 insertions, 702 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1688803af582..d8e6d2e6a86b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1929,707 +1929,6 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv, | |||
1929 | queue_work(priv->workqueue, &priv->txpower_work); | 1929 | queue_work(priv->workqueue, &priv->txpower_work); |
1930 | } | 1930 | } |
1931 | 1931 | ||
1932 | static void iwl4965_add_radiotap(struct iwl_priv *priv, | ||
1933 | struct sk_buff *skb, | ||
1934 | struct iwl4965_rx_phy_res *rx_start, | ||
1935 | struct ieee80211_rx_status *stats, | ||
1936 | u32 ampdu_status) | ||
1937 | { | ||
1938 | s8 signal = stats->signal; | ||
1939 | s8 noise = 0; | ||
1940 | int rate = stats->rate_idx; | ||
1941 | u64 tsf = stats->mactime; | ||
1942 | __le16 antenna; | ||
1943 | __le16 phy_flags_hw = rx_start->phy_flags; | ||
1944 | struct iwl4965_rt_rx_hdr { | ||
1945 | struct ieee80211_radiotap_header rt_hdr; | ||
1946 | __le64 rt_tsf; /* TSF */ | ||
1947 | u8 rt_flags; /* radiotap packet flags */ | ||
1948 | u8 rt_rate; /* rate in 500kb/s */ | ||
1949 | __le16 rt_channelMHz; /* channel in MHz */ | ||
1950 | __le16 rt_chbitmask; /* channel bitfield */ | ||
1951 | s8 rt_dbmsignal; /* signal in dBm, kluged to signed */ | ||
1952 | s8 rt_dbmnoise; | ||
1953 | u8 rt_antenna; /* antenna number */ | ||
1954 | } __attribute__ ((packed)) *iwl4965_rt; | ||
1955 | |||
1956 | /* TODO: We won't have enough headroom for HT frames. Fix it later. */ | ||
1957 | if (skb_headroom(skb) < sizeof(*iwl4965_rt)) { | ||
1958 | if (net_ratelimit()) | ||
1959 | printk(KERN_ERR "not enough headroom [%d] for " | ||
1960 | "radiotap head [%zd]\n", | ||
1961 | skb_headroom(skb), sizeof(*iwl4965_rt)); | ||
1962 | return; | ||
1963 | } | ||
1964 | |||
1965 | /* put radiotap header in front of 802.11 header and data */ | ||
1966 | iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt)); | ||
1967 | |||
1968 | /* initialise radiotap header */ | ||
1969 | iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
1970 | iwl4965_rt->rt_hdr.it_pad = 0; | ||
1971 | |||
1972 | /* total header + data */ | ||
1973 | put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), | ||
1974 | &iwl4965_rt->rt_hdr.it_len); | ||
1975 | |||
1976 | /* Indicate all the fields we add to the radiotap header */ | ||
1977 | put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | ||
1978 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
1979 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
1980 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
1981 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
1982 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
1983 | (1 << IEEE80211_RADIOTAP_ANTENNA)), | ||
1984 | &iwl4965_rt->rt_hdr.it_present); | ||
1985 | |||
1986 | /* Zero the flags, we'll add to them as we go */ | ||
1987 | iwl4965_rt->rt_flags = 0; | ||
1988 | |||
1989 | put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); | ||
1990 | |||
1991 | iwl4965_rt->rt_dbmsignal = signal; | ||
1992 | iwl4965_rt->rt_dbmnoise = noise; | ||
1993 | |||
1994 | /* Convert the channel frequency and set the flags */ | ||
1995 | put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); | ||
1996 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) | ||
1997 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
1998 | IEEE80211_CHAN_5GHZ), | ||
1999 | &iwl4965_rt->rt_chbitmask); | ||
2000 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) | ||
2001 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | | ||
2002 | IEEE80211_CHAN_2GHZ), | ||
2003 | &iwl4965_rt->rt_chbitmask); | ||
2004 | else /* 802.11g */ | ||
2005 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
2006 | IEEE80211_CHAN_2GHZ), | ||
2007 | &iwl4965_rt->rt_chbitmask); | ||
2008 | |||
2009 | if (rate == -1) | ||
2010 | iwl4965_rt->rt_rate = 0; | ||
2011 | else | ||
2012 | iwl4965_rt->rt_rate = iwl_rates[rate].ieee; | ||
2013 | |||
2014 | /* | ||
2015 | * "antenna number" | ||
2016 | * | ||
2017 | * It seems that the antenna field in the phy flags value | ||
2018 | * is actually a bitfield. This is undefined by radiotap, | ||
2019 | * it wants an actual antenna number but I always get "7" | ||
2020 | * for most legacy frames I receive indicating that the | ||
2021 | * same frame was received on all three RX chains. | ||
2022 | * | ||
2023 | * I think this field should be removed in favour of a | ||
2024 | * new 802.11n radiotap field "RX chains" that is defined | ||
2025 | * as a bitmask. | ||
2026 | */ | ||
2027 | antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; | ||
2028 | iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4; | ||
2029 | |||
2030 | /* set the preamble flag if appropriate */ | ||
2031 | if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
2032 | iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
2033 | |||
2034 | stats->flag |= RX_FLAG_RADIOTAP; | ||
2035 | } | ||
2036 | |||
2037 | static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) | ||
2038 | { | ||
2039 | /* 0 - mgmt, 1 - cnt, 2 - data */ | ||
2040 | int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; | ||
2041 | priv->rx_stats[idx].cnt++; | ||
2042 | priv->rx_stats[idx].bytes += len; | ||
2043 | } | ||
2044 | |||
2045 | /* | ||
2046 | * returns non-zero if packet should be dropped | ||
2047 | */ | ||
2048 | static int iwl4965_set_decrypted_flag(struct iwl_priv *priv, | ||
2049 | struct ieee80211_hdr *hdr, | ||
2050 | u32 decrypt_res, | ||
2051 | struct ieee80211_rx_status *stats) | ||
2052 | { | ||
2053 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
2054 | |||
2055 | if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) | ||
2056 | return 0; | ||
2057 | |||
2058 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
2059 | return 0; | ||
2060 | |||
2061 | IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); | ||
2062 | switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2063 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2064 | /* The uCode has got a bad phase 1 Key, pushes the packet. | ||
2065 | * Decryption will be done in SW. */ | ||
2066 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2067 | RX_RES_STATUS_BAD_KEY_TTAK) | ||
2068 | break; | ||
2069 | |||
2070 | case RX_RES_STATUS_SEC_TYPE_WEP: | ||
2071 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2072 | RX_RES_STATUS_BAD_ICV_MIC) { | ||
2073 | /* bad ICV, the packet is destroyed since the | ||
2074 | * decryption is inplace, drop it */ | ||
2075 | IWL_DEBUG_RX("Packet destroyed\n"); | ||
2076 | return -1; | ||
2077 | } | ||
2078 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2079 | if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == | ||
2080 | RX_RES_STATUS_DECRYPT_OK) { | ||
2081 | IWL_DEBUG_RX("hw decrypt successfully!!!\n"); | ||
2082 | stats->flag |= RX_FLAG_DECRYPTED; | ||
2083 | } | ||
2084 | break; | ||
2085 | |||
2086 | default: | ||
2087 | break; | ||
2088 | } | ||
2089 | return 0; | ||
2090 | } | ||
2091 | |||
2092 | static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
2093 | { | ||
2094 | u32 decrypt_out = 0; | ||
2095 | |||
2096 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
2097 | RX_RES_STATUS_STATION_FOUND) | ||
2098 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
2099 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
2100 | |||
2101 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
2102 | |||
2103 | /* packet was not encrypted */ | ||
2104 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
2105 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
2106 | return decrypt_out; | ||
2107 | |||
2108 | /* packet was encrypted with unknown alg */ | ||
2109 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
2110 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
2111 | return decrypt_out; | ||
2112 | |||
2113 | /* decryption was not done in HW */ | ||
2114 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
2115 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
2116 | return decrypt_out; | ||
2117 | |||
2118 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
2119 | |||
2120 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
2121 | /* alg is CCM: check MIC only */ | ||
2122 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
2123 | /* Bad MIC */ | ||
2124 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
2125 | else | ||
2126 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
2127 | |||
2128 | break; | ||
2129 | |||
2130 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
2131 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
2132 | /* Bad TTAK */ | ||
2133 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
2134 | break; | ||
2135 | } | ||
2136 | /* fall through if TTAK OK */ | ||
2137 | default: | ||
2138 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
2139 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
2140 | else | ||
2141 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
2142 | break; | ||
2143 | }; | ||
2144 | |||
2145 | IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
2146 | decrypt_in, decrypt_out); | ||
2147 | |||
2148 | return decrypt_out; | ||
2149 | } | ||
2150 | |||
2151 | static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | ||
2152 | int include_phy, | ||
2153 | struct iwl_rx_mem_buffer *rxb, | ||
2154 | struct ieee80211_rx_status *stats) | ||
2155 | { | ||
2156 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
2157 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
2158 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL; | ||
2159 | struct ieee80211_hdr *hdr; | ||
2160 | u16 len; | ||
2161 | __le32 *rx_end; | ||
2162 | unsigned int skblen; | ||
2163 | u32 ampdu_status; | ||
2164 | u32 ampdu_status_legacy; | ||
2165 | |||
2166 | if (!include_phy && priv->last_phy_res[0]) | ||
2167 | rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
2168 | |||
2169 | if (!rx_start) { | ||
2170 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
2171 | return; | ||
2172 | } | ||
2173 | if (include_phy) { | ||
2174 | hdr = (struct ieee80211_hdr *)((u8 *) & rx_start[1] + | ||
2175 | rx_start->cfg_phy_cnt); | ||
2176 | |||
2177 | len = le16_to_cpu(rx_start->byte_count); | ||
2178 | |||
2179 | rx_end = (__le32 *) ((u8 *) & pkt->u.raw[0] + | ||
2180 | sizeof(struct iwl4965_rx_phy_res) + | ||
2181 | rx_start->cfg_phy_cnt + len); | ||
2182 | |||
2183 | } else { | ||
2184 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
2185 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
2186 | |||
2187 | hdr = (struct ieee80211_hdr *)(pkt->u.raw + | ||
2188 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
2189 | len = le16_to_cpu(amsdu->byte_count); | ||
2190 | rx_start->byte_count = amsdu->byte_count; | ||
2191 | rx_end = (__le32 *) (((u8 *) hdr) + len); | ||
2192 | } | ||
2193 | /* In monitor mode allow 802.11 ACk frames (10 bytes) */ | ||
2194 | if (len > priv->hw_params.max_pkt_size || | ||
2195 | len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) { | ||
2196 | IWL_WARNING("byte count out of range [16,4K] : %d\n", len); | ||
2197 | return; | ||
2198 | } | ||
2199 | |||
2200 | ampdu_status = le32_to_cpu(*rx_end); | ||
2201 | skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32); | ||
2202 | |||
2203 | if (!include_phy) { | ||
2204 | /* New status scheme, need to translate */ | ||
2205 | ampdu_status_legacy = ampdu_status; | ||
2206 | ampdu_status = iwl4965_translate_rx_status(priv, ampdu_status); | ||
2207 | } | ||
2208 | |||
2209 | /* start from MAC */ | ||
2210 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); | ||
2211 | skb_put(rxb->skb, len); /* end where data ends */ | ||
2212 | |||
2213 | /* We only process data packets if the interface is open */ | ||
2214 | if (unlikely(!priv->is_open)) { | ||
2215 | IWL_DEBUG_DROP_LIMIT | ||
2216 | ("Dropping packet while interface is not open.\n"); | ||
2217 | return; | ||
2218 | } | ||
2219 | |||
2220 | stats->flag = 0; | ||
2221 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | ||
2222 | |||
2223 | /* in case of HW accelerated crypto and bad decryption, drop */ | ||
2224 | if (!priv->hw_params.sw_crypto && | ||
2225 | iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
2226 | return; | ||
2227 | |||
2228 | if (priv->add_radiotap) | ||
2229 | iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); | ||
2230 | |||
2231 | iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); | ||
2232 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); | ||
2233 | priv->alloc_rxb_skb--; | ||
2234 | rxb->skb = NULL; | ||
2235 | } | ||
2236 | |||
2237 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
2238 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | ||
2239 | struct iwl4965_rx_phy_res *rx_resp) | ||
2240 | { | ||
2241 | /* data from PHY/DSP regarding signal strength, etc., | ||
2242 | * contents are always there, not configurable by host. */ | ||
2243 | struct iwl4965_rx_non_cfg_phy *ncphy = | ||
2244 | (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy; | ||
2245 | u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK) | ||
2246 | >> IWL_AGC_DB_POS; | ||
2247 | |||
2248 | u32 valid_antennae = | ||
2249 | (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) | ||
2250 | >> RX_PHY_FLAGS_ANTENNAE_OFFSET; | ||
2251 | u8 max_rssi = 0; | ||
2252 | u32 i; | ||
2253 | |||
2254 | /* Find max rssi among 3 possible receivers. | ||
2255 | * These values are measured by the digital signal processor (DSP). | ||
2256 | * They should stay fairly constant even as the signal strength varies, | ||
2257 | * if the radio's automatic gain control (AGC) is working right. | ||
2258 | * AGC value (see below) will provide the "interesting" info. */ | ||
2259 | for (i = 0; i < 3; i++) | ||
2260 | if (valid_antennae & (1 << i)) | ||
2261 | max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); | ||
2262 | |||
2263 | IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
2264 | ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], | ||
2265 | max_rssi, agc); | ||
2266 | |||
2267 | /* dBm = max_rssi dB - agc dB - constant. | ||
2268 | * Higher AGC (higher radio gain) means lower signal. */ | ||
2269 | return (max_rssi - agc - IWL_RSSI_OFFSET); | ||
2270 | } | ||
2271 | |||
2272 | static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||
2273 | { | ||
2274 | unsigned long flags; | ||
2275 | |||
2276 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
2277 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | ||
2278 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | ||
2279 | priv->stations[sta_id].sta.sta.modify_mask = 0; | ||
2280 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
2281 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
2282 | |||
2283 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
2284 | } | ||
2285 | |||
2286 | static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | ||
2287 | { | ||
2288 | /* FIXME: need locking over ps_status ??? */ | ||
2289 | u8 sta_id = iwl_find_station(priv, addr); | ||
2290 | |||
2291 | if (sta_id != IWL_INVALID_STATION) { | ||
2292 | u8 sta_awake = priv->stations[sta_id]. | ||
2293 | ps_status == STA_PS_STATUS_WAKE; | ||
2294 | |||
2295 | if (sta_awake && ps_bit) | ||
2296 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
2297 | else if (!sta_awake && !ps_bit) { | ||
2298 | iwl4965_sta_modify_ps_wake(priv, sta_id); | ||
2299 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
2300 | } | ||
2301 | } | ||
2302 | } | ||
2303 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2304 | |||
2305 | /** | ||
2306 | * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions | ||
2307 | * | ||
2308 | * You may hack this function to show different aspects of received frames, | ||
2309 | * including selective frame dumps. | ||
2310 | * group100 parameter selects whether to show 1 out of 100 good frames. | ||
2311 | * | ||
2312 | * TODO: This was originally written for 3945, need to audit for | ||
2313 | * proper operation with 4965. | ||
2314 | */ | ||
2315 | static void iwl4965_dbg_report_frame(struct iwl_priv *priv, | ||
2316 | struct iwl_rx_packet *pkt, | ||
2317 | struct ieee80211_hdr *header, int group100) | ||
2318 | { | ||
2319 | u32 to_us; | ||
2320 | u32 print_summary = 0; | ||
2321 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
2322 | u32 hundred = 0; | ||
2323 | u32 dataframe = 0; | ||
2324 | __le16 fc; | ||
2325 | u16 seq_ctl; | ||
2326 | u16 channel; | ||
2327 | u16 phy_flags; | ||
2328 | int rate_sym; | ||
2329 | u16 length; | ||
2330 | u16 status; | ||
2331 | u16 bcn_tmr; | ||
2332 | u32 tsf_low; | ||
2333 | u64 tsf; | ||
2334 | u8 rssi; | ||
2335 | u8 agc; | ||
2336 | u16 sig_avg; | ||
2337 | u16 noise_diff; | ||
2338 | struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | ||
2339 | struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | ||
2340 | struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); | ||
2341 | u8 *data = IWL_RX_DATA(pkt); | ||
2342 | |||
2343 | if (likely(!(priv->debug_level & IWL_DL_RX))) | ||
2344 | return; | ||
2345 | |||
2346 | /* MAC header */ | ||
2347 | fc = header->frame_control; | ||
2348 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
2349 | |||
2350 | /* metadata */ | ||
2351 | channel = le16_to_cpu(rx_hdr->channel); | ||
2352 | phy_flags = le16_to_cpu(rx_hdr->phy_flags); | ||
2353 | rate_sym = rx_hdr->rate; | ||
2354 | length = le16_to_cpu(rx_hdr->len); | ||
2355 | |||
2356 | /* end-of-frame status and timestamp */ | ||
2357 | status = le32_to_cpu(rx_end->status); | ||
2358 | bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); | ||
2359 | tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; | ||
2360 | tsf = le64_to_cpu(rx_end->timestamp); | ||
2361 | |||
2362 | /* signal statistics */ | ||
2363 | rssi = rx_stats->rssi; | ||
2364 | agc = rx_stats->agc; | ||
2365 | sig_avg = le16_to_cpu(rx_stats->sig_avg); | ||
2366 | noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
2367 | |||
2368 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2369 | |||
2370 | /* if data frame is to us and all is good, | ||
2371 | * (optionally) print summary for only 1 out of every 100 */ | ||
2372 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
2373 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
2374 | dataframe = 1; | ||
2375 | if (!group100) | ||
2376 | print_summary = 1; /* print each frame */ | ||
2377 | else if (priv->framecnt_to_us < 100) { | ||
2378 | priv->framecnt_to_us++; | ||
2379 | print_summary = 0; | ||
2380 | } else { | ||
2381 | priv->framecnt_to_us = 0; | ||
2382 | print_summary = 1; | ||
2383 | hundred = 1; | ||
2384 | } | ||
2385 | } else { | ||
2386 | /* print summary for all other frames */ | ||
2387 | print_summary = 1; | ||
2388 | } | ||
2389 | |||
2390 | if (print_summary) { | ||
2391 | char *title; | ||
2392 | int rate_idx; | ||
2393 | u32 bitrate; | ||
2394 | |||
2395 | if (hundred) | ||
2396 | title = "100Frames"; | ||
2397 | else if (ieee80211_has_retry(fc)) | ||
2398 | title = "Retry"; | ||
2399 | else if (ieee80211_is_assoc_resp(fc)) | ||
2400 | title = "AscRsp"; | ||
2401 | else if (ieee80211_is_reassoc_resp(fc)) | ||
2402 | title = "RasRsp"; | ||
2403 | else if (ieee80211_is_probe_resp(fc)) { | ||
2404 | title = "PrbRsp"; | ||
2405 | print_dump = 1; /* dump frame contents */ | ||
2406 | } else if (ieee80211_is_beacon(fc)) { | ||
2407 | title = "Beacon"; | ||
2408 | print_dump = 1; /* dump frame contents */ | ||
2409 | } else if (ieee80211_is_atim(fc)) | ||
2410 | title = "ATIM"; | ||
2411 | else if (ieee80211_is_auth(fc)) | ||
2412 | title = "Auth"; | ||
2413 | else if (ieee80211_is_deauth(fc)) | ||
2414 | title = "DeAuth"; | ||
2415 | else if (ieee80211_is_disassoc(fc)) | ||
2416 | title = "DisAssoc"; | ||
2417 | else | ||
2418 | title = "Frame"; | ||
2419 | |||
2420 | rate_idx = iwl_hwrate_to_plcp_idx(rate_sym); | ||
2421 | if (unlikely(rate_idx == -1)) | ||
2422 | bitrate = 0; | ||
2423 | else | ||
2424 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
2425 | |||
2426 | /* print frame summary. | ||
2427 | * MAC addresses show just the last byte (for brevity), | ||
2428 | * but you can hack it to show more, if you'd like to. */ | ||
2429 | if (dataframe) | ||
2430 | IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " | ||
2431 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
2432 | title, le16_to_cpu(fc), header->addr1[5], | ||
2433 | length, rssi, channel, bitrate); | ||
2434 | else { | ||
2435 | /* src/dst addresses assume managed mode */ | ||
2436 | IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " | ||
2437 | "src=0x%02x, rssi=%u, tim=%lu usec, " | ||
2438 | "phy=0x%02x, chnl=%d\n", | ||
2439 | title, le16_to_cpu(fc), header->addr1[5], | ||
2440 | header->addr3[5], rssi, | ||
2441 | tsf_low - priv->scan_start_tsf, | ||
2442 | phy_flags, channel); | ||
2443 | } | ||
2444 | } | ||
2445 | if (print_dump) | ||
2446 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | ||
2447 | } | ||
2448 | #else | ||
2449 | static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, | ||
2450 | struct iwl_rx_packet *pkt, | ||
2451 | struct ieee80211_hdr *header, | ||
2452 | int group100) | ||
2453 | { | ||
2454 | } | ||
2455 | #endif | ||
2456 | |||
2457 | |||
2458 | |||
2459 | /* Called for REPLY_RX (legacy ABG frames), or | ||
2460 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
2461 | void iwl4965_rx_reply_rx(struct iwl_priv *priv, | ||
2462 | struct iwl_rx_mem_buffer *rxb) | ||
2463 | { | ||
2464 | struct ieee80211_hdr *header; | ||
2465 | struct ieee80211_rx_status rx_status; | ||
2466 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
2467 | /* Use phy data (Rx signal strength, etc.) contained within | ||
2468 | * this rx packet for legacy frames, | ||
2469 | * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ | ||
2470 | int include_phy = (pkt->hdr.cmd == REPLY_RX); | ||
2471 | struct iwl4965_rx_phy_res *rx_start = (include_phy) ? | ||
2472 | (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : | ||
2473 | (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; | ||
2474 | __le32 *rx_end; | ||
2475 | unsigned int len = 0; | ||
2476 | u16 fc; | ||
2477 | u8 network_packet; | ||
2478 | |||
2479 | rx_status.mactime = le64_to_cpu(rx_start->timestamp); | ||
2480 | rx_status.freq = | ||
2481 | ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); | ||
2482 | rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
2483 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
2484 | rx_status.rate_idx = | ||
2485 | iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); | ||
2486 | if (rx_status.band == IEEE80211_BAND_5GHZ) | ||
2487 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | ||
2488 | |||
2489 | rx_status.antenna = 0; | ||
2490 | rx_status.flag = 0; | ||
2491 | |||
2492 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { | ||
2493 | IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", | ||
2494 | rx_start->cfg_phy_cnt); | ||
2495 | return; | ||
2496 | } | ||
2497 | |||
2498 | if (!include_phy) { | ||
2499 | if (priv->last_phy_res[0]) | ||
2500 | rx_start = (struct iwl4965_rx_phy_res *) | ||
2501 | &priv->last_phy_res[1]; | ||
2502 | else | ||
2503 | rx_start = NULL; | ||
2504 | } | ||
2505 | |||
2506 | if (!rx_start) { | ||
2507 | IWL_ERROR("MPDU frame without a PHY data\n"); | ||
2508 | return; | ||
2509 | } | ||
2510 | |||
2511 | if (include_phy) { | ||
2512 | header = (struct ieee80211_hdr *)((u8 *) & rx_start[1] | ||
2513 | + rx_start->cfg_phy_cnt); | ||
2514 | |||
2515 | len = le16_to_cpu(rx_start->byte_count); | ||
2516 | rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + | ||
2517 | sizeof(struct iwl4965_rx_phy_res) + len); | ||
2518 | } else { | ||
2519 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
2520 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
2521 | |||
2522 | header = (void *)(pkt->u.raw + | ||
2523 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
2524 | len = le16_to_cpu(amsdu->byte_count); | ||
2525 | rx_end = (__le32 *) (pkt->u.raw + | ||
2526 | sizeof(struct iwl4965_rx_mpdu_res_start) + len); | ||
2527 | } | ||
2528 | |||
2529 | if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
2530 | !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
2531 | IWL_DEBUG_RX("Bad CRC or FIFO: 0x%08X.\n", | ||
2532 | le32_to_cpu(*rx_end)); | ||
2533 | return; | ||
2534 | } | ||
2535 | |||
2536 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); | ||
2537 | |||
2538 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
2539 | rx_status.signal = iwl4965_calc_rssi(priv, rx_start); | ||
2540 | |||
2541 | /* Meaningful noise values are available only from beacon statistics, | ||
2542 | * which are gathered only when associated, and indicate noise | ||
2543 | * only for the associated network channel ... | ||
2544 | * Ignore these noise values while scanning (other channels) */ | ||
2545 | if (iwl_is_associated(priv) && | ||
2546 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
2547 | rx_status.noise = priv->last_rx_noise; | ||
2548 | rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, | ||
2549 | rx_status.noise); | ||
2550 | } else { | ||
2551 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
2552 | rx_status.qual = iwl4965_calc_sig_qual(rx_status.signal, 0); | ||
2553 | } | ||
2554 | |||
2555 | /* Reset beacon noise level if not associated. */ | ||
2556 | if (!iwl_is_associated(priv)) | ||
2557 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
2558 | |||
2559 | /* Set "1" to report good data frames in groups of 100 */ | ||
2560 | /* FIXME: need to optimze the call: */ | ||
2561 | iwl4965_dbg_report_frame(priv, pkt, header, 1); | ||
2562 | |||
2563 | IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", | ||
2564 | rx_status.signal, rx_status.noise, rx_status.signal, | ||
2565 | (unsigned long long)rx_status.mactime); | ||
2566 | |||
2567 | |||
2568 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | ||
2569 | iwl4965_handle_data_packet(priv, 1, include_phy, | ||
2570 | rxb, &rx_status); | ||
2571 | return; | ||
2572 | } | ||
2573 | |||
2574 | network_packet = iwl4965_is_network_packet(priv, header); | ||
2575 | if (network_packet) { | ||
2576 | priv->last_rx_rssi = rx_status.signal; | ||
2577 | priv->last_beacon_time = priv->ucode_beacon_time; | ||
2578 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); | ||
2579 | } | ||
2580 | |||
2581 | fc = le16_to_cpu(header->frame_control); | ||
2582 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
2583 | case IEEE80211_FTYPE_MGMT: | ||
2584 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
2585 | iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
2586 | header->addr2); | ||
2587 | iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); | ||
2588 | break; | ||
2589 | |||
2590 | case IEEE80211_FTYPE_CTL: | ||
2591 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
2592 | case IEEE80211_STYPE_BACK_REQ: | ||
2593 | IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); | ||
2594 | iwl4965_handle_data_packet(priv, 0, include_phy, | ||
2595 | rxb, &rx_status); | ||
2596 | break; | ||
2597 | default: | ||
2598 | break; | ||
2599 | } | ||
2600 | break; | ||
2601 | |||
2602 | case IEEE80211_FTYPE_DATA: { | ||
2603 | DECLARE_MAC_BUF(mac1); | ||
2604 | DECLARE_MAC_BUF(mac2); | ||
2605 | DECLARE_MAC_BUF(mac3); | ||
2606 | |||
2607 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
2608 | iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
2609 | header->addr2); | ||
2610 | |||
2611 | if (unlikely(!network_packet)) | ||
2612 | IWL_DEBUG_DROP("Dropping (non network): " | ||
2613 | "%s, %s, %s\n", | ||
2614 | print_mac(mac1, header->addr1), | ||
2615 | print_mac(mac2, header->addr2), | ||
2616 | print_mac(mac3, header->addr3)); | ||
2617 | else if (unlikely(iwl4965_is_duplicate_packet(priv, header))) | ||
2618 | IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", | ||
2619 | print_mac(mac1, header->addr1), | ||
2620 | print_mac(mac2, header->addr2), | ||
2621 | print_mac(mac3, header->addr3)); | ||
2622 | else | ||
2623 | iwl4965_handle_data_packet(priv, 1, include_phy, rxb, | ||
2624 | &rx_status); | ||
2625 | break; | ||
2626 | } | ||
2627 | default: | ||
2628 | break; | ||
2629 | |||
2630 | } | ||
2631 | } | ||
2632 | |||
2633 | /** | 1932 | /** |
2634 | * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack | 1933 | * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack |
2635 | * | 1934 | * |
@@ -3253,7 +2552,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
3253 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2552 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
3254 | { | 2553 | { |
3255 | /* Legacy Rx frames */ | 2554 | /* Legacy Rx frames */ |
3256 | priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; | 2555 | priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; |
3257 | /* Tx response */ | 2556 | /* Tx response */ |
3258 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2557 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
3259 | /* block ack */ | 2558 | /* block ack */ |