diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 |
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 | ||
949 | static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, | 949 | static 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 | ||
2115 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2118 | static 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 | ||
261 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | 264 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) |
@@ -1533,6 +1536,8 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
1533 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 1536 | void 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 | ||
490 | static int iwl_send_remove_station(struct iwl_priv *priv, | 491 | static 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, | |||
546 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, | 547 | int 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); |
599 | out_err: | 598 | out_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 | */ |
644 | void iwl_restore_stations(struct iwl_priv *priv) | 643 | void 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 | } |
1276 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); | 1283 | EXPORT_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 | } |
1323 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1331 | EXPORT_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 | } |
1339 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | 1347 | EXPORT_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 | } |
1356 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | 1364 | EXPORT_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, | |||
196 | static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | 196 | static 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 | ||
214 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | 215 | static int iwl3945_set_dynamic_key(struct iwl_priv *priv, |