diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/iwlwifi/iwl-sta.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 298 |
1 files changed, 197 insertions, 101 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c6633fec8216..4a6686fa6b36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | * | 2 | * |
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | 3 | * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. |
4 | * | 4 | * |
5 | * Portions of this file are derived from the ipw3945 project, as well | 5 | * Portions of this file are derived from the ipw3945 project, as well |
6 | * as portions of the ieee80211 subsystem header files. | 6 | * as portions of the ieee80211 subsystem header files. |
@@ -80,59 +80,109 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
80 | } | 80 | } |
81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | 81 | EXPORT_SYMBOL(iwl_get_ra_sta_id); |
82 | 82 | ||
83 | /* priv->sta_lock must be held */ | ||
83 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 84 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
84 | { | 85 | { |
85 | unsigned long flags; | ||
86 | |||
87 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
88 | 86 | ||
89 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) | 87 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) |
90 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", | 88 | IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n", |
91 | sta_id); | 89 | sta_id, priv->stations[sta_id].sta.sta.addr); |
92 | |||
93 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
94 | IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", | ||
95 | priv->stations[sta_id].sta.sta.addr); | ||
96 | 90 | ||
97 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 91 | if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) { |
92 | IWL_DEBUG_ASSOC(priv, | ||
93 | "STA id %u addr %pM already present in uCode (according to driver)\n", | ||
94 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
95 | } else { | ||
96 | priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; | ||
97 | IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", | ||
98 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
99 | } | ||
98 | } | 100 | } |
99 | 101 | ||
100 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 102 | static void iwl_process_add_sta_resp(struct iwl_priv *priv, |
101 | struct iwl_device_cmd *cmd, | 103 | struct iwl_addsta_cmd *addsta, |
102 | struct sk_buff *skb) | 104 | struct iwl_rx_packet *pkt, |
105 | bool sync) | ||
103 | { | 106 | { |
104 | struct iwl_rx_packet *res = NULL; | ||
105 | struct iwl_addsta_cmd *addsta = | ||
106 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
107 | u8 sta_id = addsta->sta.sta_id; | 107 | u8 sta_id = addsta->sta.sta_id; |
108 | unsigned long flags; | ||
108 | 109 | ||
109 | if (!skb) { | 110 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
110 | IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | res = (struct iwl_rx_packet *)skb->data; | ||
115 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
116 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 111 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
117 | res->hdr.flags); | 112 | pkt->hdr.flags); |
118 | return; | 113 | return; |
119 | } | 114 | } |
120 | 115 | ||
121 | switch (res->u.add_sta.status) { | 116 | IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", |
117 | sta_id); | ||
118 | |||
119 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
120 | |||
121 | switch (pkt->u.add_sta.status) { | ||
122 | case ADD_STA_SUCCESS_MSK: | 122 | case ADD_STA_SUCCESS_MSK: |
123 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
123 | iwl_sta_ucode_activate(priv, sta_id); | 124 | iwl_sta_ucode_activate(priv, sta_id); |
124 | /* fall through */ | 125 | break; |
126 | case ADD_STA_NO_ROOM_IN_TABLE: | ||
127 | IWL_ERR(priv, "Adding station %d failed, no room in table.\n", | ||
128 | sta_id); | ||
129 | break; | ||
130 | case ADD_STA_NO_BLOCK_ACK_RESOURCE: | ||
131 | IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n", | ||
132 | sta_id); | ||
133 | break; | ||
134 | case ADD_STA_MODIFY_NON_EXIST_STA: | ||
135 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | ||
136 | sta_id); | ||
137 | break; | ||
125 | default: | 138 | default: |
126 | IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", | 139 | IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", |
127 | res->u.add_sta.status); | 140 | pkt->u.add_sta.status); |
128 | break; | 141 | break; |
129 | } | 142 | } |
143 | |||
144 | IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n", | ||
145 | priv->stations[sta_id].sta.mode == | ||
146 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
147 | sta_id, priv->stations[sta_id].sta.sta.addr); | ||
148 | |||
149 | /* | ||
150 | * XXX: The MAC address in the command buffer is often changed from | ||
151 | * the original sent to the device. That is, the MAC address | ||
152 | * written to the command buffer often is not the same MAC adress | ||
153 | * read from the command buffer when the command returns. This | ||
154 | * issue has not yet been resolved and this debugging is left to | ||
155 | * observe the problem. | ||
156 | */ | ||
157 | IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n", | ||
158 | priv->stations[sta_id].sta.mode == | ||
159 | STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", | ||
160 | addsta->sta.addr); | ||
161 | |||
162 | /* | ||
163 | * Determine if we wanted to modify or add a station, | ||
164 | * if adding a station succeeded we have some more initialization | ||
165 | * to do when using station notification. TODO | ||
166 | */ | ||
167 | |||
168 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
169 | } | ||
170 | |||
171 | static void iwl_add_sta_callback(struct iwl_priv *priv, | ||
172 | struct iwl_device_cmd *cmd, | ||
173 | struct iwl_rx_packet *pkt) | ||
174 | { | ||
175 | struct iwl_addsta_cmd *addsta = | ||
176 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | ||
177 | |||
178 | iwl_process_add_sta_resp(priv, addsta, pkt, false); | ||
179 | |||
130 | } | 180 | } |
131 | 181 | ||
132 | int iwl_send_add_sta(struct iwl_priv *priv, | 182 | int iwl_send_add_sta(struct iwl_priv *priv, |
133 | struct iwl_addsta_cmd *sta, u8 flags) | 183 | struct iwl_addsta_cmd *sta, u8 flags) |
134 | { | 184 | { |
135 | struct iwl_rx_packet *res = NULL; | 185 | struct iwl_rx_packet *pkt = NULL; |
136 | int ret = 0; | 186 | int ret = 0; |
137 | u8 data[sizeof(*sta)]; | 187 | u8 data[sizeof(*sta)]; |
138 | struct iwl_host_cmd cmd = { | 188 | struct iwl_host_cmd cmd = { |
@@ -152,28 +202,11 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
152 | if (ret || (flags & CMD_ASYNC)) | 202 | if (ret || (flags & CMD_ASYNC)) |
153 | return ret; | 203 | return ret; |
154 | 204 | ||
155 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | ||
156 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
157 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | ||
158 | res->hdr.flags); | ||
159 | ret = -EIO; | ||
160 | } | ||
161 | |||
162 | if (ret == 0) { | 205 | if (ret == 0) { |
163 | switch (res->u.add_sta.status) { | 206 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
164 | case ADD_STA_SUCCESS_MSK: | 207 | iwl_process_add_sta_resp(priv, sta, pkt, true); |
165 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); | ||
166 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | ||
167 | break; | ||
168 | default: | ||
169 | ret = -EIO; | ||
170 | IWL_WARN(priv, "REPLY_ADD_STA failed\n"); | ||
171 | break; | ||
172 | } | ||
173 | } | 208 | } |
174 | 209 | iwl_free_pages(priv, cmd.reply_page); | |
175 | priv->alloc_rxb_skb--; | ||
176 | dev_kfree_skb_any(cmd.reply_skb); | ||
177 | 210 | ||
178 | return ret; | 211 | return ret; |
179 | } | 212 | } |
@@ -189,6 +222,11 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | |||
189 | goto done; | 222 | goto done; |
190 | 223 | ||
191 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; | 224 | mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; |
225 | IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n", | ||
226 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? | ||
227 | "static" : | ||
228 | (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? | ||
229 | "dynamic" : "disabled"); | ||
192 | 230 | ||
193 | sta_flags = priv->stations[index].sta.station_flags; | 231 | sta_flags = priv->stations[index].sta.station_flags; |
194 | 232 | ||
@@ -301,7 +339,7 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, | |||
301 | } | 339 | } |
302 | EXPORT_SYMBOL(iwl_add_station); | 340 | EXPORT_SYMBOL(iwl_add_station); |
303 | 341 | ||
304 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | 342 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr) |
305 | { | 343 | { |
306 | unsigned long flags; | 344 | unsigned long flags; |
307 | u8 sta_id = iwl_find_station(priv, addr); | 345 | u8 sta_id = iwl_find_station(priv, addr); |
@@ -324,26 +362,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | |||
324 | 362 | ||
325 | static void iwl_remove_sta_callback(struct iwl_priv *priv, | 363 | static void iwl_remove_sta_callback(struct iwl_priv *priv, |
326 | struct iwl_device_cmd *cmd, | 364 | struct iwl_device_cmd *cmd, |
327 | struct sk_buff *skb) | 365 | struct iwl_rx_packet *pkt) |
328 | { | 366 | { |
329 | struct iwl_rx_packet *res = NULL; | ||
330 | struct iwl_rem_sta_cmd *rm_sta = | 367 | struct iwl_rem_sta_cmd *rm_sta = |
331 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; | 368 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; |
332 | const char *addr = rm_sta->addr; | 369 | const u8 *addr = rm_sta->addr; |
333 | |||
334 | if (!skb) { | ||
335 | IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n"); | ||
336 | return; | ||
337 | } | ||
338 | 370 | ||
339 | res = (struct iwl_rx_packet *)skb->data; | 371 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
340 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
341 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 372 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
342 | res->hdr.flags); | 373 | pkt->hdr.flags); |
343 | return; | 374 | return; |
344 | } | 375 | } |
345 | 376 | ||
346 | switch (res->u.rem_sta.status) { | 377 | switch (pkt->u.rem_sta.status) { |
347 | case REM_STA_SUCCESS_MSK: | 378 | case REM_STA_SUCCESS_MSK: |
348 | iwl_sta_ucode_deactivate(priv, addr); | 379 | iwl_sta_ucode_deactivate(priv, addr); |
349 | break; | 380 | break; |
@@ -356,7 +387,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv, | |||
356 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | 387 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, |
357 | u8 flags) | 388 | u8 flags) |
358 | { | 389 | { |
359 | struct iwl_rx_packet *res = NULL; | 390 | struct iwl_rx_packet *pkt; |
360 | int ret; | 391 | int ret; |
361 | 392 | ||
362 | struct iwl_rem_sta_cmd rm_sta_cmd; | 393 | struct iwl_rem_sta_cmd rm_sta_cmd; |
@@ -381,15 +412,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
381 | if (ret || (flags & CMD_ASYNC)) | 412 | if (ret || (flags & CMD_ASYNC)) |
382 | return ret; | 413 | return ret; |
383 | 414 | ||
384 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 415 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
385 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 416 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
386 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 417 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
387 | res->hdr.flags); | 418 | pkt->hdr.flags); |
388 | ret = -EIO; | 419 | ret = -EIO; |
389 | } | 420 | } |
390 | 421 | ||
391 | if (!ret) { | 422 | if (!ret) { |
392 | switch (res->u.rem_sta.status) { | 423 | switch (pkt->u.rem_sta.status) { |
393 | case REM_STA_SUCCESS_MSK: | 424 | case REM_STA_SUCCESS_MSK: |
394 | iwl_sta_ucode_deactivate(priv, addr); | 425 | iwl_sta_ucode_deactivate(priv, addr); |
395 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 426 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
@@ -400,9 +431,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
400 | break; | 431 | break; |
401 | } | 432 | } |
402 | } | 433 | } |
403 | 434 | iwl_free_pages(priv, cmd.reply_page); | |
404 | priv->alloc_rxb_skb--; | ||
405 | dev_kfree_skb_any(cmd.reply_skb); | ||
406 | 435 | ||
407 | return ret; | 436 | return ret; |
408 | } | 437 | } |
@@ -1016,24 +1045,19 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
1016 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; | 1045 | struct ieee80211_sta_ht_cap *cur_ht_config = NULL; |
1017 | u8 sta_id; | 1046 | u8 sta_id; |
1018 | 1047 | ||
1019 | /* Add station to device's station table */ | ||
1020 | |||
1021 | /* | 1048 | /* |
1022 | * XXX: This check is definitely not correct, if we're an AP | 1049 | * Set HT capabilities. It is ok to set this struct even if not using |
1023 | * it'll always be false which is not what we want, but | 1050 | * HT config: the priv->current_ht_config.is_ht flag will just be false |
1024 | * it doesn't look like iwlagn is prepared to be an HT | ||
1025 | * AP anyway. | ||
1026 | */ | 1051 | */ |
1027 | if (priv->current_ht_config.is_ht) { | 1052 | rcu_read_lock(); |
1028 | rcu_read_lock(); | 1053 | sta = ieee80211_find_sta(priv->vif, addr); |
1029 | sta = ieee80211_find_sta(priv->hw, addr); | 1054 | if (sta) { |
1030 | if (sta) { | 1055 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); |
1031 | memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); | 1056 | cur_ht_config = &ht_config; |
1032 | cur_ht_config = &ht_config; | ||
1033 | } | ||
1034 | rcu_read_unlock(); | ||
1035 | } | 1057 | } |
1058 | rcu_read_unlock(); | ||
1036 | 1059 | ||
1060 | /* Add station to device's station table */ | ||
1037 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); | 1061 | sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); |
1038 | 1062 | ||
1039 | /* Set up default rate scaling table in device's station table */ | 1063 | /* Set up default rate scaling table in device's station table */ |
@@ -1044,6 +1068,79 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
1044 | EXPORT_SYMBOL(iwl_rxon_add_station); | 1068 | EXPORT_SYMBOL(iwl_rxon_add_station); |
1045 | 1069 | ||
1046 | /** | 1070 | /** |
1071 | * iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table | ||
1072 | * | ||
1073 | * NOTE: Run REPLY_ADD_STA command to set up station table entry, before | ||
1074 | * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, | ||
1075 | * which requires station table entry to exist). | ||
1076 | */ | ||
1077 | static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) | ||
1078 | { | ||
1079 | int i, r; | ||
1080 | struct iwl_link_quality_cmd link_cmd = { | ||
1081 | .reserved1 = 0, | ||
1082 | }; | ||
1083 | u32 rate_flags; | ||
1084 | |||
1085 | /* Set up the rate scaling to start at selected rate, fall back | ||
1086 | * all the way down to 1M in IEEE order, and then spin on 1M */ | ||
1087 | if (priv->band == IEEE80211_BAND_5GHZ) | ||
1088 | r = IWL_RATE_6M_INDEX; | ||
1089 | else | ||
1090 | r = IWL_RATE_1M_INDEX; | ||
1091 | |||
1092 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
1093 | rate_flags = 0; | ||
1094 | if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||
1095 | rate_flags |= RATE_MCS_CCK_MSK; | ||
1096 | |||
1097 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | ||
1098 | RATE_MCS_ANT_POS; | ||
1099 | |||
1100 | link_cmd.rs_table[i].rate_n_flags = | ||
1101 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||
1102 | r = iwl_get_prev_ieee_rate(r); | ||
1103 | } | ||
1104 | |||
1105 | link_cmd.general_params.single_stream_ant_msk = | ||
1106 | first_antenna(priv->hw_params.valid_tx_ant); | ||
1107 | link_cmd.general_params.dual_stream_ant_msk = 3; | ||
1108 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | ||
1109 | link_cmd.agg_params.agg_time_limit = | ||
1110 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | ||
1111 | |||
1112 | /* Update the rate scaling for control frame Tx to AP */ | ||
1113 | link_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
1114 | |||
1115 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | ||
1116 | sizeof(link_cmd), &link_cmd, NULL); | ||
1117 | } | ||
1118 | |||
1119 | |||
1120 | /** | ||
1121 | * iwl_add_bcast_station - add broadcast station into station table. | ||
1122 | */ | ||
1123 | void iwl_add_bcast_station(struct iwl_priv *priv) | ||
1124 | { | ||
1125 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1126 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | ||
1127 | |||
1128 | /* Set up default rate scaling table in device's station table */ | ||
1129 | iwl_sta_init_bcast_lq(priv); | ||
1130 | } | ||
1131 | EXPORT_SYMBOL(iwl_add_bcast_station); | ||
1132 | |||
1133 | /** | ||
1134 | * iwl3945_add_bcast_station - add broadcast station into station table. | ||
1135 | */ | ||
1136 | void iwl3945_add_bcast_station(struct iwl_priv *priv) | ||
1137 | { | ||
1138 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1139 | iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); | ||
1140 | } | ||
1141 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | ||
1142 | |||
1143 | /** | ||
1047 | * iwl_get_sta_id - Find station's index within station table | 1144 | * iwl_get_sta_id - Find station's index within station table |
1048 | * | 1145 | * |
1049 | * If new IBSS station, create new entry in station table | 1146 | * If new IBSS station, create new entry in station table |
@@ -1163,7 +1260,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | |||
1163 | } | 1260 | } |
1164 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1261 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); |
1165 | 1262 | ||
1166 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | 1263 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) |
1167 | { | 1264 | { |
1168 | unsigned long flags; | 1265 | unsigned long flags; |
1169 | 1266 | ||
@@ -1171,27 +1268,26 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1171 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | 1268 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; |
1172 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | 1269 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1173 | priv->stations[sta_id].sta.sta.modify_mask = 0; | 1270 | priv->stations[sta_id].sta.sta.modify_mask = 0; |
1271 | priv->stations[sta_id].sta.sleep_tx_count = 0; | ||
1174 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1272 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1175 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1273 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1176 | 1274 | ||
1177 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1275 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1178 | } | 1276 | } |
1277 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | ||
1179 | 1278 | ||
1180 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | 1279 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) |
1181 | { | 1280 | { |
1182 | /* FIXME: need locking over ps_status ??? */ | 1281 | unsigned long flags; |
1183 | u8 sta_id = iwl_find_station(priv, addr); | ||
1184 | 1282 | ||
1185 | if (sta_id != IWL_INVALID_STATION) { | 1283 | spin_lock_irqsave(&priv->sta_lock, flags); |
1186 | u8 sta_awake = priv->stations[sta_id]. | 1284 | priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; |
1187 | ps_status == STA_PS_STATUS_WAKE; | 1285 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1286 | priv->stations[sta_id].sta.sta.modify_mask = | ||
1287 | STA_MODIFY_SLEEP_TX_COUNT_MSK; | ||
1288 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); | ||
1289 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1290 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1188 | 1291 | ||
1189 | if (sta_awake && ps_bit) | 1292 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1190 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1191 | else if (!sta_awake && !ps_bit) { | ||
1192 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1193 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1194 | } | ||
1195 | } | ||
1196 | } | 1293 | } |
1197 | |||