diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 137 |
1 files changed, 79 insertions, 58 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3fc982e87921..5950184d9860 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -71,18 +71,6 @@ static const u8 tid_to_ac[] = { | |||
71 | 2, 3, 3, 2, 1, 1, 0, 0 | 71 | 2, 3, 3, 2, 1, 1, 0, 0 |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static const u8 ac_to_fifo[] = { | ||
75 | IWL_TX_FIFO_VO, | ||
76 | IWL_TX_FIFO_VI, | ||
77 | IWL_TX_FIFO_BE, | ||
78 | IWL_TX_FIFO_BK, | ||
79 | }; | ||
80 | |||
81 | static inline int get_fifo_from_ac(u8 ac) | ||
82 | { | ||
83 | return ac_to_fifo[ac]; | ||
84 | } | ||
85 | |||
86 | static inline int get_ac_from_tid(u16 tid) | 74 | static inline int get_ac_from_tid(u16 tid) |
87 | { | 75 | { |
88 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | 76 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) |
@@ -92,10 +80,10 @@ static inline int get_ac_from_tid(u16 tid) | |||
92 | return -EINVAL; | 80 | return -EINVAL; |
93 | } | 81 | } |
94 | 82 | ||
95 | static inline int get_fifo_from_tid(u16 tid) | 83 | static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) |
96 | { | 84 | { |
97 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | 85 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) |
98 | return get_fifo_from_ac(tid_to_ac[tid]); | 86 | return ctx->ac_to_fifo[tid_to_ac[tid]]; |
99 | 87 | ||
100 | /* no support for TIDs 8-15 yet */ | 88 | /* no support for TIDs 8-15 yet */ |
101 | return -EINVAL; | 89 | return -EINVAL; |
@@ -118,7 +106,7 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
118 | 106 | ||
119 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | 107 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); |
120 | 108 | ||
121 | if (txq_id != IWL_CMD_QUEUE_NUM) { | 109 | if (txq_id != priv->cmd_queue) { |
122 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | 110 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; |
123 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | 111 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; |
124 | 112 | ||
@@ -155,7 +143,7 @@ void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | |||
155 | 143 | ||
156 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | 144 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); |
157 | 145 | ||
158 | if (txq_id != IWL_CMD_QUEUE_NUM) | 146 | if (txq_id != priv->cmd_queue) |
159 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | 147 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; |
160 | 148 | ||
161 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | 149 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); |
@@ -333,19 +321,15 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
333 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); | 321 | iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask); |
334 | } | 322 | } |
335 | 323 | ||
336 | static inline int get_queue_from_ac(u16 ac) | ||
337 | { | ||
338 | return ac; | ||
339 | } | ||
340 | |||
341 | /* | 324 | /* |
342 | * handle build REPLY_TX command notification. | 325 | * handle build REPLY_TX command notification. |
343 | */ | 326 | */ |
344 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | 327 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, |
345 | struct iwl_tx_cmd *tx_cmd, | 328 | struct sk_buff *skb, |
346 | struct ieee80211_tx_info *info, | 329 | struct iwl_tx_cmd *tx_cmd, |
347 | struct ieee80211_hdr *hdr, | 330 | struct ieee80211_tx_info *info, |
348 | u8 std_id) | 331 | struct ieee80211_hdr *hdr, |
332 | u8 std_id) | ||
349 | { | 333 | { |
350 | __le16 fc = hdr->frame_control; | 334 | __le16 fc = hdr->frame_control; |
351 | __le32 tx_flags = tx_cmd->tx_flags; | 335 | __le32 tx_flags = tx_cmd->tx_flags; |
@@ -365,6 +349,12 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | |||
365 | 349 | ||
366 | if (ieee80211_is_back_req(fc)) | 350 | if (ieee80211_is_back_req(fc)) |
367 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | 351 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; |
352 | else if (info->band == IEEE80211_BAND_2GHZ && | ||
353 | priv->cfg->advanced_bt_coexist && | ||
354 | (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || | ||
355 | ieee80211_is_reassoc_req(fc) || | ||
356 | skb->protocol == cpu_to_be16(ETH_P_PAE))) | ||
357 | tx_flags |= TX_CMD_FLG_IGNORE_BT; | ||
368 | 358 | ||
369 | 359 | ||
370 | tx_cmd->sta_id = std_id; | 360 | tx_cmd->sta_id = std_id; |
@@ -454,7 +444,12 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | |||
454 | rate_flags |= RATE_MCS_CCK_MSK; | 444 | rate_flags |= RATE_MCS_CCK_MSK; |
455 | 445 | ||
456 | /* Set up antennas */ | 446 | /* Set up antennas */ |
457 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 447 | if (priv->cfg->advanced_bt_coexist && priv->bt_full_concurrent) { |
448 | /* operated as 1x1 in full concurrency mode */ | ||
449 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | ||
450 | first_antenna(priv->hw_params.valid_tx_ant)); | ||
451 | } else | ||
452 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | ||
458 | priv->hw_params.valid_tx_ant); | 453 | priv->hw_params.valid_tx_ant); |
459 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 454 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); |
460 | 455 | ||
@@ -519,6 +514,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
519 | struct iwl_device_cmd *out_cmd; | 514 | struct iwl_device_cmd *out_cmd; |
520 | struct iwl_cmd_meta *out_meta; | 515 | struct iwl_cmd_meta *out_meta; |
521 | struct iwl_tx_cmd *tx_cmd; | 516 | struct iwl_tx_cmd *tx_cmd; |
517 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
522 | int swq_id, txq_id; | 518 | int swq_id, txq_id; |
523 | dma_addr_t phys_addr; | 519 | dma_addr_t phys_addr; |
524 | dma_addr_t txcmd_phys; | 520 | dma_addr_t txcmd_phys; |
@@ -533,6 +529,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
533 | u8 *qc = NULL; | 529 | u8 *qc = NULL; |
534 | unsigned long flags; | 530 | unsigned long flags; |
535 | 531 | ||
532 | if (info->control.vif) | ||
533 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); | ||
534 | |||
536 | spin_lock_irqsave(&priv->lock, flags); | 535 | spin_lock_irqsave(&priv->lock, flags); |
537 | if (iwl_is_rfkill(priv)) { | 536 | if (iwl_is_rfkill(priv)) { |
538 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | 537 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); |
@@ -553,7 +552,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
553 | hdr_len = ieee80211_hdrlen(fc); | 552 | hdr_len = ieee80211_hdrlen(fc); |
554 | 553 | ||
555 | /* Find index into station table for destination station */ | 554 | /* Find index into station table for destination station */ |
556 | sta_id = iwl_sta_id_or_broadcast(priv, info->control.sta); | 555 | sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta); |
557 | if (sta_id == IWL_INVALID_STATION) { | 556 | if (sta_id == IWL_INVALID_STATION) { |
558 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 557 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
559 | hdr->addr1); | 558 | hdr->addr1); |
@@ -565,8 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
565 | if (sta) | 564 | if (sta) |
566 | sta_priv = (void *)sta->drv_priv; | 565 | sta_priv = (void *)sta->drv_priv; |
567 | 566 | ||
568 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | 567 | if (sta_priv && sta_priv->asleep) { |
569 | sta_priv->asleep) { | ||
570 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | 568 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); |
571 | /* | 569 | /* |
572 | * This sends an asynchronous command to the device, | 570 | * This sends an asynchronous command to the device, |
@@ -580,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
580 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | 578 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); |
581 | } | 579 | } |
582 | 580 | ||
583 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | 581 | /* |
582 | * Send this frame after DTIM -- there's a special queue | ||
583 | * reserved for this for contexts that support AP mode. | ||
584 | */ | ||
585 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
586 | txq_id = ctx->mcast_queue; | ||
587 | /* | ||
588 | * The microcode will clear the more data | ||
589 | * bit in the last frame it transmits. | ||
590 | */ | ||
591 | hdr->frame_control |= | ||
592 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
593 | } else | ||
594 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
584 | 595 | ||
585 | /* irqs already disabled/saved above when locking priv->lock */ | 596 | /* irqs already disabled/saved above when locking priv->lock */ |
586 | spin_lock(&priv->sta_lock); | 597 | spin_lock(&priv->sta_lock); |
@@ -625,6 +636,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
625 | /* Set up driver data for this TFD */ | 636 | /* Set up driver data for this TFD */ |
626 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 637 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
627 | txq->txb[q->write_ptr].skb = skb; | 638 | txq->txb[q->write_ptr].skb = skb; |
639 | txq->txb[q->write_ptr].ctx = ctx; | ||
628 | 640 | ||
629 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 641 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
630 | out_cmd = txq->cmd[q->write_ptr]; | 642 | out_cmd = txq->cmd[q->write_ptr]; |
@@ -655,7 +667,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
655 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | 667 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); |
656 | 668 | ||
657 | /* TODO need this for burst mode later on */ | 669 | /* TODO need this for burst mode later on */ |
658 | iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | 670 | iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); |
659 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | 671 | iwl_dbg_log_tx_data_frame(priv, len, hdr); |
660 | 672 | ||
661 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); | 673 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); |
@@ -813,7 +825,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | |||
813 | /* Tx queues */ | 825 | /* Tx queues */ |
814 | if (priv->txq) { | 826 | if (priv->txq) { |
815 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 827 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
816 | if (txq_id == IWL_CMD_QUEUE_NUM) | 828 | if (txq_id == priv->cmd_queue) |
817 | iwl_cmd_queue_free(priv); | 829 | iwl_cmd_queue_free(priv); |
818 | else | 830 | else |
819 | iwl_tx_queue_free(priv, txq_id); | 831 | iwl_tx_queue_free(priv, txq_id); |
@@ -870,9 +882,9 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) | |||
870 | 882 | ||
871 | spin_unlock_irqrestore(&priv->lock, flags); | 883 | spin_unlock_irqrestore(&priv->lock, flags); |
872 | 884 | ||
873 | /* Alloc and init all Tx queues, including the command queue (#4) */ | 885 | /* Alloc and init all Tx queues, including the command queue (#4/#9) */ |
874 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 886 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
875 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | 887 | slots_num = (txq_id == priv->cmd_queue) ? |
876 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 888 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; |
877 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | 889 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, |
878 | txq_id); | 890 | txq_id); |
@@ -910,7 +922,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | |||
910 | 922 | ||
911 | /* Alloc and init all Tx queues, including the command queue (#4) */ | 923 | /* Alloc and init all Tx queues, including the command queue (#4) */ |
912 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 924 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
913 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | 925 | slots_num = txq_id == priv->cmd_queue ? |
914 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 926 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; |
915 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | 927 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); |
916 | } | 928 | } |
@@ -968,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
968 | unsigned long flags; | 980 | unsigned long flags; |
969 | struct iwl_tid_data *tid_data; | 981 | struct iwl_tid_data *tid_data; |
970 | 982 | ||
971 | tx_fifo = get_fifo_from_tid(tid); | 983 | tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); |
972 | if (unlikely(tx_fifo < 0)) | 984 | if (unlikely(tx_fifo < 0)) |
973 | return tx_fifo; | 985 | return tx_fifo; |
974 | 986 | ||
@@ -1024,12 +1036,12 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1024 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | 1036 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, |
1025 | struct ieee80211_sta *sta, u16 tid) | 1037 | struct ieee80211_sta *sta, u16 tid) |
1026 | { | 1038 | { |
1027 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | 1039 | int tx_fifo_id, txq_id, sta_id, ssn; |
1028 | struct iwl_tid_data *tid_data; | 1040 | struct iwl_tid_data *tid_data; |
1029 | int write_ptr, read_ptr; | 1041 | int write_ptr, read_ptr; |
1030 | unsigned long flags; | 1042 | unsigned long flags; |
1031 | 1043 | ||
1032 | tx_fifo_id = get_fifo_from_tid(tid); | 1044 | tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); |
1033 | if (unlikely(tx_fifo_id < 0)) | 1045 | if (unlikely(tx_fifo_id < 0)) |
1034 | return tx_fifo_id; | 1046 | return tx_fifo_id; |
1035 | 1047 | ||
@@ -1042,21 +1054,26 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1042 | 1054 | ||
1043 | spin_lock_irqsave(&priv->sta_lock, flags); | 1055 | spin_lock_irqsave(&priv->sta_lock, flags); |
1044 | 1056 | ||
1045 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1046 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1047 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1048 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1049 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1050 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1055 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1056 | |||
1057 | tid_data = &priv->stations[sta_id].tid[tid]; | 1057 | tid_data = &priv->stations[sta_id].tid[tid]; |
1058 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | 1058 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; |
1059 | txq_id = tid_data->agg.txq_id; | 1059 | txq_id = tid_data->agg.txq_id; |
1060 | |||
1061 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1062 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1063 | /* | ||
1064 | * This can happen if the peer stops aggregation | ||
1065 | * again before we've had a chance to drain the | ||
1066 | * queue we selected previously, i.e. before the | ||
1067 | * session was really started completely. | ||
1068 | */ | ||
1069 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1070 | goto turn_off; | ||
1071 | case IWL_AGG_ON: | ||
1072 | break; | ||
1073 | default: | ||
1074 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1075 | } | ||
1076 | |||
1060 | write_ptr = priv->txq[txq_id].q.write_ptr; | 1077 | write_ptr = priv->txq[txq_id].q.write_ptr; |
1061 | read_ptr = priv->txq[txq_id].q.read_ptr; | 1078 | read_ptr = priv->txq[txq_id].q.read_ptr; |
1062 | 1079 | ||
@@ -1070,6 +1087,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1070 | } | 1087 | } |
1071 | 1088 | ||
1072 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1089 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1090 | turn_off: | ||
1073 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1091 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1074 | 1092 | ||
1075 | /* do not restore/save irqs */ | 1093 | /* do not restore/save irqs */ |
@@ -1098,6 +1116,9 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1098 | struct iwl_queue *q = &priv->txq[txq_id].q; | 1116 | struct iwl_queue *q = &priv->txq[txq_id].q; |
1099 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | 1117 | u8 *addr = priv->stations[sta_id].sta.sta.addr; |
1100 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | 1118 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; |
1119 | struct iwl_rxon_context *ctx; | ||
1120 | |||
1121 | ctx = &priv->contexts[priv->stations[sta_id].ctxid]; | ||
1101 | 1122 | ||
1102 | lockdep_assert_held(&priv->sta_lock); | 1123 | lockdep_assert_held(&priv->sta_lock); |
1103 | 1124 | ||
@@ -1108,12 +1129,12 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1108 | if ((txq_id == tid_data->agg.txq_id) && | 1129 | if ((txq_id == tid_data->agg.txq_id) && |
1109 | (q->read_ptr == q->write_ptr)) { | 1130 | (q->read_ptr == q->write_ptr)) { |
1110 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | 1131 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); |
1111 | int tx_fifo = get_fifo_from_tid(tid); | 1132 | int tx_fifo = get_fifo_from_tid(ctx, tid); |
1112 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | 1133 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); |
1113 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | 1134 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, |
1114 | ssn, tx_fifo); | 1135 | ssn, tx_fifo); |
1115 | tid_data->agg.state = IWL_AGG_OFF; | 1136 | tid_data->agg.state = IWL_AGG_OFF; |
1116 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | 1137 | ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid); |
1117 | } | 1138 | } |
1118 | break; | 1139 | break; |
1119 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 1140 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -1121,7 +1142,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1121 | if (tid_data->tfds_in_queue == 0) { | 1142 | if (tid_data->tfds_in_queue == 0) { |
1122 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | 1143 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); |
1123 | tid_data->agg.state = IWL_AGG_ON; | 1144 | tid_data->agg.state = IWL_AGG_ON; |
1124 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | 1145 | ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid); |
1125 | } | 1146 | } |
1126 | break; | 1147 | break; |
1127 | } | 1148 | } |
@@ -1129,14 +1150,14 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1129 | return 0; | 1150 | return 0; |
1130 | } | 1151 | } |
1131 | 1152 | ||
1132 | static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | 1153 | static void iwlagn_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info) |
1133 | { | 1154 | { |
1134 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1155 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data; |
1135 | struct ieee80211_sta *sta; | 1156 | struct ieee80211_sta *sta; |
1136 | struct iwl_station_priv *sta_priv; | 1157 | struct iwl_station_priv *sta_priv; |
1137 | 1158 | ||
1138 | rcu_read_lock(); | 1159 | rcu_read_lock(); |
1139 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | 1160 | sta = ieee80211_find_sta(tx_info->ctx->vif, hdr->addr1); |
1140 | if (sta) { | 1161 | if (sta) { |
1141 | sta_priv = (void *)sta->drv_priv; | 1162 | sta_priv = (void *)sta->drv_priv; |
1142 | /* avoid atomic ops if this isn't a client */ | 1163 | /* avoid atomic ops if this isn't a client */ |
@@ -1146,7 +1167,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | |||
1146 | } | 1167 | } |
1147 | rcu_read_unlock(); | 1168 | rcu_read_unlock(); |
1148 | 1169 | ||
1149 | ieee80211_tx_status_irqsafe(priv->hw, skb); | 1170 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb); |
1150 | } | 1171 | } |
1151 | 1172 | ||
1152 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | 1173 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) |
@@ -1169,7 +1190,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1169 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1190 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1170 | 1191 | ||
1171 | tx_info = &txq->txb[txq->q.read_ptr]; | 1192 | tx_info = &txq->txb[txq->q.read_ptr]; |
1172 | iwlagn_tx_status(priv, tx_info->skb); | 1193 | iwlagn_tx_status(priv, tx_info); |
1173 | 1194 | ||
1174 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; | 1195 | hdr = (struct ieee80211_hdr *)tx_info->skb->data; |
1175 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | 1196 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) |