diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-08-23 04:46:51 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-08-27 12:29:32 -0400 |
commit | e72f368be61d9835c98cd00ee1f330d28e2488ef (patch) | |
tree | 5f84437d3933928b367528e2d902d6cffb929243 /drivers | |
parent | 60744f62971cfa80cab36ab8c12afeae371fbe8b (diff) |
iwlagn: queue frames according to context
Frames for different contexts need to be put
on different queues, and multicast after DTIM
frames have a special queue yet which also
depends on the context, so put all this into
the context.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 5 |
3 files changed, 51 insertions, 23 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 64daddd92279..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; |
@@ -333,11 +321,6 @@ 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 | */ |
@@ -595,7 +578,20 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
595 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | 578 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); |
596 | } | 579 | } |
597 | 580 | ||
598 | 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)]; | ||
599 | 595 | ||
600 | /* irqs already disabled/saved above when locking priv->lock */ | 596 | /* irqs already disabled/saved above when locking priv->lock */ |
601 | spin_lock(&priv->sta_lock); | 597 | spin_lock(&priv->sta_lock); |
@@ -984,7 +980,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
984 | unsigned long flags; | 980 | unsigned long flags; |
985 | struct iwl_tid_data *tid_data; | 981 | struct iwl_tid_data *tid_data; |
986 | 982 | ||
987 | tx_fifo = get_fifo_from_tid(tid); | 983 | tx_fifo = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); |
988 | if (unlikely(tx_fifo < 0)) | 984 | if (unlikely(tx_fifo < 0)) |
989 | return tx_fifo; | 985 | return tx_fifo; |
990 | 986 | ||
@@ -1045,7 +1041,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
1045 | int write_ptr, read_ptr; | 1041 | int write_ptr, read_ptr; |
1046 | unsigned long flags; | 1042 | unsigned long flags; |
1047 | 1043 | ||
1048 | tx_fifo_id = get_fifo_from_tid(tid); | 1044 | tx_fifo_id = get_fifo_from_tid(iwl_rxon_ctx_from_vif(vif), tid); |
1049 | if (unlikely(tx_fifo_id < 0)) | 1045 | if (unlikely(tx_fifo_id < 0)) |
1050 | return tx_fifo_id; | 1046 | return tx_fifo_id; |
1051 | 1047 | ||
@@ -1133,7 +1129,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, | |||
1133 | if ((txq_id == tid_data->agg.txq_id) && | 1129 | if ((txq_id == tid_data->agg.txq_id) && |
1134 | (q->read_ptr == q->write_ptr)) { | 1130 | (q->read_ptr == q->write_ptr)) { |
1135 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | 1131 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); |
1136 | int tx_fifo = get_fifo_from_tid(tid); | 1132 | int tx_fifo = get_fifo_from_tid(ctx, tid); |
1137 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | 1133 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); |
1138 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | 1134 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, |
1139 | ssn, tx_fifo); | 1135 | ssn, tx_fifo); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b07d397ed5a7..143c12a29fd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -4196,6 +4196,28 @@ static int iwl_set_hw_params(struct iwl_priv *priv) | |||
4196 | return priv->cfg->ops->lib->set_hw_params(priv); | 4196 | return priv->cfg->ops->lib->set_hw_params(priv); |
4197 | } | 4197 | } |
4198 | 4198 | ||
4199 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
4200 | IWL_TX_FIFO_VO, | ||
4201 | IWL_TX_FIFO_VI, | ||
4202 | IWL_TX_FIFO_BE, | ||
4203 | IWL_TX_FIFO_BK, | ||
4204 | }; | ||
4205 | |||
4206 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
4207 | 0, 1, 2, 3, | ||
4208 | }; | ||
4209 | |||
4210 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
4211 | IWL_TX_FIFO_VO_IPAN, | ||
4212 | IWL_TX_FIFO_VI_IPAN, | ||
4213 | IWL_TX_FIFO_BE_IPAN, | ||
4214 | IWL_TX_FIFO_BK_IPAN, | ||
4215 | }; | ||
4216 | |||
4217 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
4218 | 7, 6, 5, 4, | ||
4219 | }; | ||
4220 | |||
4199 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 4221 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
4200 | { | 4222 | { |
4201 | int err = 0, i; | 4223 | int err = 0, i; |
@@ -4242,6 +4264,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4242 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; | 4264 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; |
4243 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; | 4265 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; |
4244 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | 4266 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; |
4267 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; | ||
4268 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; | ||
4245 | 4269 | ||
4246 | priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; | 4270 | priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; |
4247 | priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; | 4271 | priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; |
@@ -4251,6 +4275,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4251 | priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; | 4275 | priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; |
4252 | priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; | 4276 | priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; |
4253 | priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; | 4277 | priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; |
4278 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; | ||
4279 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; | ||
4280 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | ||
4254 | 4281 | ||
4255 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 4282 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
4256 | 4283 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 99b6b81be7e2..422c71e122f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1111,6 +1111,11 @@ enum iwl_rxon_context_id { | |||
1111 | 1111 | ||
1112 | struct iwl_rxon_context { | 1112 | struct iwl_rxon_context { |
1113 | struct ieee80211_vif *vif; | 1113 | struct ieee80211_vif *vif; |
1114 | |||
1115 | const u8 *ac_to_fifo; | ||
1116 | const u8 *ac_to_queue; | ||
1117 | u8 mcast_queue; | ||
1118 | |||
1114 | enum iwl_rxon_context_id ctxid; | 1119 | enum iwl_rxon_context_id ctxid; |
1115 | /* | 1120 | /* |
1116 | * We declare this const so it can only be | 1121 | * We declare this const so it can only be |