aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-rx.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-06-30 05:23:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-30 17:37:40 -0400
commit4b8817b2a06958efd868677880334229fe5a96cf (patch)
tree1a9cef9b89433fccecaeba54d64025cb617baa75 /drivers/net/wireless/iwlwifi/iwl-rx.c
parent1781a07fbe9cce3dc1697288a5edd260ea7edc02 (diff)
iwlwifi: remove useless network and duplicate checking
The iwlwifi drivers go to great lengths to avoid passing packets to mac80211 they think shouldn't go there, while mac80211 can (of course!) handle them very well. Especially in the case of duplicate packets this is interesting because it's such a performance hog (especially for IBSS networks) while mac80211 does that work on the side without much effort. This patch removes all that and leaves only what is absolutely necessary for the hardware. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> 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-rx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c148
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
960static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data, 960static 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
1115static 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
1180static int iwl_is_network_packet(struct iwl_priv *priv, 1108static 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 }