diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-06-30 05:23:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-30 17:37:40 -0400 |
commit | 4b8817b2a06958efd868677880334229fe5a96cf (patch) | |
tree | 1a9cef9b89433fccecaeba54d64025cb617baa75 /drivers | |
parent | 1781a07fbe9cce3dc1697288a5edd260ea7edc02 (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')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 148 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 26 |
4 files changed, 13 insertions, 173 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6ca946051b82..95f7320fc9dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -846,7 +846,6 @@ EXPORT_SYMBOL(iwl_setup_mac); | |||
846 | int iwl_init_drv(struct iwl_priv *priv) | 846 | int iwl_init_drv(struct iwl_priv *priv) |
847 | { | 847 | { |
848 | int ret; | 848 | int ret; |
849 | int i; | ||
850 | 849 | ||
851 | priv->retry_rate = 1; | 850 | priv->retry_rate = 1; |
852 | priv->ibss_beacon = NULL; | 851 | priv->ibss_beacon = NULL; |
@@ -857,9 +856,6 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
857 | spin_lock_init(&priv->hcmd_lock); | 856 | spin_lock_init(&priv->hcmd_lock); |
858 | spin_lock_init(&priv->lq_mngr.lock); | 857 | spin_lock_init(&priv->lq_mngr.lock); |
859 | 858 | ||
860 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) | ||
861 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | ||
862 | |||
863 | INIT_LIST_HEAD(&priv->free_frames); | 859 | INIT_LIST_HEAD(&priv->free_frames); |
864 | 860 | ||
865 | mutex_init(&priv->mutex); | 861 | mutex_init(&priv->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8017e57dc148..79a6941be5ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1017,14 +1017,6 @@ struct iwl_priv { | |||
1017 | u32 last_beacon_time; | 1017 | u32 last_beacon_time; |
1018 | u64 last_tsf; | 1018 | u64 last_tsf; |
1019 | 1019 | ||
1020 | /* Duplicate packet detection */ | ||
1021 | u16 last_seq_num; | ||
1022 | u16 last_frag_num; | ||
1023 | unsigned long last_packet_time; | ||
1024 | |||
1025 | /* Hash table for finding stations in IBSS network */ | ||
1026 | struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; | ||
1027 | |||
1028 | /* eeprom */ | 1020 | /* eeprom */ |
1029 | u8 *eeprom; | 1021 | u8 *eeprom; |
1030 | struct iwl_eeprom_calib_info *calib_info; | 1022 | struct iwl_eeprom_calib_info *calib_info; |
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 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 499705ff8887..4129e90f360a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -613,20 +613,6 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) | |||
613 | } | 613 | } |
614 | } | 614 | } |
615 | 615 | ||
616 | static void iwl4965_sequence_reset(struct iwl_priv *priv) | ||
617 | { | ||
618 | /* Reset ieee stats */ | ||
619 | |||
620 | /* We don't reset the net_device_stats (ieee->stats) on | ||
621 | * re-association */ | ||
622 | |||
623 | priv->last_seq_num = -1; | ||
624 | priv->last_frag_num = -1; | ||
625 | priv->last_packet_time = 0; | ||
626 | |||
627 | iwl_scan_cancel(priv); | ||
628 | } | ||
629 | |||
630 | #define MAX_UCODE_BEACON_INTERVAL 4096 | 616 | #define MAX_UCODE_BEACON_INTERVAL 4096 |
631 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) | 617 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) |
632 | 618 | ||
@@ -2515,8 +2501,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2515 | break; | 2501 | break; |
2516 | } | 2502 | } |
2517 | 2503 | ||
2518 | iwl4965_sequence_reset(priv); | ||
2519 | |||
2520 | /* Enable Rx differential gain and sensitivity calibrations */ | 2504 | /* Enable Rx differential gain and sensitivity calibrations */ |
2521 | iwl_chain_noise_reset(priv); | 2505 | iwl_chain_noise_reset(priv); |
2522 | priv->start_calib = 1; | 2506 | priv->start_calib = 1; |
@@ -4337,8 +4321,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4337 | static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | 4321 | static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) |
4338 | { | 4322 | { |
4339 | struct iwl_priv *priv = pci_get_drvdata(pdev); | 4323 | struct iwl_priv *priv = pci_get_drvdata(pdev); |
4340 | struct list_head *p, *q; | ||
4341 | int i; | ||
4342 | unsigned long flags; | 4324 | unsigned long flags; |
4343 | 4325 | ||
4344 | if (!priv) | 4326 | if (!priv) |
@@ -4367,14 +4349,6 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | |||
4367 | 4349 | ||
4368 | iwl_synchronize_irq(priv); | 4350 | iwl_synchronize_irq(priv); |
4369 | 4351 | ||
4370 | /* Free MAC hash list for ADHOC */ | ||
4371 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { | ||
4372 | list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { | ||
4373 | list_del(p); | ||
4374 | kfree(list_entry(p, struct iwl4965_ibss_seq, list)); | ||
4375 | } | ||
4376 | } | ||
4377 | |||
4378 | iwl_rfkill_unregister(priv); | 4352 | iwl_rfkill_unregister(priv); |
4379 | iwl4965_dealloc_ucode_pci(priv); | 4353 | iwl4965_dealloc_ucode_pci(priv); |
4380 | 4354 | ||