aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2011-02-20 21:18:00 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-23 16:25:25 -0500
commita97b478c92c14255d375ed9ceb7a882083523593 (patch)
tree26f696e628401920344c069b46d21c8582d59af9 /drivers/net/wireless/ath
parent36bcce430657e6fece0e8dd91557f35dbb69ec67 (diff)
ath9k_htc: Allow upto two simultaneous interfaces
Multiple interfaces can be configured if a slot is free on the target. Monitor mode also requires a slot. The maximum number of stations that can be handled in the firmware is 8, manage the station slots accordingly. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c148
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c29
3 files changed, 130 insertions, 54 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 0cb504d7b8c4..ab8d1f0cba13 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -204,6 +204,8 @@ struct ath9k_htc_target_stats {
204 __be32 ht_tx_xretries; 204 __be32 ht_tx_xretries;
205} __packed; 205} __packed;
206 206
207#define ATH9K_HTC_MAX_VIF 2
208
207struct ath9k_htc_vif { 209struct ath9k_htc_vif {
208 u8 index; 210 u8 index;
209}; 211};
@@ -358,6 +360,11 @@ struct ath9k_htc_priv {
358 enum htc_endpoint_id data_vi_ep; 360 enum htc_endpoint_id data_vi_ep;
359 enum htc_endpoint_id data_vo_ep; 361 enum htc_endpoint_id data_vo_ep;
360 362
363 u8 vif_slot;
364 u8 mon_vif_idx;
365 u8 sta_slot;
366 u8 vif_sta_pos[ATH9K_HTC_MAX_VIF];
367
361 u16 op_flags; 368 u16 op_flags;
362 u16 curtxpow; 369 u16 curtxpow;
363 u16 txpowlimit; 370 u16 txpowlimit;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 50fde0e10595..618670d318c5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -227,6 +227,13 @@ err:
227 return ret; 227 return ret;
228} 228}
229 229
230/*
231 * Monitor mode handling is a tad complicated because the firmware requires
232 * an interface to be created exclusively, while mac80211 doesn't associate
233 * an interface with the mode.
234 *
235 * So, for now, only one monitor interface can be configured.
236 */
230static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) 237static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
231{ 238{
232 struct ath_common *common = ath9k_hw_common(priv->ah); 239 struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -236,9 +243,10 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
236 243
237 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); 244 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
238 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); 245 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
239 hvif.index = 0; /* Should do for now */ 246 hvif.index = priv->mon_vif_idx;
240 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); 247 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
241 priv->nvifs--; 248 priv->nvifs--;
249 priv->vif_slot &= ~(1 << priv->mon_vif_idx);
242} 250}
243 251
244static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) 252static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
@@ -246,51 +254,69 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
246 struct ath_common *common = ath9k_hw_common(priv->ah); 254 struct ath_common *common = ath9k_hw_common(priv->ah);
247 struct ath9k_htc_target_vif hvif; 255 struct ath9k_htc_target_vif hvif;
248 struct ath9k_htc_target_sta tsta; 256 struct ath9k_htc_target_sta tsta;
249 int ret = 0; 257 int ret = 0, sta_idx;
250 u8 cmd_rsp; 258 u8 cmd_rsp;
251 259
252 if (priv->nvifs > 0) 260 if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) ||
253 return -ENOBUFS; 261 (priv->nstations >= ATH9K_HTC_MAX_STA)) {
262 ret = -ENOBUFS;
263 goto err_vif;
264 }
254 265
255 if (priv->nstations >= ATH9K_HTC_MAX_STA) 266 sta_idx = ffz(priv->sta_slot);
256 return -ENOBUFS; 267 if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) {
268 ret = -ENOBUFS;
269 goto err_vif;
270 }
257 271
258 /* 272 /*
259 * Add an interface. 273 * Add an interface.
260 */ 274 */
261
262 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); 275 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
263 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); 276 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
264 277
265 hvif.opmode = cpu_to_be32(HTC_M_MONITOR); 278 hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
266 priv->ah->opmode = NL80211_IFTYPE_MONITOR; 279 hvif.index = ffz(priv->vif_slot);
267 hvif.index = priv->nvifs;
268 280
269 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); 281 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
270 if (ret) 282 if (ret)
271 return ret; 283 goto err_vif;
284
285 /*
286 * Assign the monitor interface index as a special case here.
287 * This is needed when the interface is brought down.
288 */
289 priv->mon_vif_idx = hvif.index;
290 priv->vif_slot |= (1 << hvif.index);
291
292 /*
293 * Set the hardware mode to monitor only if there are no
294 * other interfaces.
295 */
296 if (!priv->nvifs)
297 priv->ah->opmode = NL80211_IFTYPE_MONITOR;
272 298
273 priv->nvifs++; 299 priv->nvifs++;
274 300
275 /* 301 /*
276 * Associate a station with the interface for packet injection. 302 * Associate a station with the interface for packet injection.
277 */ 303 */
278
279 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); 304 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
280 305
281 memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); 306 memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
282 307
283 tsta.is_vif_sta = 1; 308 tsta.is_vif_sta = 1;
284 tsta.sta_index = priv->nstations; 309 tsta.sta_index = sta_idx;
285 tsta.vif_index = hvif.index; 310 tsta.vif_index = hvif.index;
286 tsta.maxampdu = 0xffff; 311 tsta.maxampdu = 0xffff;
287 312
288 WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); 313 WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
289 if (ret) { 314 if (ret) {
290 ath_err(common, "Unable to add station entry for monitor mode\n"); 315 ath_err(common, "Unable to add station entry for monitor mode\n");
291 goto err_vif; 316 goto err_sta;
292 } 317 }
293 318
319 priv->sta_slot |= (1 << sta_idx);
294 priv->nstations++; 320 priv->nstations++;
295 321
296 /* 322 /*
@@ -301,15 +327,23 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
301 ath_dbg(common, ATH_DBG_CONFIG, 327 ath_dbg(common, ATH_DBG_CONFIG,
302 "Failed to update capability in target\n"); 328 "Failed to update capability in target\n");
303 329
330 priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
304 priv->ah->is_monitoring = true; 331 priv->ah->is_monitoring = true;
305 332
333 ath_dbg(common, ATH_DBG_CONFIG,
334 "Attached a monitor interface at idx: %d, sta idx: %d\n",
335 priv->mon_vif_idx, sta_idx);
336
306 return 0; 337 return 0;
307 338
308err_vif: 339err_sta:
309 /* 340 /*
310 * Remove the interface from the target. 341 * Remove the interface from the target.
311 */ 342 */
312 __ath9k_htc_remove_monitor_interface(priv); 343 __ath9k_htc_remove_monitor_interface(priv);
344err_vif:
345 ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n");
346
313 return ret; 347 return ret;
314} 348}
315 349
@@ -321,7 +355,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
321 355
322 __ath9k_htc_remove_monitor_interface(priv); 356 __ath9k_htc_remove_monitor_interface(priv);
323 357
324 sta_idx = 0; /* Only single interface, for now */ 358 sta_idx = priv->vif_sta_pos[priv->mon_vif_idx];
325 359
326 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); 360 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
327 if (ret) { 361 if (ret) {
@@ -329,9 +363,14 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
329 return ret; 363 return ret;
330 } 364 }
331 365
366 priv->sta_slot &= ~(1 << sta_idx);
332 priv->nstations--; 367 priv->nstations--;
333 priv->ah->is_monitoring = false; 368 priv->ah->is_monitoring = false;
334 369
370 ath_dbg(common, ATH_DBG_CONFIG,
371 "Removed a monitor interface at idx: %d, sta idx: %d\n",
372 priv->mon_vif_idx, sta_idx);
373
335 return 0; 374 return 0;
336} 375}
337 376
@@ -343,12 +382,16 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
343 struct ath9k_htc_target_sta tsta; 382 struct ath9k_htc_target_sta tsta;
344 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; 383 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
345 struct ath9k_htc_sta *ista; 384 struct ath9k_htc_sta *ista;
346 int ret; 385 int ret, sta_idx;
347 u8 cmd_rsp; 386 u8 cmd_rsp;
348 387
349 if (priv->nstations >= ATH9K_HTC_MAX_STA) 388 if (priv->nstations >= ATH9K_HTC_MAX_STA)
350 return -ENOBUFS; 389 return -ENOBUFS;
351 390
391 sta_idx = ffz(priv->sta_slot);
392 if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA))
393 return -ENOBUFS;
394
352 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); 395 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
353 396
354 if (sta) { 397 if (sta) {
@@ -358,13 +401,13 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
358 tsta.associd = common->curaid; 401 tsta.associd = common->curaid;
359 tsta.is_vif_sta = 0; 402 tsta.is_vif_sta = 0;
360 tsta.valid = true; 403 tsta.valid = true;
361 ista->index = priv->nstations; 404 ista->index = sta_idx;
362 } else { 405 } else {
363 memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); 406 memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
364 tsta.is_vif_sta = 1; 407 tsta.is_vif_sta = 1;
365 } 408 }
366 409
367 tsta.sta_index = priv->nstations; 410 tsta.sta_index = sta_idx;
368 tsta.vif_index = avp->index; 411 tsta.vif_index = avp->index;
369 tsta.maxampdu = 0xffff; 412 tsta.maxampdu = 0xffff;
370 if (sta && sta->ht_cap.ht_supported) 413 if (sta && sta->ht_cap.ht_supported)
@@ -379,12 +422,21 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
379 return ret; 422 return ret;
380 } 423 }
381 424
382 if (sta) 425 if (sta) {
383 ath_dbg(common, ATH_DBG_CONFIG, 426 ath_dbg(common, ATH_DBG_CONFIG,
384 "Added a station entry for: %pM (idx: %d)\n", 427 "Added a station entry for: %pM (idx: %d)\n",
385 sta->addr, tsta.sta_index); 428 sta->addr, tsta.sta_index);
429 } else {
430 ath_dbg(common, ATH_DBG_CONFIG,
431 "Added a station entry for VIF %d (idx: %d)\n",
432 avp->index, tsta.sta_index);
433 }
386 434
435 priv->sta_slot |= (1 << sta_idx);
387 priv->nstations++; 436 priv->nstations++;
437 if (!sta)
438 priv->vif_sta_pos[avp->index] = sta_idx;
439
388 return 0; 440 return 0;
389} 441}
390 442
@@ -393,6 +445,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
393 struct ieee80211_sta *sta) 445 struct ieee80211_sta *sta)
394{ 446{
395 struct ath_common *common = ath9k_hw_common(priv->ah); 447 struct ath_common *common = ath9k_hw_common(priv->ah);
448 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
396 struct ath9k_htc_sta *ista; 449 struct ath9k_htc_sta *ista;
397 int ret; 450 int ret;
398 u8 cmd_rsp, sta_idx; 451 u8 cmd_rsp, sta_idx;
@@ -401,7 +454,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
401 ista = (struct ath9k_htc_sta *) sta->drv_priv; 454 ista = (struct ath9k_htc_sta *) sta->drv_priv;
402 sta_idx = ista->index; 455 sta_idx = ista->index;
403 } else { 456 } else {
404 sta_idx = 0; 457 sta_idx = priv->vif_sta_pos[avp->index];
405 } 458 }
406 459
407 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); 460 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
@@ -413,12 +466,19 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
413 return ret; 466 return ret;
414 } 467 }
415 468
416 if (sta) 469 if (sta) {
417 ath_dbg(common, ATH_DBG_CONFIG, 470 ath_dbg(common, ATH_DBG_CONFIG,
418 "Removed a station entry for: %pM (idx: %d)\n", 471 "Removed a station entry for: %pM (idx: %d)\n",
419 sta->addr, sta_idx); 472 sta->addr, sta_idx);
473 } else {
474 ath_dbg(common, ATH_DBG_CONFIG,
475 "Removed a station entry for VIF %d (idx: %d)\n",
476 avp->index, sta_idx);
477 }
420 478
479 priv->sta_slot &= ~(1 << sta_idx);
421 priv->nstations--; 480 priv->nstations--;
481
422 return 0; 482 return 0;
423} 483}
424 484
@@ -1049,21 +1109,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
1049 1109
1050 mutex_lock(&priv->mutex); 1110 mutex_lock(&priv->mutex);
1051 1111
1052 /* Remove monitor interface here */
1053 if (ah->opmode == NL80211_IFTYPE_MONITOR) {
1054 if (ath9k_htc_remove_monitor_interface(priv))
1055 ath_err(common, "Unable to remove monitor interface\n");
1056 else
1057 ath_dbg(common, ATH_DBG_CONFIG,
1058 "Monitor interface removed\n");
1059 }
1060
1061 if (ah->btcoex_hw.enabled) { 1112 if (ah->btcoex_hw.enabled) {
1062 ath9k_hw_btcoex_disable(ah); 1113 ath9k_hw_btcoex_disable(ah);
1063 if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) 1114 if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
1064 ath_htc_cancel_btcoex_work(priv); 1115 ath_htc_cancel_btcoex_work(priv);
1065 } 1116 }
1066 1117
1118 /* Remove a monitor interface if it's present. */
1119 if (priv->ah->is_monitoring)
1120 ath9k_htc_remove_monitor_interface(priv);
1121
1067 ath9k_hw_phy_disable(ah); 1122 ath9k_hw_phy_disable(ah);
1068 ath9k_hw_disable(ah); 1123 ath9k_hw_disable(ah);
1069 ath9k_htc_ps_restore(priv); 1124 ath9k_htc_ps_restore(priv);
@@ -1087,8 +1142,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1087 1142
1088 mutex_lock(&priv->mutex); 1143 mutex_lock(&priv->mutex);
1089 1144
1090 /* Only one interface for now */ 1145 if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
1091 if (priv->nvifs > 0) {
1092 ret = -ENOBUFS; 1146 ret = -ENOBUFS;
1093 goto out; 1147 goto out;
1094 } 1148 }
@@ -1111,13 +1165,8 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1111 goto out; 1165 goto out;
1112 } 1166 }
1113 1167
1114 ath_dbg(common, ATH_DBG_CONFIG,
1115 "Attach a VIF of type: %d\n", vif->type);
1116
1117 priv->ah->opmode = vif->type;
1118
1119 /* Index starts from zero on the target */ 1168 /* Index starts from zero on the target */
1120 avp->index = hvif.index = priv->nvifs; 1169 avp->index = hvif.index = ffz(priv->vif_slot);
1121 hvif.rtsthreshold = cpu_to_be16(2304); 1170 hvif.rtsthreshold = cpu_to_be16(2304);
1122 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); 1171 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
1123 if (ret) 1172 if (ret)
@@ -1138,7 +1187,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1138 ath_dbg(common, ATH_DBG_CONFIG, 1187 ath_dbg(common, ATH_DBG_CONFIG,
1139 "Failed to update capability in target\n"); 1188 "Failed to update capability in target\n");
1140 1189
1190 priv->ah->opmode = vif->type;
1191 priv->vif_slot |= (1 << avp->index);
1141 priv->vif = vif; 1192 priv->vif = vif;
1193
1194 ath_dbg(common, ATH_DBG_CONFIG,
1195 "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
1196
1142out: 1197out:
1143 ath9k_htc_ps_restore(priv); 1198 ath9k_htc_ps_restore(priv);
1144 mutex_unlock(&priv->mutex); 1199 mutex_unlock(&priv->mutex);
@@ -1156,8 +1211,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
1156 int ret = 0; 1211 int ret = 0;
1157 u8 cmd_rsp; 1212 u8 cmd_rsp;
1158 1213
1159 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
1160
1161 mutex_lock(&priv->mutex); 1214 mutex_lock(&priv->mutex);
1162 ath9k_htc_ps_wakeup(priv); 1215 ath9k_htc_ps_wakeup(priv);
1163 1216
@@ -1166,10 +1219,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
1166 hvif.index = avp->index; 1219 hvif.index = avp->index;
1167 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); 1220 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
1168 priv->nvifs--; 1221 priv->nvifs--;
1222 priv->vif_slot &= ~(1 << avp->index);
1169 1223
1170 ath9k_htc_remove_station(priv, vif, NULL); 1224 ath9k_htc_remove_station(priv, vif, NULL);
1171 priv->vif = NULL; 1225 priv->vif = NULL;
1172 1226
1227 ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index);
1228
1173 ath9k_htc_ps_restore(priv); 1229 ath9k_htc_ps_restore(priv);
1174 mutex_unlock(&priv->mutex); 1230 mutex_unlock(&priv->mutex);
1175} 1231}
@@ -1205,13 +1261,11 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
1205 * IEEE80211_CONF_CHANGE_CHANNEL is handled. 1261 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
1206 */ 1262 */
1207 if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 1263 if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1208 if (conf->flags & IEEE80211_CONF_MONITOR) { 1264 if ((conf->flags & IEEE80211_CONF_MONITOR) &&
1209 if (ath9k_htc_add_monitor_interface(priv)) 1265 !priv->ah->is_monitoring)
1210 ath_err(common, "Failed to set monitor mode\n"); 1266 ath9k_htc_add_monitor_interface(priv);
1211 else 1267 else if (priv->ah->is_monitoring)
1212 ath_dbg(common, ATH_DBG_CONFIG, 1268 ath9k_htc_remove_monitor_interface(priv);
1213 "HW opmode set to Monitor mode\n");
1214 }
1215 } 1269 }
1216 1270
1217 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 1271 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 7a5ffca21958..d5f0f41b4dec 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -84,7 +84,9 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
84 struct ieee80211_hdr *hdr; 84 struct ieee80211_hdr *hdr;
85 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 85 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
86 struct ieee80211_sta *sta = tx_info->control.sta; 86 struct ieee80211_sta *sta = tx_info->control.sta;
87 struct ieee80211_vif *vif = tx_info->control.vif;
87 struct ath9k_htc_sta *ista; 88 struct ath9k_htc_sta *ista;
89 struct ath9k_htc_vif *avp;
88 struct ath9k_htc_tx_ctl tx_ctl; 90 struct ath9k_htc_tx_ctl tx_ctl;
89 enum htc_endpoint_id epid; 91 enum htc_endpoint_id epid;
90 u16 qnum; 92 u16 qnum;
@@ -95,18 +97,31 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
95 hdr = (struct ieee80211_hdr *) skb->data; 97 hdr = (struct ieee80211_hdr *) skb->data;
96 fc = hdr->frame_control; 98 fc = hdr->frame_control;
97 99
98 if (tx_info->control.vif && 100 /*
99 (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv) 101 * Find out on which interface this packet has to be
100 vif_idx = ((struct ath9k_htc_vif *) 102 * sent out.
101 tx_info->control.vif->drv_priv)->index; 103 */
102 else 104 if (vif) {
103 vif_idx = priv->nvifs; 105 avp = (struct ath9k_htc_vif *) vif->drv_priv;
106 vif_idx = avp->index;
107 } else {
108 if (!priv->ah->is_monitoring) {
109 ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
110 "VIF is null, but no monitor interface !\n");
111 return -EINVAL;
112 }
104 113
114 vif_idx = priv->mon_vif_idx;
115 }
116
117 /*
118 * Find out which station this packet is destined for.
119 */
105 if (sta) { 120 if (sta) {
106 ista = (struct ath9k_htc_sta *) sta->drv_priv; 121 ista = (struct ath9k_htc_sta *) sta->drv_priv;
107 sta_idx = ista->index; 122 sta_idx = ista->index;
108 } else { 123 } else {
109 sta_idx = 0; 124 sta_idx = priv->vif_sta_pos[vif_idx];
110 } 125 }
111 126
112 memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); 127 memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));