diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-helpers.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 223 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 19 |
10 files changed, 201 insertions, 168 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 7ce56ff4a525..b4d7460f05ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -835,7 +835,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
835 | */ | 835 | */ |
836 | if (ctx->last_tx_rejected) { | 836 | if (ctx->last_tx_rejected) { |
837 | ctx->last_tx_rejected = false; | 837 | ctx->last_tx_rejected = false; |
838 | iwl_wake_any_queue(priv, ctx); | 838 | iwl_trans_wake_any_queue(trans(priv), |
839 | ctx->ctxid); | ||
839 | } | 840 | } |
840 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 841 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
841 | 842 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index b02125a6a437..32e39059b9bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -278,14 +278,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
278 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 278 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
279 | struct iwl_device_cmd *dev_cmd = NULL; | 279 | struct iwl_device_cmd *dev_cmd = NULL; |
280 | struct iwl_tx_cmd *tx_cmd; | 280 | struct iwl_tx_cmd *tx_cmd; |
281 | int txq_id; | ||
282 | 281 | ||
283 | u16 seq_number = 0; | ||
284 | __le16 fc; | 282 | __le16 fc; |
285 | u8 hdr_len; | 283 | u8 hdr_len; |
286 | u16 len; | 284 | u16 len; |
287 | u8 sta_id; | 285 | u8 sta_id; |
288 | u8 tid = 0; | ||
289 | unsigned long flags; | 286 | unsigned long flags; |
290 | bool is_agg = false; | 287 | bool is_agg = false; |
291 | 288 | ||
@@ -343,50 +340,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
343 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | 340 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); |
344 | } | 341 | } |
345 | 342 | ||
346 | /* | ||
347 | * Send this frame after DTIM -- there's a special queue | ||
348 | * reserved for this for contexts that support AP mode. | ||
349 | */ | ||
350 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
351 | txq_id = ctx->mcast_queue; | ||
352 | /* | ||
353 | * The microcode will clear the more data | ||
354 | * bit in the last frame it transmits. | ||
355 | */ | ||
356 | hdr->frame_control |= | ||
357 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
358 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
359 | txq_id = IWL_AUX_QUEUE; | ||
360 | else | ||
361 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
362 | |||
363 | /* irqs already disabled/saved above when locking priv->shrd->lock */ | 343 | /* irqs already disabled/saved above when locking priv->shrd->lock */ |
364 | spin_lock(&priv->shrd->sta_lock); | 344 | spin_lock(&priv->shrd->sta_lock); |
365 | 345 | ||
366 | if (ieee80211_is_data_qos(fc)) { | ||
367 | u8 *qc = NULL; | ||
368 | struct iwl_tid_data *tid_data; | ||
369 | qc = ieee80211_get_qos_ctl(hdr); | ||
370 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
371 | tid_data = &priv->shrd->tid_data[sta_id][tid]; | ||
372 | |||
373 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
374 | goto drop_unlock_sta; | ||
375 | |||
376 | seq_number = tid_data->seq_number; | ||
377 | seq_number &= IEEE80211_SCTL_SEQ; | ||
378 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
379 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
380 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
381 | seq_number += 0x10; | ||
382 | /* aggregation is on for this <sta,tid> */ | ||
383 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
384 | tid_data->agg.state == IWL_AGG_ON) { | ||
385 | txq_id = tid_data->agg.txq_id; | ||
386 | is_agg = true; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); | 346 | dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC); |
391 | 347 | ||
392 | if (unlikely(!dev_cmd)) | 348 | if (unlikely(!dev_cmd)) |
@@ -416,16 +372,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
416 | info->driver_data[0] = ctx; | 372 | info->driver_data[0] = ctx; |
417 | info->driver_data[1] = dev_cmd; | 373 | info->driver_data[1] = dev_cmd; |
418 | 374 | ||
419 | if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id, fc, is_agg)) | 375 | if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id)) |
420 | goto drop_unlock_sta; | 376 | goto drop_unlock_sta; |
421 | 377 | ||
422 | if (ieee80211_is_data_qos(fc)) { | ||
423 | priv->shrd->tid_data[sta_id][tid].tfds_in_queue++; | ||
424 | if (!ieee80211_has_morefrags(fc)) | ||
425 | priv->shrd->tid_data[sta_id][tid].seq_number = | ||
426 | seq_number; | ||
427 | } | ||
428 | |||
429 | spin_unlock(&priv->shrd->sta_lock); | 378 | spin_unlock(&priv->shrd->sta_lock); |
430 | spin_unlock_irqrestore(&priv->shrd->lock, flags); | 379 | spin_unlock_irqrestore(&priv->shrd->lock, flags); |
431 | 380 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cfb4a4ae52ce..60b964bd5cf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -617,24 +617,6 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc, | |||
617 | 617 | ||
618 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 618 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
619 | { | 619 | { |
620 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
621 | IWL_TX_FIFO_VO, | ||
622 | IWL_TX_FIFO_VI, | ||
623 | IWL_TX_FIFO_BE, | ||
624 | IWL_TX_FIFO_BK, | ||
625 | }; | ||
626 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
627 | 0, 1, 2, 3, | ||
628 | }; | ||
629 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
630 | IWL_TX_FIFO_VO_IPAN, | ||
631 | IWL_TX_FIFO_VI_IPAN, | ||
632 | IWL_TX_FIFO_BE_IPAN, | ||
633 | IWL_TX_FIFO_BK_IPAN, | ||
634 | }; | ||
635 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
636 | 7, 6, 5, 4, | ||
637 | }; | ||
638 | int i; | 620 | int i; |
639 | 621 | ||
640 | /* | 622 | /* |
@@ -656,8 +638,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
656 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; | 638 | priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM; |
657 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; | 639 | priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID; |
658 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | 640 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; |
659 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo; | ||
660 | priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue; | ||
661 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = | 641 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = |
662 | BIT(NL80211_IFTYPE_ADHOC); | 642 | BIT(NL80211_IFTYPE_ADHOC); |
663 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | 643 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = |
@@ -677,9 +657,6 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
677 | priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; | 657 | priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; |
678 | priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; | 658 | priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID; |
679 | priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; | 659 | priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION; |
680 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo; | ||
681 | priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue; | ||
682 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | ||
683 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = | 660 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = |
684 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); | 661 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); |
685 | 662 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 977015b47c64..2e75429f5ac6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -244,13 +244,6 @@ struct iwl_channel_info { | |||
244 | #define IWL_DEFAULT_CMD_QUEUE_NUM 4 | 244 | #define IWL_DEFAULT_CMD_QUEUE_NUM 4 |
245 | #define IWL_IPAN_CMD_QUEUE_NUM 9 | 245 | #define IWL_IPAN_CMD_QUEUE_NUM 9 |
246 | 246 | ||
247 | /* | ||
248 | * This queue number is required for proper operation | ||
249 | * because the ucode will stop/start the scheduler as | ||
250 | * required. | ||
251 | */ | ||
252 | #define IWL_IPAN_MCAST_QUEUE 8 | ||
253 | |||
254 | #define IEEE80211_DATA_LEN 2304 | 247 | #define IEEE80211_DATA_LEN 2304 |
255 | #define IEEE80211_4ADDR_LEN 30 | 248 | #define IEEE80211_4ADDR_LEN 30 |
256 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) | 249 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) |
@@ -965,10 +958,6 @@ struct iwl_notification_wait { | |||
965 | struct iwl_rxon_context { | 958 | struct iwl_rxon_context { |
966 | struct ieee80211_vif *vif; | 959 | struct ieee80211_vif *vif; |
967 | 960 | ||
968 | const u8 *ac_to_fifo; | ||
969 | const u8 *ac_to_queue; | ||
970 | u8 mcast_queue; | ||
971 | |||
972 | /* | 961 | /* |
973 | * We could use the vif to indicate active, but we | 962 | * We could use the vif to indicate active, but we |
974 | * also need it to be active during disabling when | 963 | * also need it to be active during disabling when |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 8ca624d2a8b0..7f92d14083ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -113,19 +113,6 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, | |||
113 | ieee80211_stop_queue(priv->hw, ac); | 113 | ieee80211_stop_queue(priv->hw, ac); |
114 | } | 114 | } |
115 | 115 | ||
116 | static inline void iwl_wake_any_queue(struct iwl_priv *priv, | ||
117 | struct iwl_rxon_context *ctx) | ||
118 | { | ||
119 | u8 ac; | ||
120 | |||
121 | for (ac = 0; ac < AC_NUM; ac++) { | ||
122 | IWL_DEBUG_INFO(priv, "Queue Status: Q[%d] %s\n", | ||
123 | ac, (atomic_read(&priv->queue_stop_count[ac]) > 0) | ||
124 | ? "stopped" : "awake"); | ||
125 | iwl_wake_queue(priv, &priv->txq[ctx->ac_to_queue[ac]]); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | #ifdef ieee80211_stop_queue | 116 | #ifdef ieee80211_stop_queue |
130 | #undef ieee80211_stop_queue | 117 | #undef ieee80211_stop_queue |
131 | #endif | 118 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 2c6659c82f92..8572548dd4a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -699,7 +699,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
699 | ctx->active.bssid_addr)) | 699 | ctx->active.bssid_addr)) |
700 | continue; | 700 | continue; |
701 | ctx->last_tx_rejected = false; | 701 | ctx->last_tx_rejected = false; |
702 | iwl_wake_any_queue(priv, ctx); | 702 | iwl_trans_wake_any_queue(trans(priv), ctx->ctxid); |
703 | } | 703 | } |
704 | } | 704 | } |
705 | 705 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h index f443c106291a..d73ebefa7d05 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-int-pcie.h | |||
@@ -107,6 +107,13 @@ struct iwl_dma_ptr { | |||
107 | size_t size; | 107 | size_t size; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | /* | ||
111 | * This queue number is required for proper operation | ||
112 | * because the ucode will stop/start the scheduler as | ||
113 | * required. | ||
114 | */ | ||
115 | #define IWL_IPAN_MCAST_QUEUE 8 | ||
116 | |||
110 | /** | 117 | /** |
111 | * struct iwl_trans_pcie - PCIe transport specific data | 118 | * struct iwl_trans_pcie - PCIe transport specific data |
112 | * @rxq: all the RX queue data | 119 | * @rxq: all the RX queue data |
@@ -115,6 +122,9 @@ struct iwl_dma_ptr { | |||
115 | * @scd_base_addr: scheduler sram base address in SRAM | 122 | * @scd_base_addr: scheduler sram base address in SRAM |
116 | * @scd_bc_tbls: pointer to the byte count table of the scheduler | 123 | * @scd_bc_tbls: pointer to the byte count table of the scheduler |
117 | * @kw: keep warm address | 124 | * @kw: keep warm address |
125 | * @ac_to_fifo: to what fifo is a specifc AC mapped ? | ||
126 | * @ac_to_queue: to what tx queue is a specifc AC mapped ? | ||
127 | * @mcast_queue: | ||
118 | */ | 128 | */ |
119 | struct iwl_trans_pcie { | 129 | struct iwl_trans_pcie { |
120 | struct iwl_rx_queue rxq; | 130 | struct iwl_rx_queue rxq; |
@@ -136,6 +146,10 @@ struct iwl_trans_pcie { | |||
136 | u32 scd_base_addr; | 146 | u32 scd_base_addr; |
137 | struct iwl_dma_ptr scd_bc_tbls; | 147 | struct iwl_dma_ptr scd_bc_tbls; |
138 | struct iwl_dma_ptr kw; | 148 | struct iwl_dma_ptr kw; |
149 | |||
150 | const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; | ||
151 | const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; | ||
152 | u8 mcast_queue[NUM_IWL_RXON_CTX]; | ||
139 | }; | 153 | }; |
140 | 154 | ||
141 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 155 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c index 96ad0afd185e..6af33104228a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c | |||
@@ -424,10 +424,12 @@ void iwl_trans_tx_queue_set_status(struct iwl_priv *priv, | |||
424 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | 424 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); |
425 | } | 425 | } |
426 | 426 | ||
427 | static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) | 427 | static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, |
428 | u8 ctx, u16 tid) | ||
428 | { | 429 | { |
430 | const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx]; | ||
429 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | 431 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) |
430 | return ctx->ac_to_fifo[tid_to_ac[tid]]; | 432 | return ac_to_fifo[tid_to_ac[tid]]; |
431 | 433 | ||
432 | /* no support for TIDs 8-15 yet */ | 434 | /* no support for TIDs 8-15 yet */ |
433 | return -EINVAL; | 435 | return -EINVAL; |
@@ -451,7 +453,7 @@ void iwl_trans_pcie_txq_agg_setup(struct iwl_priv *priv, | |||
451 | if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) | 453 | if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) |
452 | return; | 454 | return; |
453 | 455 | ||
454 | tx_fifo = get_fifo_from_tid(&priv->contexts[ctx], tid); | 456 | tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid); |
455 | if (WARN_ON(tx_fifo < 0)) { | 457 | if (WARN_ON(tx_fifo < 0)) { |
456 | IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); | 458 | IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); |
457 | return; | 459 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 7de042c6c258..133b227cb64d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -714,12 +714,75 @@ static int iwl_trans_pcie_prepare_card_hw(struct iwl_trans *trans) | |||
714 | return ret; | 714 | return ret; |
715 | } | 715 | } |
716 | 716 | ||
717 | #define IWL_AC_UNSET -1 | ||
718 | |||
719 | struct queue_to_fifo_ac { | ||
720 | s8 fifo, ac; | ||
721 | }; | ||
722 | |||
723 | static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { | ||
724 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
725 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
726 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
727 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
728 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
729 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
730 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
731 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
732 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
733 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
734 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
735 | }; | ||
736 | |||
737 | static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { | ||
738 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
739 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
740 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
741 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
742 | { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, | ||
743 | { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, | ||
744 | { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, | ||
745 | { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, | ||
746 | { IWL_TX_FIFO_BE_IPAN, 2, }, | ||
747 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
748 | { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, | ||
749 | }; | ||
750 | |||
751 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
752 | IWL_TX_FIFO_VO, | ||
753 | IWL_TX_FIFO_VI, | ||
754 | IWL_TX_FIFO_BE, | ||
755 | IWL_TX_FIFO_BK, | ||
756 | }; | ||
757 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
758 | 0, 1, 2, 3, | ||
759 | }; | ||
760 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
761 | IWL_TX_FIFO_VO_IPAN, | ||
762 | IWL_TX_FIFO_VI_IPAN, | ||
763 | IWL_TX_FIFO_BE_IPAN, | ||
764 | IWL_TX_FIFO_BK_IPAN, | ||
765 | }; | ||
766 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
767 | 7, 6, 5, 4, | ||
768 | }; | ||
769 | |||
717 | static int iwl_trans_pcie_start_device(struct iwl_trans *trans) | 770 | static int iwl_trans_pcie_start_device(struct iwl_trans *trans) |
718 | { | 771 | { |
719 | int ret; | 772 | int ret; |
720 | struct iwl_priv *priv = priv(trans); | 773 | struct iwl_priv *priv = priv(trans); |
774 | struct iwl_trans_pcie *trans_pcie = | ||
775 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
721 | 776 | ||
722 | priv->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; | 777 | priv->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER; |
778 | trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; | ||
779 | trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; | ||
780 | |||
781 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; | ||
782 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; | ||
783 | |||
784 | trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; | ||
785 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; | ||
723 | 786 | ||
724 | if ((hw_params(priv).sku & EEPROM_SKU_CAP_AMT_ENABLE) && | 787 | if ((hw_params(priv).sku & EEPROM_SKU_CAP_AMT_ENABLE) && |
725 | iwl_trans_pcie_prepare_card_hw(trans)) { | 788 | iwl_trans_pcie_prepare_card_hw(trans)) { |
@@ -773,39 +836,6 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | |||
773 | iwl_write_prph(bus(trans), SCD_TXFACT, mask); | 836 | iwl_write_prph(bus(trans), SCD_TXFACT, mask); |
774 | } | 837 | } |
775 | 838 | ||
776 | #define IWL_AC_UNSET -1 | ||
777 | |||
778 | struct queue_to_fifo_ac { | ||
779 | s8 fifo, ac; | ||
780 | }; | ||
781 | |||
782 | static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { | ||
783 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
784 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
785 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
786 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
787 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
788 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
789 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
790 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
791 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
792 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
793 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
794 | }; | ||
795 | |||
796 | static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { | ||
797 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
798 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
799 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
800 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
801 | { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, | ||
802 | { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, | ||
803 | { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, | ||
804 | { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, | ||
805 | { IWL_TX_FIFO_BE_IPAN, 2, }, | ||
806 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
807 | { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, | ||
808 | }; | ||
809 | static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) | 839 | static void iwl_trans_pcie_tx_start(struct iwl_trans *trans) |
810 | { | 840 | { |
811 | const struct queue_to_fifo_ac *queue_to_fifo; | 841 | const struct queue_to_fifo_ac *queue_to_fifo; |
@@ -1012,22 +1042,75 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1012 | iwl_apm_stop(priv(trans)); | 1042 | iwl_apm_stop(priv(trans)); |
1013 | } | 1043 | } |
1014 | 1044 | ||
1015 | static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | 1045 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
1016 | struct iwl_device_cmd *dev_cmd, int txq_id, | 1046 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) |
1017 | __le16 fc, bool ampdu) | ||
1018 | { | 1047 | { |
1019 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 1048 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1020 | struct iwl_queue *q = &txq->q; | 1049 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1050 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1021 | struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; | 1051 | struct iwl_tx_cmd *tx_cmd = &dev_cmd->cmd.tx; |
1022 | struct iwl_cmd_meta *out_meta; | 1052 | struct iwl_cmd_meta *out_meta; |
1053 | struct iwl_tx_queue *txq; | ||
1054 | struct iwl_queue *q; | ||
1023 | 1055 | ||
1024 | dma_addr_t phys_addr = 0; | 1056 | dma_addr_t phys_addr = 0; |
1025 | dma_addr_t txcmd_phys; | 1057 | dma_addr_t txcmd_phys; |
1026 | dma_addr_t scratch_phys; | 1058 | dma_addr_t scratch_phys; |
1027 | u16 len, firstlen, secondlen; | 1059 | u16 len, firstlen, secondlen; |
1060 | u16 seq_number = 0; | ||
1028 | u8 wait_write_ptr = 0; | 1061 | u8 wait_write_ptr = 0; |
1062 | u8 txq_id; | ||
1063 | u8 tid = 0; | ||
1064 | bool is_agg = false; | ||
1065 | __le16 fc = hdr->frame_control; | ||
1029 | u8 hdr_len = ieee80211_hdrlen(fc); | 1066 | u8 hdr_len = ieee80211_hdrlen(fc); |
1030 | 1067 | ||
1068 | /* | ||
1069 | * Send this frame after DTIM -- there's a special queue | ||
1070 | * reserved for this for contexts that support AP mode. | ||
1071 | */ | ||
1072 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
1073 | txq_id = trans_pcie->mcast_queue[ctx]; | ||
1074 | |||
1075 | /* | ||
1076 | * The microcode will clear the more data | ||
1077 | * bit in the last frame it transmits. | ||
1078 | */ | ||
1079 | hdr->frame_control |= | ||
1080 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1081 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
1082 | txq_id = IWL_AUX_QUEUE; | ||
1083 | else | ||
1084 | txq_id = | ||
1085 | trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; | ||
1086 | |||
1087 | if (ieee80211_is_data_qos(fc)) { | ||
1088 | u8 *qc = NULL; | ||
1089 | struct iwl_tid_data *tid_data; | ||
1090 | qc = ieee80211_get_qos_ctl(hdr); | ||
1091 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
1092 | tid_data = &trans->shrd->tid_data[sta_id][tid]; | ||
1093 | |||
1094 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | ||
1095 | return -1; | ||
1096 | |||
1097 | seq_number = tid_data->seq_number; | ||
1098 | seq_number &= IEEE80211_SCTL_SEQ; | ||
1099 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
1100 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
1101 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
1102 | seq_number += 0x10; | ||
1103 | /* aggregation is on for this <sta,tid> */ | ||
1104 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
1105 | tid_data->agg.state == IWL_AGG_ON) { | ||
1106 | txq_id = tid_data->agg.txq_id; | ||
1107 | is_agg = true; | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | txq = &priv(trans)->txq[txq_id]; | ||
1112 | q = &txq->q; | ||
1113 | |||
1031 | /* Set up driver data for this TFD */ | 1114 | /* Set up driver data for this TFD */ |
1032 | txq->skbs[q->write_ptr] = skb; | 1115 | txq->skbs[q->write_ptr] = skb; |
1033 | txq->cmd[q->write_ptr] = dev_cmd; | 1116 | txq->cmd[q->write_ptr] = dev_cmd; |
@@ -1058,10 +1141,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | |||
1058 | 1141 | ||
1059 | /* Physical address of this Tx command's header (not MAC header!), | 1142 | /* Physical address of this Tx command's header (not MAC header!), |
1060 | * within command buffer array. */ | 1143 | * within command buffer array. */ |
1061 | txcmd_phys = dma_map_single(priv->bus->dev, | 1144 | txcmd_phys = dma_map_single(bus(trans)->dev, |
1062 | &dev_cmd->hdr, firstlen, | 1145 | &dev_cmd->hdr, firstlen, |
1063 | DMA_BIDIRECTIONAL); | 1146 | DMA_BIDIRECTIONAL); |
1064 | if (unlikely(dma_mapping_error(priv->bus->dev, txcmd_phys))) | 1147 | if (unlikely(dma_mapping_error(bus(trans)->dev, txcmd_phys))) |
1065 | return -1; | 1148 | return -1; |
1066 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 1149 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
1067 | dma_unmap_len_set(out_meta, len, firstlen); | 1150 | dma_unmap_len_set(out_meta, len, firstlen); |
@@ -1077,10 +1160,10 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | |||
1077 | * if any (802.11 null frames have no payload). */ | 1160 | * if any (802.11 null frames have no payload). */ |
1078 | secondlen = skb->len - hdr_len; | 1161 | secondlen = skb->len - hdr_len; |
1079 | if (secondlen > 0) { | 1162 | if (secondlen > 0) { |
1080 | phys_addr = dma_map_single(priv->bus->dev, skb->data + hdr_len, | 1163 | phys_addr = dma_map_single(bus(trans)->dev, skb->data + hdr_len, |
1081 | secondlen, DMA_TO_DEVICE); | 1164 | secondlen, DMA_TO_DEVICE); |
1082 | if (unlikely(dma_mapping_error(priv->bus->dev, phys_addr))) { | 1165 | if (unlikely(dma_mapping_error(bus(trans)->dev, phys_addr))) { |
1083 | dma_unmap_single(priv->bus->dev, | 1166 | dma_unmap_single(bus(trans)->dev, |
1084 | dma_unmap_addr(out_meta, mapping), | 1167 | dma_unmap_addr(out_meta, mapping), |
1085 | dma_unmap_len(out_meta, len), | 1168 | dma_unmap_len(out_meta, len), |
1086 | DMA_BIDIRECTIONAL); | 1169 | DMA_BIDIRECTIONAL); |
@@ -1089,36 +1172,35 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | |||
1089 | } | 1172 | } |
1090 | 1173 | ||
1091 | /* Attach buffers to TFD */ | 1174 | /* Attach buffers to TFD */ |
1092 | iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, txcmd_phys, | 1175 | iwlagn_txq_attach_buf_to_tfd(trans, txq, txcmd_phys, firstlen, 1); |
1093 | firstlen, 1); | ||
1094 | if (secondlen > 0) | 1176 | if (secondlen > 0) |
1095 | iwlagn_txq_attach_buf_to_tfd(trans(priv), txq, phys_addr, | 1177 | iwlagn_txq_attach_buf_to_tfd(trans, txq, phys_addr, |
1096 | secondlen, 0); | 1178 | secondlen, 0); |
1097 | 1179 | ||
1098 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | 1180 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + |
1099 | offsetof(struct iwl_tx_cmd, scratch); | 1181 | offsetof(struct iwl_tx_cmd, scratch); |
1100 | 1182 | ||
1101 | /* take back ownership of DMA buffer to enable update */ | 1183 | /* take back ownership of DMA buffer to enable update */ |
1102 | dma_sync_single_for_cpu(priv->bus->dev, txcmd_phys, firstlen, | 1184 | dma_sync_single_for_cpu(bus(trans)->dev, txcmd_phys, firstlen, |
1103 | DMA_BIDIRECTIONAL); | 1185 | DMA_BIDIRECTIONAL); |
1104 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | 1186 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); |
1105 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | 1187 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); |
1106 | 1188 | ||
1107 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", | 1189 | IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n", |
1108 | le16_to_cpu(dev_cmd->hdr.sequence)); | 1190 | le16_to_cpu(dev_cmd->hdr.sequence)); |
1109 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | 1191 | IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); |
1110 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | 1192 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); |
1111 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | 1193 | iwl_print_hex_dump(trans, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); |
1112 | 1194 | ||
1113 | /* Set up entry for this TFD in Tx byte-count array */ | 1195 | /* Set up entry for this TFD in Tx byte-count array */ |
1114 | if (ampdu) | 1196 | if (is_agg) |
1115 | iwl_trans_txq_update_byte_cnt_tbl(trans(priv), txq, | 1197 | iwl_trans_txq_update_byte_cnt_tbl(trans, txq, |
1116 | le16_to_cpu(tx_cmd->len)); | 1198 | le16_to_cpu(tx_cmd->len)); |
1117 | 1199 | ||
1118 | dma_sync_single_for_device(priv->bus->dev, txcmd_phys, firstlen, | 1200 | dma_sync_single_for_device(bus(trans)->dev, txcmd_phys, firstlen, |
1119 | DMA_BIDIRECTIONAL); | 1201 | DMA_BIDIRECTIONAL); |
1120 | 1202 | ||
1121 | trace_iwlwifi_dev_tx(priv, | 1203 | trace_iwlwifi_dev_tx(priv(trans), |
1122 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | 1204 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], |
1123 | sizeof(struct iwl_tfd), | 1205 | sizeof(struct iwl_tfd), |
1124 | &dev_cmd->hdr, firstlen, | 1206 | &dev_cmd->hdr, firstlen, |
@@ -1126,7 +1208,14 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | |||
1126 | 1208 | ||
1127 | /* Tell device the write index *just past* this latest filled TFD */ | 1209 | /* Tell device the write index *just past* this latest filled TFD */ |
1128 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1210 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1129 | iwl_txq_update_write_ptr(trans(priv), txq); | 1211 | iwl_txq_update_write_ptr(trans, txq); |
1212 | |||
1213 | if (ieee80211_is_data_qos(fc)) { | ||
1214 | trans->shrd->tid_data[sta_id][tid].tfds_in_queue++; | ||
1215 | if (!ieee80211_has_morefrags(fc)) | ||
1216 | trans->shrd->tid_data[sta_id][tid].seq_number = | ||
1217 | seq_number; | ||
1218 | } | ||
1130 | 1219 | ||
1131 | /* | 1220 | /* |
1132 | * At this point the frame is "transmitted" successfully | 1221 | * At this point the frame is "transmitted" successfully |
@@ -1137,9 +1226,9 @@ static int iwl_trans_pcie_tx(struct iwl_priv *priv, struct sk_buff *skb, | |||
1137 | if (iwl_queue_space(q) < q->high_mark) { | 1226 | if (iwl_queue_space(q) < q->high_mark) { |
1138 | if (wait_write_ptr) { | 1227 | if (wait_write_ptr) { |
1139 | txq->need_update = 1; | 1228 | txq->need_update = 1; |
1140 | iwl_txq_update_write_ptr(trans(priv), txq); | 1229 | iwl_txq_update_write_ptr(trans, txq); |
1141 | } else { | 1230 | } else { |
1142 | iwl_stop_queue(priv, txq); | 1231 | iwl_stop_queue(priv(trans), txq); |
1143 | } | 1232 | } |
1144 | } | 1233 | } |
1145 | return 0; | 1234 | return 0; |
@@ -1262,6 +1351,23 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans) | |||
1262 | 1351 | ||
1263 | #endif /* CONFIG_PM */ | 1352 | #endif /* CONFIG_PM */ |
1264 | 1353 | ||
1354 | static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans, | ||
1355 | u8 ctx) | ||
1356 | { | ||
1357 | u8 ac, txq_id; | ||
1358 | struct iwl_trans_pcie *trans_pcie = | ||
1359 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1360 | |||
1361 | for (ac = 0; ac < AC_NUM; ac++) { | ||
1362 | txq_id = trans_pcie->ac_to_queue[ctx][ac]; | ||
1363 | IWL_DEBUG_INFO(trans, "Queue Status: Q[%d] %s\n", | ||
1364 | ac, | ||
1365 | (atomic_read(&priv(trans)->queue_stop_count[ac]) > 0) | ||
1366 | ? "stopped" : "awake"); | ||
1367 | iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]); | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1265 | const struct iwl_trans_ops trans_ops_pcie; | 1371 | const struct iwl_trans_ops trans_ops_pcie; |
1266 | 1372 | ||
1267 | static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | 1373 | static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) |
@@ -1842,6 +1948,7 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1842 | .stop_device = iwl_trans_pcie_stop_device, | 1948 | .stop_device = iwl_trans_pcie_stop_device, |
1843 | 1949 | ||
1844 | .tx_start = iwl_trans_pcie_tx_start, | 1950 | .tx_start = iwl_trans_pcie_tx_start, |
1951 | .wake_any_queue = iwl_trans_pcie_wake_any_queue, | ||
1845 | 1952 | ||
1846 | .send_cmd = iwl_trans_pcie_send_cmd, | 1953 | .send_cmd = iwl_trans_pcie_send_cmd, |
1847 | .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, | 1954 | .send_cmd_pdu = iwl_trans_pcie_send_cmd_pdu, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0691d39bce05..0fee8840c0aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -88,6 +88,7 @@ struct iwl_device_cmd; | |||
88 | * probe. | 88 | * probe. |
89 | * @tx_start: starts and configures all the Tx fifo - usually done once the fw | 89 | * @tx_start: starts and configures all the Tx fifo - usually done once the fw |
90 | * is alive. | 90 | * is alive. |
91 | * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* | ||
91 | * @stop_device:stops the whole device (embedded CPU put to reset) | 92 | * @stop_device:stops the whole device (embedded CPU put to reset) |
92 | * @send_cmd:send a host command | 93 | * @send_cmd:send a host command |
93 | * @send_cmd_pdu:send a host command: flags can be CMD_* | 94 | * @send_cmd_pdu:send a host command: flags can be CMD_* |
@@ -113,13 +114,14 @@ struct iwl_trans_ops { | |||
113 | void (*stop_device)(struct iwl_trans *trans); | 114 | void (*stop_device)(struct iwl_trans *trans); |
114 | void (*tx_start)(struct iwl_trans *trans); | 115 | void (*tx_start)(struct iwl_trans *trans); |
115 | 116 | ||
117 | void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx); | ||
118 | |||
116 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 119 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
117 | 120 | ||
118 | int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, | 121 | int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len, |
119 | const void *data); | 122 | const void *data); |
120 | int (*tx)(struct iwl_priv *priv, struct sk_buff *skb, | 123 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, |
121 | struct iwl_device_cmd *dev_cmd, | 124 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id); |
122 | int txq_id, __le16 fc, bool ampdu); | ||
123 | void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, | 125 | void (*reclaim)(struct iwl_trans *trans, int txq_id, int ssn, |
124 | u32 status, struct sk_buff_head *skbs); | 126 | u32 status, struct sk_buff_head *skbs); |
125 | 127 | ||
@@ -178,6 +180,12 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans) | |||
178 | trans->ops->tx_start(trans); | 180 | trans->ops->tx_start(trans); |
179 | } | 181 | } |
180 | 182 | ||
183 | static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx) | ||
184 | { | ||
185 | trans->ops->wake_any_queue(trans, ctx); | ||
186 | } | ||
187 | |||
188 | |||
181 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 189 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, |
182 | struct iwl_host_cmd *cmd) | 190 | struct iwl_host_cmd *cmd) |
183 | { | 191 | { |
@@ -191,10 +199,9 @@ static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, | |||
191 | } | 199 | } |
192 | 200 | ||
193 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 201 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
194 | struct iwl_device_cmd *dev_cmd, | 202 | struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id) |
195 | int txq_id, __le16 fc, bool ampdu) | ||
196 | { | 203 | { |
197 | return trans->ops->tx(priv(trans), skb, dev_cmd, txq_id, fc, ampdu); | 204 | return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id); |
198 | } | 205 | } |
199 | 206 | ||
200 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, | 207 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int txq_id, |