diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 148 |
1 files changed, 13 insertions, 135 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index e0d3e2dd1d82..9c346cc9476c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -957,7 +957,7 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | |||
957 | return decrypt_out; | 957 | return decrypt_out; |
958 | } | 958 | } |
959 | 959 | ||
960 | static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data, | 960 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, |
961 | int include_phy, | 961 | int include_phy, |
962 | struct iwl_rx_mem_buffer *rxb, | 962 | struct iwl_rx_mem_buffer *rxb, |
963 | struct ieee80211_rx_status *stats) | 963 | struct ieee80211_rx_status *stats) |
@@ -999,12 +999,6 @@ static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
999 | rx_start->byte_count = amsdu->byte_count; | 999 | rx_start->byte_count = amsdu->byte_count; |
1000 | rx_end = (__le32 *) (((u8 *) hdr) + len); | 1000 | rx_end = (__le32 *) (((u8 *) hdr) + len); |
1001 | } | 1001 | } |
1002 | /* In monitor mode allow 802.11 ACk frames (10 bytes) */ | ||
1003 | if (len > priv->hw_params.max_pkt_size || | ||
1004 | len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) { | ||
1005 | IWL_WARNING("byte count out of range [16,4K] : %d\n", len); | ||
1006 | return; | ||
1007 | } | ||
1008 | 1002 | ||
1009 | ampdu_status = le32_to_cpu(*rx_end); | 1003 | ampdu_status = le32_to_cpu(*rx_end); |
1010 | skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32); | 1004 | skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32); |
@@ -1110,73 +1104,7 @@ static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | |||
1110 | } | 1104 | } |
1111 | } | 1105 | } |
1112 | 1106 | ||
1113 | #define IWL_PACKET_RETRY_TIME HZ | 1107 | /* This is necessary only for a number of statistics, see the caller. */ |
1114 | |||
1115 | static int iwl_is_duplicate_packet(struct iwl_priv *priv, | ||
1116 | struct ieee80211_hdr *header) | ||
1117 | { | ||
1118 | u16 sc = le16_to_cpu(header->seq_ctrl); | ||
1119 | u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
1120 | u16 frag = sc & IEEE80211_SCTL_FRAG; | ||
1121 | u16 *last_seq, *last_frag; | ||
1122 | unsigned long *last_time; | ||
1123 | |||
1124 | switch (priv->iw_mode) { | ||
1125 | case IEEE80211_IF_TYPE_IBSS:{ | ||
1126 | struct list_head *p; | ||
1127 | struct iwl4965_ibss_seq *entry = NULL; | ||
1128 | u8 *mac = header->addr2; | ||
1129 | int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); | ||
1130 | |||
1131 | __list_for_each(p, &priv->ibss_mac_hash[index]) { | ||
1132 | entry = list_entry(p, struct iwl4965_ibss_seq, list); | ||
1133 | if (!compare_ether_addr(entry->mac, mac)) | ||
1134 | break; | ||
1135 | } | ||
1136 | if (p == &priv->ibss_mac_hash[index]) { | ||
1137 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | ||
1138 | if (!entry) { | ||
1139 | IWL_ERROR("Cannot malloc new mac entry\n"); | ||
1140 | return 0; | ||
1141 | } | ||
1142 | memcpy(entry->mac, mac, ETH_ALEN); | ||
1143 | entry->seq_num = seq; | ||
1144 | entry->frag_num = frag; | ||
1145 | entry->packet_time = jiffies; | ||
1146 | list_add(&entry->list, &priv->ibss_mac_hash[index]); | ||
1147 | return 0; | ||
1148 | } | ||
1149 | last_seq = &entry->seq_num; | ||
1150 | last_frag = &entry->frag_num; | ||
1151 | last_time = &entry->packet_time; | ||
1152 | break; | ||
1153 | } | ||
1154 | case IEEE80211_IF_TYPE_STA: | ||
1155 | last_seq = &priv->last_seq_num; | ||
1156 | last_frag = &priv->last_frag_num; | ||
1157 | last_time = &priv->last_packet_time; | ||
1158 | break; | ||
1159 | default: | ||
1160 | return 0; | ||
1161 | } | ||
1162 | if ((*last_seq == seq) && | ||
1163 | time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { | ||
1164 | if (*last_frag == frag) | ||
1165 | goto drop; | ||
1166 | if (*last_frag + 1 != frag) | ||
1167 | /* out-of-order fragment */ | ||
1168 | goto drop; | ||
1169 | } else | ||
1170 | *last_seq = seq; | ||
1171 | |||
1172 | *last_frag = frag; | ||
1173 | *last_time = jiffies; | ||
1174 | return 0; | ||
1175 | |||
1176 | drop: | ||
1177 | return 1; | ||
1178 | } | ||
1179 | |||
1180 | static int iwl_is_network_packet(struct iwl_priv *priv, | 1108 | static int iwl_is_network_packet(struct iwl_priv *priv, |
1181 | struct ieee80211_hdr *header) | 1109 | struct ieee80211_hdr *header) |
1182 | { | 1110 | { |
@@ -1184,28 +1112,14 @@ static int iwl_is_network_packet(struct iwl_priv *priv, | |||
1184 | * this network, discarding packets coming from ourselves */ | 1112 | * this network, discarding packets coming from ourselves */ |
1185 | switch (priv->iw_mode) { | 1113 | switch (priv->iw_mode) { |
1186 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | 1114 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ |
1187 | /* packets from our adapter are dropped (echo) */ | 1115 | /* packets to our IBSS update information */ |
1188 | if (!compare_ether_addr(header->addr2, priv->mac_addr)) | 1116 | return !compare_ether_addr(header->addr3, priv->bssid); |
1189 | return 0; | ||
1190 | /* {broad,multi}cast packets to our IBSS go through */ | ||
1191 | if (is_multicast_ether_addr(header->addr1)) | ||
1192 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
1193 | /* packets to our adapter go through */ | ||
1194 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
1195 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | 1117 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ |
1196 | /* packets from our adapter are dropped (echo) */ | 1118 | /* packets to our IBSS update information */ |
1197 | if (!compare_ether_addr(header->addr3, priv->mac_addr)) | 1119 | return !compare_ether_addr(header->addr2, priv->bssid); |
1198 | return 0; | ||
1199 | /* {broad,multi}cast packets to our BSS go through */ | ||
1200 | if (is_multicast_ether_addr(header->addr1)) | ||
1201 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
1202 | /* packets to our adapter go through */ | ||
1203 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
1204 | default: | 1120 | default: |
1205 | break; | 1121 | return 1; |
1206 | } | 1122 | } |
1207 | |||
1208 | return 1; | ||
1209 | } | 1123 | } |
1210 | 1124 | ||
1211 | /* Called for REPLY_RX (legacy ABG frames), or | 1125 | /* Called for REPLY_RX (legacy ABG frames), or |
@@ -1316,9 +1230,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1316 | rx_status.signal, rx_status.noise, rx_status.signal, | 1230 | rx_status.signal, rx_status.noise, rx_status.signal, |
1317 | (unsigned long long)rx_status.mactime); | 1231 | (unsigned long long)rx_status.mactime); |
1318 | 1232 | ||
1319 | 1233 | /* Take shortcut when only in monitor mode */ | |
1320 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | 1234 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { |
1321 | iwl_handle_data_packet(priv, 1, include_phy, | 1235 | iwl_pass_packet_to_mac80211(priv, include_phy, |
1322 | rxb, &rx_status); | 1236 | rxb, &rx_status); |
1323 | return; | 1237 | return; |
1324 | } | 1238 | } |
@@ -1333,50 +1247,14 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1333 | fc = le16_to_cpu(header->frame_control); | 1247 | fc = le16_to_cpu(header->frame_control); |
1334 | switch (fc & IEEE80211_FCTL_FTYPE) { | 1248 | switch (fc & IEEE80211_FCTL_FTYPE) { |
1335 | case IEEE80211_FTYPE_MGMT: | 1249 | case IEEE80211_FTYPE_MGMT: |
1250 | case IEEE80211_FTYPE_DATA: | ||
1336 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | 1251 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) |
1337 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | 1252 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, |
1338 | header->addr2); | 1253 | header->addr2); |
1339 | iwl_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); | 1254 | /* fall through */ |
1340 | break; | ||
1341 | |||
1342 | case IEEE80211_FTYPE_CTL: | ||
1343 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1344 | case IEEE80211_STYPE_BACK_REQ: | ||
1345 | IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); | ||
1346 | iwl_handle_data_packet(priv, 0, include_phy, | ||
1347 | rxb, &rx_status); | ||
1348 | break; | ||
1349 | default: | ||
1350 | break; | ||
1351 | } | ||
1352 | break; | ||
1353 | |||
1354 | case IEEE80211_FTYPE_DATA: { | ||
1355 | DECLARE_MAC_BUF(mac1); | ||
1356 | DECLARE_MAC_BUF(mac2); | ||
1357 | DECLARE_MAC_BUF(mac3); | ||
1358 | |||
1359 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | ||
1360 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
1361 | header->addr2); | ||
1362 | |||
1363 | if (unlikely(!network_packet)) | ||
1364 | IWL_DEBUG_DROP("Dropping (non network): " | ||
1365 | "%s, %s, %s\n", | ||
1366 | print_mac(mac1, header->addr1), | ||
1367 | print_mac(mac2, header->addr2), | ||
1368 | print_mac(mac3, header->addr3)); | ||
1369 | else if (unlikely(iwl_is_duplicate_packet(priv, header))) | ||
1370 | IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", | ||
1371 | print_mac(mac1, header->addr1), | ||
1372 | print_mac(mac2, header->addr2), | ||
1373 | print_mac(mac3, header->addr3)); | ||
1374 | else | ||
1375 | iwl_handle_data_packet(priv, 1, include_phy, rxb, | ||
1376 | &rx_status); | ||
1377 | break; | ||
1378 | } | ||
1379 | default: | 1255 | default: |
1256 | iwl_pass_packet_to_mac80211(priv, include_phy, rxb, | ||
1257 | &rx_status); | ||
1380 | break; | 1258 | break; |
1381 | 1259 | ||
1382 | } | 1260 | } |