aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c148
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c26
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);
846int iwl_init_drv(struct iwl_priv *priv) 846int 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
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 }
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
616static 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
4337static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) 4321static 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