diff options
author | Johannes Berg <johannes.berg@intel.com> | 2014-08-01 06:17:40 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-09-03 15:49:05 -0400 |
commit | d4578ea810ce468fdb8e1b7014818c31db9be5e2 (patch) | |
tree | af2b99803e49a976ccc17bf21506e379087a0c3e | |
parent | 0ade579cce06806353e5f601ff3285a0a7d1e398 (diff) |
iwlwifi: trans: allow skipping scheduler hardware config
In a later patch, the hardware configuration will be moved to
firmware. Prepare for this by allowing hardware configuration
in the transport to be skipped by not passing a configuration
on enable and passing configure_scd=false on disable.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tx.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 47 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tx.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 99 |
7 files changed, 104 insertions, 65 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 3255a1723d17..d1ce3ce13591 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -580,7 +580,7 @@ turn_off: | |||
580 | * time, or we hadn't time to drain the AC queues. | 580 | * time, or we hadn't time to drain the AC queues. |
581 | */ | 581 | */ |
582 | if (agg_state == IWL_AGG_ON) | 582 | if (agg_state == IWL_AGG_ON) |
583 | iwl_trans_txq_disable(priv->trans, txq_id); | 583 | iwl_trans_txq_disable(priv->trans, txq_id, true); |
584 | else | 584 | else |
585 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | 585 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", |
586 | agg_state); | 586 | agg_state); |
@@ -686,7 +686,7 @@ int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
686 | * time, or we hadn't time to drain the AC queues. | 686 | * time, or we hadn't time to drain the AC queues. |
687 | */ | 687 | */ |
688 | if (agg_state == IWL_AGG_ON) | 688 | if (agg_state == IWL_AGG_ON) |
689 | iwl_trans_txq_disable(priv->trans, txq_id); | 689 | iwl_trans_txq_disable(priv->trans, txq_id, true); |
690 | else | 690 | else |
691 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | 691 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", |
692 | agg_state); | 692 | agg_state); |
@@ -781,7 +781,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
781 | "Can continue DELBA flow ssn = next_recl = %d\n", | 781 | "Can continue DELBA flow ssn = next_recl = %d\n", |
782 | tid_data->next_reclaimed); | 782 | tid_data->next_reclaimed); |
783 | iwl_trans_txq_disable(priv->trans, | 783 | iwl_trans_txq_disable(priv->trans, |
784 | tid_data->agg.txq_id); | 784 | tid_data->agg.txq_id, true); |
785 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | 785 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); |
786 | tid_data->agg.state = IWL_AGG_OFF; | 786 | tid_data->agg.state = IWL_AGG_OFF; |
787 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); | 787 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c198dde339c6..dd3aefc0ad2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -444,7 +444,9 @@ struct iwl_trans_txq_scd_cfg { | |||
444 | * Must be atomic | 444 | * Must be atomic |
445 | * @txq_enable: setup a queue. To setup an AC queue, use the | 445 | * @txq_enable: setup a queue. To setup an AC queue, use the |
446 | * iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before | 446 | * iwl_trans_ac_txq_enable wrapper. fw_alive must have been called before |
447 | * this one. The op_mode must not configure the HCMD queue. May sleep. | 447 | * this one. The op_mode must not configure the HCMD queue. The scheduler |
448 | * configuration may be %NULL, in which case the hardware will not be | ||
449 | * configured. May sleep. | ||
448 | * @txq_disable: de-configure a Tx queue to send AMPDUs | 450 | * @txq_disable: de-configure a Tx queue to send AMPDUs |
449 | * Must be atomic | 451 | * Must be atomic |
450 | * @wait_tx_queue_empty: wait until tx queues are empty. May sleep. | 452 | * @wait_tx_queue_empty: wait until tx queues are empty. May sleep. |
@@ -501,7 +503,8 @@ struct iwl_trans_ops { | |||
501 | 503 | ||
502 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, | 504 | void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn, |
503 | const struct iwl_trans_txq_scd_cfg *cfg); | 505 | const struct iwl_trans_txq_scd_cfg *cfg); |
504 | void (*txq_disable)(struct iwl_trans *trans, int queue); | 506 | void (*txq_disable)(struct iwl_trans *trans, int queue, |
507 | bool configure_scd); | ||
505 | 508 | ||
506 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 509 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
507 | int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); | 510 | int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); |
@@ -773,9 +776,22 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | |||
773 | trans->ops->reclaim(trans, queue, ssn, skbs); | 776 | trans->ops->reclaim(trans, queue, ssn, skbs); |
774 | } | 777 | } |
775 | 778 | ||
776 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) | 779 | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue, |
780 | bool configure_scd) | ||
777 | { | 781 | { |
778 | trans->ops->txq_disable(trans, queue); | 782 | trans->ops->txq_disable(trans, queue, configure_scd); |
783 | } | ||
784 | |||
785 | static inline void | ||
786 | iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn, | ||
787 | const struct iwl_trans_txq_scd_cfg *cfg) | ||
788 | { | ||
789 | might_sleep(); | ||
790 | |||
791 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) | ||
792 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | ||
793 | |||
794 | trans->ops->txq_enable(trans, queue, ssn, cfg); | ||
779 | } | 795 | } |
780 | 796 | ||
781 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | 797 | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, |
@@ -789,19 +805,26 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | |||
789 | .frame_limit = frame_limit, | 805 | .frame_limit = frame_limit, |
790 | }; | 806 | }; |
791 | 807 | ||
792 | might_sleep(); | 808 | iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg); |
793 | |||
794 | if (unlikely((trans->state != IWL_TRANS_FW_ALIVE))) | ||
795 | IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); | ||
796 | |||
797 | trans->ops->txq_enable(trans, queue, ssn, &cfg); | ||
798 | } | 809 | } |
799 | 810 | ||
800 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, | 811 | static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, |
801 | int fifo) | 812 | int fifo) |
802 | { | 813 | { |
803 | iwl_trans_txq_enable(trans, queue, fifo, -1, | 814 | struct iwl_trans_txq_scd_cfg cfg = { |
804 | IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0); | 815 | .fifo = fifo, |
816 | .sta_id = -1, | ||
817 | .tid = IWL_MAX_TID_COUNT, | ||
818 | .frame_limit = IWL_FRAME_LIMIT, | ||
819 | }; | ||
820 | |||
821 | iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg); | ||
822 | } | ||
823 | |||
824 | static inline void | ||
825 | iwl_trans_txq_enable_no_scd(struct iwl_trans *trans, int queue, u16 ssn) | ||
826 | { | ||
827 | iwl_trans_txq_enable_cfg(trans, queue, ssn, NULL); | ||
805 | } | 828 | } |
806 | 829 | ||
807 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, | 830 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 0e523e28cabf..08162043c897 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -452,14 +452,16 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
452 | 452 | ||
453 | switch (vif->type) { | 453 | switch (vif->type) { |
454 | case NL80211_IFTYPE_P2P_DEVICE: | 454 | case NL80211_IFTYPE_P2P_DEVICE: |
455 | iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE); | 455 | iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE, |
456 | true); | ||
456 | break; | 457 | break; |
457 | case NL80211_IFTYPE_AP: | 458 | case NL80211_IFTYPE_AP: |
458 | iwl_trans_txq_disable(mvm->trans, vif->cab_queue); | 459 | iwl_trans_txq_disable(mvm->trans, vif->cab_queue, true); |
459 | /* fall through */ | 460 | /* fall through */ |
460 | default: | 461 | default: |
461 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 462 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
462 | iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac]); | 463 | iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac], |
464 | true); | ||
463 | } | 465 | } |
464 | } | 466 | } |
465 | 467 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 763548880399..863a5363c416 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -910,7 +910,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
910 | } | 910 | } |
911 | 911 | ||
912 | tid_data->ssn = 0xffff; | 912 | tid_data->ssn = 0xffff; |
913 | iwl_trans_txq_disable(mvm->trans, txq_id); | 913 | iwl_trans_txq_disable(mvm->trans, txq_id, true); |
914 | /* fall through */ | 914 | /* fall through */ |
915 | case IWL_AGG_STARTING: | 915 | case IWL_AGG_STARTING: |
916 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 916 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -965,7 +965,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
965 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) | 965 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) |
966 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); | 966 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); |
967 | 967 | ||
968 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); | 968 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true); |
969 | } | 969 | } |
970 | 970 | ||
971 | mvm->queue_to_mac80211[tid_data->txq_id] = | 971 | mvm->queue_to_mac80211[tid_data->txq_id] = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index dbc870713882..748b16993bda 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -482,7 +482,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, | |||
482 | IWL_DEBUG_TX_QUEUES(mvm, | 482 | IWL_DEBUG_TX_QUEUES(mvm, |
483 | "Can continue DELBA flow ssn = next_recl = %d\n", | 483 | "Can continue DELBA flow ssn = next_recl = %d\n", |
484 | tid_data->next_reclaimed); | 484 | tid_data->next_reclaimed); |
485 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id); | 485 | iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true); |
486 | tid_data->state = IWL_AGG_OFF; | 486 | tid_data->state = IWL_AGG_OFF; |
487 | /* | 487 | /* |
488 | * we can't hold the mutex - but since we are after a sequence | 488 | * we can't hold the mutex - but since we are after a sequence |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 5760405a9cad..163aac563f90 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -366,7 +366,8 @@ int iwl_pcie_tx_stop(struct iwl_trans *trans); | |||
366 | void iwl_pcie_tx_free(struct iwl_trans *trans); | 366 | void iwl_pcie_tx_free(struct iwl_trans *trans); |
367 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, | 367 | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int queue, u16 ssn, |
368 | const struct iwl_trans_txq_scd_cfg *cfg); | 368 | const struct iwl_trans_txq_scd_cfg *cfg); |
369 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); | 369 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue, |
370 | bool configure_scd); | ||
370 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 371 | int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
371 | struct iwl_device_cmd *dev_cmd, int txq_id); | 372 | struct iwl_device_cmd *dev_cmd, int txq_id); |
372 | void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans); | 373 | void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 5c95386c72bf..eb39e584cc6d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1070,37 +1070,41 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
1070 | const struct iwl_trans_txq_scd_cfg *cfg) | 1070 | const struct iwl_trans_txq_scd_cfg *cfg) |
1071 | { | 1071 | { |
1072 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1072 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1073 | u8 frame_limit = cfg->frame_limit; | 1073 | int fifo = -1; |
1074 | 1074 | ||
1075 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 1075 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
1076 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 1076 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
1077 | 1077 | ||
1078 | /* Stop this Tx queue before configuring it */ | 1078 | if (cfg) { |
1079 | iwl_scd_txq_set_inactive(trans, txq_id); | 1079 | fifo = cfg->fifo; |
1080 | 1080 | ||
1081 | /* Set this queue as a chain-building queue unless it is CMD queue */ | 1081 | /* Stop this Tx queue before configuring it */ |
1082 | if (txq_id != trans_pcie->cmd_queue) | 1082 | iwl_scd_txq_set_inactive(trans, txq_id); |
1083 | iwl_scd_txq_set_chain(trans, txq_id); | ||
1084 | 1083 | ||
1085 | /* If this queue is mapped to a certain station: it is an AGG queue */ | 1084 | /* Set this queue as a chain-building queue unless it is CMD */ |
1086 | if (cfg->sta_id >= 0) { | 1085 | if (txq_id != trans_pcie->cmd_queue) |
1087 | u16 ra_tid = BUILD_RAxTID(cfg->sta_id, cfg->tid); | 1086 | iwl_scd_txq_set_chain(trans, txq_id); |
1088 | 1087 | ||
1089 | /* Map receiver-address / traffic-ID to this queue */ | 1088 | /* If this queue is mapped to a certain station: it is an AGG */ |
1090 | iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id); | 1089 | if (cfg->sta_id >= 0) { |
1090 | u16 ra_tid = BUILD_RAxTID(cfg->sta_id, cfg->tid); | ||
1091 | 1091 | ||
1092 | /* enable aggregations for the queue */ | 1092 | /* Map receiver-address / traffic-ID to this queue */ |
1093 | iwl_scd_txq_enable_agg(trans, txq_id); | 1093 | iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id); |
1094 | trans_pcie->txq[txq_id].ampdu = true; | 1094 | |
1095 | } else { | 1095 | /* enable aggregations for the queue */ |
1096 | /* | 1096 | iwl_scd_txq_enable_agg(trans, txq_id); |
1097 | * disable aggregations for the queue, this will also make the | 1097 | trans_pcie->txq[txq_id].ampdu = true; |
1098 | * ra_tid mapping configuration irrelevant since it is now a | 1098 | } else { |
1099 | * non-AGG queue. | 1099 | /* |
1100 | */ | 1100 | * disable aggregations for the queue, this will also |
1101 | iwl_scd_txq_disable_agg(trans, txq_id); | 1101 | * make the ra_tid mapping configuration irrelevant |
1102 | * since it is now a non-AGG queue. | ||
1103 | */ | ||
1104 | iwl_scd_txq_disable_agg(trans, txq_id); | ||
1102 | 1105 | ||
1103 | ssn = trans_pcie->txq[txq_id].q.read_ptr; | 1106 | ssn = trans_pcie->txq[txq_id].q.read_ptr; |
1107 | } | ||
1104 | } | 1108 | } |
1105 | 1109 | ||
1106 | /* Place first TFD at index corresponding to start sequence number. | 1110 | /* Place first TFD at index corresponding to start sequence number. |
@@ -1108,32 +1112,39 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, | |||
1108 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); | 1112 | trans_pcie->txq[txq_id].q.read_ptr = (ssn & 0xff); |
1109 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); | 1113 | trans_pcie->txq[txq_id].q.write_ptr = (ssn & 0xff); |
1110 | 1114 | ||
1111 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | 1115 | if (cfg) { |
1112 | (ssn & 0xff) | (txq_id << 8)); | 1116 | u8 frame_limit = cfg->frame_limit; |
1113 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); | 1117 | |
1118 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | ||
1119 | (ssn & 0xff) | (txq_id << 8)); | ||
1120 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); | ||
1114 | 1121 | ||
1115 | /* Set up Tx window size and frame limit for this queue */ | 1122 | /* Set up Tx window size and frame limit for this queue */ |
1116 | iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + | 1123 | iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + |
1117 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); | 1124 | SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); |
1118 | iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + | 1125 | iwl_trans_write_mem32(trans, |
1126 | trans_pcie->scd_base_addr + | ||
1119 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | 1127 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), |
1120 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 1128 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |
1121 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | 1129 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |
1122 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | 1130 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |
1123 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 1131 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
1124 | 1132 | ||
1125 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 1133 | /* Set up status area in SRAM, map to Tx DMA/FIFO, activate */ |
1126 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | 1134 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), |
1127 | (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | | 1135 | (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | |
1128 | (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) | | 1136 | (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) | |
1129 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | | 1137 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | |
1130 | SCD_QUEUE_STTS_REG_MSK); | 1138 | SCD_QUEUE_STTS_REG_MSK); |
1139 | } | ||
1140 | |||
1131 | trans_pcie->txq[txq_id].active = true; | 1141 | trans_pcie->txq[txq_id].active = true; |
1132 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", | 1142 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", |
1133 | txq_id, cfg->fifo, ssn & 0xff); | 1143 | txq_id, fifo, ssn & 0xff); |
1134 | } | 1144 | } |
1135 | 1145 | ||
1136 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | 1146 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, |
1147 | bool configure_scd) | ||
1137 | { | 1148 | { |
1138 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1149 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1139 | u32 stts_addr = trans_pcie->scd_base_addr + | 1150 | u32 stts_addr = trans_pcie->scd_base_addr + |
@@ -1152,10 +1163,12 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | |||
1152 | return; | 1163 | return; |
1153 | } | 1164 | } |
1154 | 1165 | ||
1155 | iwl_scd_txq_set_inactive(trans, txq_id); | 1166 | if (configure_scd) { |
1167 | iwl_scd_txq_set_inactive(trans, txq_id); | ||
1156 | 1168 | ||
1157 | iwl_trans_write_mem(trans, stts_addr, (void *)zero_val, | 1169 | iwl_trans_write_mem(trans, stts_addr, (void *)zero_val, |
1158 | ARRAY_SIZE(zero_val)); | 1170 | ARRAY_SIZE(zero_val)); |
1171 | } | ||
1159 | 1172 | ||
1160 | iwl_pcie_txq_unmap(trans, txq_id); | 1173 | iwl_pcie_txq_unmap(trans, txq_id); |
1161 | trans_pcie->txq[txq_id].ampdu = false; | 1174 | trans_pcie->txq[txq_id].ampdu = false; |