aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2010-05-05 05:26:06 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-05-13 13:44:16 -0400
commit9c5ac091b269912cd30fade987f4bc615ef3be90 (patch)
tree698fe77ad1f144ca1c2e3ba9738946a22253399f /drivers/net
parent94adfaa406420ae035b1b760e3d5015775fe7b7c (diff)
iwlwifi: fix and add missing sta_lock usage
There are a few places where sta_lock is used, but the station information protected by it is accessed outside of the lock. Address this in two ways, if the access won't sleep then just move the access into the lock, if the access can sleep then copy the needed station information to the stack to be accessed without risk of it changing while access in progress. Additionally, a number of other places access station station information without holding the sta_lock, fix those as well. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c56
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c5
7 files changed, 85 insertions, 42 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 0eb0faa9d3cf..5ffbce8f4563 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -946,8 +946,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
946 tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); 946 tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
947} 947}
948 948
949static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, 949static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
950 u16 tx_rate, u8 flags)
951{ 950{
952 unsigned long flags_spin; 951 unsigned long flags_spin;
953 struct iwl_station_entry *station; 952 struct iwl_station_entry *station;
@@ -961,10 +960,9 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
961 station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; 960 station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
962 station->sta.rate_n_flags = cpu_to_le16(tx_rate); 961 station->sta.rate_n_flags = cpu_to_le16(tx_rate);
963 station->sta.mode = STA_CONTROL_MODIFY_MSK; 962 station->sta.mode = STA_CONTROL_MODIFY_MSK;
964 963 iwl_send_add_sta(priv, &station->sta, CMD_ASYNC);
965 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 964 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
966 965
967 iwl_send_add_sta(priv, &station->sta, flags);
968 IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", 966 IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
969 sta_id, tx_rate); 967 sta_id, tx_rate);
970 return sta_id; 968 return sta_id;
@@ -2472,8 +2470,7 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
2472 2470
2473 iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, 2471 iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
2474 (priv->band == IEEE80211_BAND_5GHZ) ? 2472 (priv->band == IEEE80211_BAND_5GHZ) ?
2475 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, 2473 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
2476 CMD_ASYNC);
2477 iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); 2474 iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
2478 2475
2479 return 0; 2476 return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 03b066c7aa3c..ad4d7d11c3b8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2026,6 +2026,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2026 int sta_id; 2026 int sta_id;
2027 int freed; 2027 int freed;
2028 u8 *qc = NULL; 2028 u8 *qc = NULL;
2029 unsigned long flags;
2029 2030
2030 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { 2031 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
2031 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " 2032 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
@@ -2050,10 +2051,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2050 return; 2051 return;
2051 } 2052 }
2052 2053
2054 spin_lock_irqsave(&priv->sta_lock, flags);
2053 if (txq->sched_retry) { 2055 if (txq->sched_retry) {
2054 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); 2056 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
2055 struct iwl_ht_agg *agg = NULL; 2057 struct iwl_ht_agg *agg = NULL;
2056
2057 WARN_ON(!qc); 2058 WARN_ON(!qc);
2058 2059
2059 agg = &priv->stations[sta_id].tid[tid].agg; 2060 agg = &priv->stations[sta_id].tid[tid].agg;
@@ -2110,6 +2111,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2110 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); 2111 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
2111 2112
2112 iwl_check_abort_status(priv, tx_resp->frame_count, status); 2113 iwl_check_abort_status(priv, tx_resp->frame_count, status);
2114
2115 spin_unlock_irqrestore(&priv->sta_lock, flags);
2113} 2116}
2114 2117
2115static int iwl4965_calc_rssi(struct iwl_priv *priv, 2118static int iwl4965_calc_rssi(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 5f07bc2e14e9..4857b5f62481 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -184,6 +184,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
184 int tid; 184 int tid;
185 int sta_id; 185 int sta_id;
186 int freed; 186 int freed;
187 unsigned long flags;
187 188
188 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { 189 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
189 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " 190 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
@@ -199,9 +200,10 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
199 tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; 200 tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
200 sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; 201 sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
201 202
203 spin_lock_irqsave(&priv->sta_lock, flags);
202 if (txq->sched_retry) { 204 if (txq->sched_retry) {
203 const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); 205 const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp);
204 struct iwl_ht_agg *agg = NULL; 206 struct iwl_ht_agg *agg;
205 207
206 agg = &priv->stations[sta_id].tid[tid].agg; 208 agg = &priv->stations[sta_id].tid[tid].agg;
207 209
@@ -256,6 +258,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
256 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); 258 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
257 259
258 iwl_check_abort_status(priv, tx_resp->frame_count, status); 260 iwl_check_abort_status(priv, tx_resp->frame_count, status);
261 spin_unlock_irqrestore(&priv->sta_lock, flags);
259} 262}
260 263
261void iwlagn_rx_handler_setup(struct iwl_priv *priv) 264void iwlagn_rx_handler_setup(struct iwl_priv *priv)
@@ -1533,6 +1536,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
1533void iwl_free_tfds_in_queue(struct iwl_priv *priv, 1536void iwl_free_tfds_in_queue(struct iwl_priv *priv,
1534 int sta_id, int tid, int freed) 1537 int sta_id, int tid, int freed)
1535{ 1538{
1539 WARN_ON(!spin_is_locked(&priv->sta_lock));
1540
1536 if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) 1541 if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
1537 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 1542 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1538 else { 1543 else {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 18b15466fce1..52bec1040467 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -595,11 +595,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
595 } 595 }
596 596
597 txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); 597 txq_id = get_queue_from_ac(skb_get_queue_mapping(skb));
598
599 /* irqs already disabled/saved above when locking priv->lock */
600 spin_lock(&priv->sta_lock);
601
598 if (ieee80211_is_data_qos(fc)) { 602 if (ieee80211_is_data_qos(fc)) {
599 qc = ieee80211_get_qos_ctl(hdr); 603 qc = ieee80211_get_qos_ctl(hdr);
600 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; 604 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
601 if (unlikely(tid >= MAX_TID_COUNT)) 605 if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
606 spin_unlock(&priv->sta_lock);
602 goto drop_unlock; 607 goto drop_unlock;
608 }
603 seq_number = priv->stations[sta_id].tid[tid].seq_number; 609 seq_number = priv->stations[sta_id].tid[tid].seq_number;
604 seq_number &= IEEE80211_SCTL_SEQ; 610 seq_number &= IEEE80211_SCTL_SEQ;
605 hdr->seq_ctrl = hdr->seq_ctrl & 611 hdr->seq_ctrl = hdr->seq_ctrl &
@@ -617,11 +623,18 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
617 swq_id = txq->swq_id; 623 swq_id = txq->swq_id;
618 q = &txq->q; 624 q = &txq->q;
619 625
620 if (unlikely(iwl_queue_space(q) < q->high_mark)) 626 if (unlikely(iwl_queue_space(q) < q->high_mark)) {
627 spin_unlock(&priv->sta_lock);
621 goto drop_unlock; 628 goto drop_unlock;
629 }
622 630
623 if (ieee80211_is_data_qos(fc)) 631 if (ieee80211_is_data_qos(fc)) {
624 priv->stations[sta_id].tid[tid].tfds_in_queue++; 632 priv->stations[sta_id].tid[tid].tfds_in_queue++;
633 if (!ieee80211_has_morefrags(fc))
634 priv->stations[sta_id].tid[tid].seq_number = seq_number;
635 }
636
637 spin_unlock(&priv->sta_lock);
625 638
626 /* Set up driver data for this TFD */ 639 /* Set up driver data for this TFD */
627 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); 640 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
@@ -700,8 +713,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
700 713
701 if (!ieee80211_has_morefrags(hdr->frame_control)) { 714 if (!ieee80211_has_morefrags(hdr->frame_control)) {
702 txq->need_update = 1; 715 txq->need_update = 1;
703 if (qc)
704 priv->stations[sta_id].tid[tid].seq_number = seq_number;
705 } else { 716 } else {
706 wait_write_ptr = 1; 717 wait_write_ptr = 1;
707 txq->need_update = 0; 718 txq->need_update = 0;
@@ -1006,6 +1017,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
1006 if (ret) 1017 if (ret)
1007 return ret; 1018 return ret;
1008 1019
1020 spin_lock_irqsave(&priv->sta_lock, flags);
1021 tid_data = &priv->stations[sta_id].tid[tid];
1009 if (tid_data->tfds_in_queue == 0) { 1022 if (tid_data->tfds_in_queue == 0) {
1010 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1023 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1011 tid_data->agg.state = IWL_AGG_ON; 1024 tid_data->agg.state = IWL_AGG_ON;
@@ -1015,6 +1028,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
1015 tid_data->tfds_in_queue); 1028 tid_data->tfds_in_queue);
1016 tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; 1029 tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
1017 } 1030 }
1031 spin_unlock_irqrestore(&priv->sta_lock, flags);
1018 return ret; 1032 return ret;
1019} 1033}
1020 1034
@@ -1037,11 +1051,14 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1037 return -ENXIO; 1051 return -ENXIO;
1038 } 1052 }
1039 1053
1054 spin_lock_irqsave(&priv->sta_lock, flags);
1055
1040 if (priv->stations[sta_id].tid[tid].agg.state == 1056 if (priv->stations[sta_id].tid[tid].agg.state ==
1041 IWL_EMPTYING_HW_QUEUE_ADDBA) { 1057 IWL_EMPTYING_HW_QUEUE_ADDBA) {
1042 IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); 1058 IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
1043 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1059 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1044 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1060 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1061 spin_unlock_irqrestore(&priv->sta_lock, flags);
1045 return 0; 1062 return 0;
1046 } 1063 }
1047 1064
@@ -1059,13 +1076,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1059 IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); 1076 IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
1060 priv->stations[sta_id].tid[tid].agg.state = 1077 priv->stations[sta_id].tid[tid].agg.state =
1061 IWL_EMPTYING_HW_QUEUE_DELBA; 1078 IWL_EMPTYING_HW_QUEUE_DELBA;
1079 spin_unlock_irqrestore(&priv->sta_lock, flags);
1062 return 0; 1080 return 0;
1063 } 1081 }
1064 1082
1065 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1083 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1066 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1084 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1067 1085
1068 spin_lock_irqsave(&priv->lock, flags); 1086 /* do not restore/save irqs */
1087 spin_unlock(&priv->sta_lock);
1088 spin_lock(&priv->lock);
1089
1069 /* 1090 /*
1070 * the only reason this call can fail is queue number out of range, 1091 * the only reason this call can fail is queue number out of range,
1071 * which can happen if uCode is reloaded and all the station 1092 * which can happen if uCode is reloaded and all the station
@@ -1089,6 +1110,8 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1089 u8 *addr = priv->stations[sta_id].sta.sta.addr; 1110 u8 *addr = priv->stations[sta_id].sta.sta.addr;
1090 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; 1111 struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
1091 1112
1113 WARN_ON(!spin_is_locked(&priv->sta_lock));
1114
1092 switch (priv->stations[sta_id].tid[tid].agg.state) { 1115 switch (priv->stations[sta_id].tid[tid].agg.state) {
1093 case IWL_EMPTYING_HW_QUEUE_DELBA: 1116 case IWL_EMPTYING_HW_QUEUE_DELBA:
1094 /* We are reclaiming the last packet of the */ 1117 /* We are reclaiming the last packet of the */
@@ -1113,6 +1136,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
1113 } 1136 }
1114 break; 1137 break;
1115 } 1138 }
1139
1116 return 0; 1140 return 0;
1117} 1141}
1118 1142
@@ -1276,6 +1300,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1276 int index; 1300 int index;
1277 int sta_id; 1301 int sta_id;
1278 int tid; 1302 int tid;
1303 unsigned long flags;
1279 1304
1280 /* "flow" corresponds to Tx queue */ 1305 /* "flow" corresponds to Tx queue */
1281 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); 1306 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
@@ -1298,7 +1323,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1298 /* Find index just before block-ack window */ 1323 /* Find index just before block-ack window */
1299 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); 1324 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
1300 1325
1301 /* TODO: Need to get this copy more safely - now good for debug */ 1326 spin_lock_irqsave(&priv->sta_lock, flags);
1302 1327
1303 IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " 1328 IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
1304 "sta_id = %d\n", 1329 "sta_id = %d\n",
@@ -1334,4 +1359,6 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
1334 1359
1335 iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); 1360 iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow);
1336 } 1361 }
1362
1363 spin_unlock_irqrestore(&priv->sta_lock, flags);
1337} 1364}
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 8538af788a73..5ac03f5a4713 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1224,7 +1224,9 @@ struct iwl_priv {
1224 u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */ 1224 u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
1225 u8 mac_addr[ETH_ALEN]; 1225 u8 mac_addr[ETH_ALEN];
1226 1226
1227 /*station table variables */ 1227 /* station table variables */
1228
1229 /* Note: if lock and sta_lock are needed, lock must be acquired first */
1228 spinlock_t sta_lock; 1230 spinlock_t sta_lock;
1229 int num_stations; 1231 int num_stations;
1230 struct iwl_station_entry stations[IWL_STATION_COUNT]; 1232 struct iwl_station_entry stations[IWL_STATION_COUNT];
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 2eafba60053b..4d878d8cbbee 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -311,10 +311,10 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
311 struct ieee80211_sta_ht_cap *ht_info, 311 struct ieee80211_sta_ht_cap *ht_info,
312 u8 *sta_id_r) 312 u8 *sta_id_r)
313{ 313{
314 struct iwl_station_entry *station;
315 unsigned long flags_spin; 314 unsigned long flags_spin;
316 int ret = 0; 315 int ret = 0;
317 u8 sta_id; 316 u8 sta_id;
317 struct iwl_addsta_cmd sta_cmd;
318 318
319 *sta_id_r = 0; 319 *sta_id_r = 0;
320 spin_lock_irqsave(&priv->sta_lock, flags_spin); 320 spin_lock_irqsave(&priv->sta_lock, flags_spin);
@@ -347,14 +347,15 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
347 } 347 }
348 348
349 priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; 349 priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
350 station = &priv->stations[sta_id]; 350 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
351 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 351 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
352 352
353 /* Add station to device's station table */ 353 /* Add station to device's station table */
354 ret = iwl_send_add_sta(priv, &station->sta, CMD_SYNC); 354 ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
355 if (ret) { 355 if (ret) {
356 IWL_ERR(priv, "Adding station %pM failed.\n", station->sta.sta.addr);
357 spin_lock_irqsave(&priv->sta_lock, flags_spin); 356 spin_lock_irqsave(&priv->sta_lock, flags_spin);
357 IWL_ERR(priv, "Adding station %pM failed.\n",
358 priv->stations[sta_id].sta.sta.addr);
358 priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; 359 priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
359 priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; 360 priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
360 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 361 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
@@ -488,7 +489,7 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
488} 489}
489 490
490static int iwl_send_remove_station(struct iwl_priv *priv, 491static int iwl_send_remove_station(struct iwl_priv *priv,
491 struct iwl_station_entry *station) 492 const u8 *addr, int sta_id)
492{ 493{
493 struct iwl_rx_packet *pkt; 494 struct iwl_rx_packet *pkt;
494 int ret; 495 int ret;
@@ -505,7 +506,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
505 506
506 memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); 507 memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
507 rm_sta_cmd.num_sta = 1; 508 rm_sta_cmd.num_sta = 1;
508 memcpy(&rm_sta_cmd.addr, &station->sta.sta.addr , ETH_ALEN); 509 memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
509 510
510 cmd.flags |= CMD_WANT_SKB; 511 cmd.flags |= CMD_WANT_SKB;
511 512
@@ -525,7 +526,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
525 switch (pkt->u.rem_sta.status) { 526 switch (pkt->u.rem_sta.status) {
526 case REM_STA_SUCCESS_MSK: 527 case REM_STA_SUCCESS_MSK:
527 spin_lock_irqsave(&priv->sta_lock, flags_spin); 528 spin_lock_irqsave(&priv->sta_lock, flags_spin);
528 iwl_sta_ucode_deactivate(priv, station->sta.sta.sta_id); 529 iwl_sta_ucode_deactivate(priv, sta_id);
529 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 530 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
530 IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); 531 IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
531 break; 532 break;
@@ -546,7 +547,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
546int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, 547int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
547 const u8 *addr) 548 const u8 *addr)
548{ 549{
549 struct iwl_station_entry *station;
550 unsigned long flags; 550 unsigned long flags;
551 551
552 if (!iwl_is_ready(priv)) { 552 if (!iwl_is_ready(priv)) {
@@ -592,10 +592,9 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
592 592
593 BUG_ON(priv->num_stations < 0); 593 BUG_ON(priv->num_stations < 0);
594 594
595 station = &priv->stations[sta_id];
596 spin_unlock_irqrestore(&priv->sta_lock, flags); 595 spin_unlock_irqrestore(&priv->sta_lock, flags);
597 596
598 return iwl_send_remove_station(priv, station); 597 return iwl_send_remove_station(priv, addr, sta_id);
599out_err: 598out_err:
600 spin_unlock_irqrestore(&priv->sta_lock, flags); 599 spin_unlock_irqrestore(&priv->sta_lock, flags);
601 return -EINVAL; 600 return -EINVAL;
@@ -643,11 +642,13 @@ EXPORT_SYMBOL(iwl_clear_ucode_stations);
643 */ 642 */
644void iwl_restore_stations(struct iwl_priv *priv) 643void iwl_restore_stations(struct iwl_priv *priv)
645{ 644{
646 struct iwl_station_entry *station; 645 struct iwl_addsta_cmd sta_cmd;
646 struct iwl_link_quality_cmd lq;
647 unsigned long flags_spin; 647 unsigned long flags_spin;
648 int i; 648 int i;
649 bool found = false; 649 bool found = false;
650 int ret; 650 int ret;
651 bool send_lq;
651 652
652 if (!iwl_is_ready(priv)) { 653 if (!iwl_is_ready(priv)) {
653 IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n"); 654 IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
@@ -669,13 +670,20 @@ void iwl_restore_stations(struct iwl_priv *priv)
669 670
670 for (i = 0; i < priv->hw_params.max_stations; i++) { 671 for (i = 0; i < priv->hw_params.max_stations; i++) {
671 if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) { 672 if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
673 memcpy(&sta_cmd, &priv->stations[i].sta,
674 sizeof(struct iwl_addsta_cmd));
675 send_lq = false;
676 if (priv->stations[i].lq) {
677 memcpy(&lq, priv->stations[i].lq,
678 sizeof(struct iwl_link_quality_cmd));
679 send_lq = true;
680 }
672 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 681 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
673 station = &priv->stations[i]; 682 ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
674 ret = iwl_send_add_sta(priv, &priv->stations[i].sta, CMD_SYNC);
675 if (ret) { 683 if (ret) {
676 IWL_ERR(priv, "Adding station %pM failed.\n",
677 station->sta.sta.addr);
678 spin_lock_irqsave(&priv->sta_lock, flags_spin); 684 spin_lock_irqsave(&priv->sta_lock, flags_spin);
685 IWL_ERR(priv, "Adding station %pM failed.\n",
686 priv->stations[i].sta.sta.addr);
679 priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE; 687 priv->stations[i].used &= ~IWL_STA_DRIVER_ACTIVE;
680 priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; 688 priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
681 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 689 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
@@ -684,8 +692,8 @@ void iwl_restore_stations(struct iwl_priv *priv)
684 * Rate scaling has already been initialized, send 692 * Rate scaling has already been initialized, send
685 * current LQ command 693 * current LQ command
686 */ 694 */
687 if (station->lq) 695 if (send_lq)
688 iwl_send_lq_cmd(priv, station->lq, CMD_SYNC, true); 696 iwl_send_lq_cmd(priv, &lq, CMD_SYNC, true);
689 spin_lock_irqsave(&priv->sta_lock, flags_spin); 697 spin_lock_irqsave(&priv->sta_lock, flags_spin);
690 priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS; 698 priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
691 } 699 }
@@ -1269,9 +1277,8 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
1269 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; 1277 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
1270 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); 1278 priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
1271 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1279 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1272 spin_unlock_irqrestore(&priv->sta_lock, flags);
1273
1274 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); 1280 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1281 spin_unlock_irqrestore(&priv->sta_lock, flags);
1275} 1282}
1276EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); 1283EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
1277 1284
@@ -1302,7 +1309,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1302 int tid) 1309 int tid)
1303{ 1310{
1304 unsigned long flags; 1311 unsigned long flags;
1305 int sta_id; 1312 int sta_id, ret;
1306 1313
1307 sta_id = iwl_sta_id(sta); 1314 sta_id = iwl_sta_id(sta);
1308 if (sta_id == IWL_INVALID_STATION) { 1315 if (sta_id == IWL_INVALID_STATION) {
@@ -1315,10 +1322,11 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
1315 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; 1322 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
1316 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; 1323 priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
1317 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1324 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1325 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1318 spin_unlock_irqrestore(&priv->sta_lock, flags); 1326 spin_unlock_irqrestore(&priv->sta_lock, flags);
1319 1327
1320 return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 1328 return ret;
1321 CMD_ASYNC); 1329
1322} 1330}
1323EXPORT_SYMBOL(iwl_sta_rx_agg_stop); 1331EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
1324 1332
@@ -1332,9 +1340,9 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
1332 priv->stations[sta_id].sta.sta.modify_mask = 0; 1340 priv->stations[sta_id].sta.sta.modify_mask = 0;
1333 priv->stations[sta_id].sta.sleep_tx_count = 0; 1341 priv->stations[sta_id].sta.sleep_tx_count = 0;
1334 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1342 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1343 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1335 spin_unlock_irqrestore(&priv->sta_lock, flags); 1344 spin_unlock_irqrestore(&priv->sta_lock, flags);
1336 1345
1337 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1338} 1346}
1339EXPORT_SYMBOL(iwl_sta_modify_ps_wake); 1347EXPORT_SYMBOL(iwl_sta_modify_ps_wake);
1340 1348
@@ -1349,9 +1357,9 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
1349 STA_MODIFY_SLEEP_TX_COUNT_MSK; 1357 STA_MODIFY_SLEEP_TX_COUNT_MSK;
1350 priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); 1358 priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
1351 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 1359 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
1360 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1352 spin_unlock_irqrestore(&priv->sta_lock, flags); 1361 spin_unlock_irqrestore(&priv->sta_lock, flags);
1353 1362
1354 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
1355} 1363}
1356EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); 1364EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
1357 1365
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 445406406bd0..82beeb5a2af9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -196,6 +196,7 @@ static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
196static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) 196static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
197{ 197{
198 unsigned long flags; 198 unsigned long flags;
199 struct iwl_addsta_cmd sta_cmd;
199 200
200 spin_lock_irqsave(&priv->sta_lock, flags); 201 spin_lock_irqsave(&priv->sta_lock, flags);
201 memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); 202 memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
@@ -204,11 +205,11 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
204 priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; 205 priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
205 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; 206 priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
206 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 207 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
208 memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
207 spin_unlock_irqrestore(&priv->sta_lock, flags); 209 spin_unlock_irqrestore(&priv->sta_lock, flags);
208 210
209 IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); 211 IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
210 iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); 212 return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
211 return 0;
212} 213}
213 214
214static int iwl3945_set_dynamic_key(struct iwl_priv *priv, 215static int iwl3945_set_dynamic_key(struct iwl_priv *priv,