mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-20 12:47:12 +07:00
iwlwifi: pcie: support short Tx queues for A000 device family
This allows to modify TFD_TX_CMD_SLOTS to a power of 2 which is smaller than 256. Note that we still need to set values to wrap at 256 into the scheduler's write pointer, but all the rest of the code can use shorter transmit queues. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
fbfe378fe4
commit
4ecab56160
@ -244,7 +244,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
|
|||||||
ctxt_info->hcmd_cfg.cmd_queue_addr =
|
ctxt_info->hcmd_cfg.cmd_queue_addr =
|
||||||
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
|
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
|
||||||
ctxt_info->hcmd_cfg.cmd_queue_size =
|
ctxt_info->hcmd_cfg.cmd_queue_size =
|
||||||
TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX);
|
TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS);
|
||||||
|
|
||||||
/* allocate ucode sections in dram and set addresses */
|
/* allocate ucode sections in dram and set addresses */
|
||||||
ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
|
ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
|
||||||
|
@ -661,10 +661,16 @@ static inline void iwl_pcie_sw_reset(struct iwl_trans *trans)
|
|||||||
usleep_range(5000, 6000);
|
usleep_range(5000, 6000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u8 iwl_pcie_get_cmd_index(struct iwl_txq *q, u32 index)
|
||||||
|
{
|
||||||
|
return index & (q->n_window - 1);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie,
|
static inline void *iwl_pcie_get_tfd(struct iwl_trans_pcie *trans_pcie,
|
||||||
struct iwl_txq *txq, int idx)
|
struct iwl_txq *txq, int idx)
|
||||||
{
|
{
|
||||||
return txq->tfds + trans_pcie->tfd_size * idx;
|
return txq->tfds + trans_pcie->tfd_size * iwl_pcie_get_cmd_index(txq,
|
||||||
|
idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
|
static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
|
||||||
@ -726,11 +732,6 @@ static inline bool iwl_queue_used(const struct iwl_txq *q, int i)
|
|||||||
!(i < q->read_ptr && i >= q->write_ptr);
|
!(i < q->read_ptr && i >= q->write_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 get_cmd_index(struct iwl_txq *q, u32 index)
|
|
||||||
{
|
|
||||||
return index & (q->n_window - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
|
static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
|
@ -1176,7 +1176,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
|||||||
|
|
||||||
sequence = le16_to_cpu(pkt->hdr.sequence);
|
sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||||
index = SEQ_TO_INDEX(sequence);
|
index = SEQ_TO_INDEX(sequence);
|
||||||
cmd_index = get_cmd_index(txq, index);
|
cmd_index = iwl_pcie_get_cmd_index(txq, index);
|
||||||
|
|
||||||
if (rxq->id == 0)
|
if (rxq->id == 0)
|
||||||
iwl_op_mode_rx(trans->op_mode, &rxq->napi,
|
iwl_op_mode_rx(trans->op_mode, &rxq->napi,
|
||||||
|
@ -2835,7 +2835,7 @@ static struct iwl_trans_dump_data
|
|||||||
spin_lock_bh(&cmdq->lock);
|
spin_lock_bh(&cmdq->lock);
|
||||||
ptr = cmdq->write_ptr;
|
ptr = cmdq->write_ptr;
|
||||||
for (i = 0; i < cmdq->n_window; i++) {
|
for (i = 0; i < cmdq->n_window; i++) {
|
||||||
u8 idx = get_cmd_index(cmdq, ptr);
|
u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
|
||||||
u32 caplen, cmdlen;
|
u32 caplen, cmdlen;
|
||||||
|
|
||||||
cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
|
cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
|
||||||
|
@ -88,14 +88,14 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_txq *txq, u16 byte_cnt,
|
|||||||
int num_tbs)
|
int num_tbs)
|
||||||
{
|
{
|
||||||
struct iwlagn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.addr;
|
struct iwlagn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.addr;
|
||||||
int write_ptr = txq->write_ptr;
|
int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
|
||||||
u8 filled_tfd_size, num_fetch_chunks;
|
u8 filled_tfd_size, num_fetch_chunks;
|
||||||
u16 len = byte_cnt;
|
u16 len = byte_cnt;
|
||||||
__le16 bc_ent;
|
__le16 bc_ent;
|
||||||
|
|
||||||
len = DIV_ROUND_UP(len, 4);
|
len = DIV_ROUND_UP(len, 4);
|
||||||
|
|
||||||
if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX))
|
if (WARN_ON(len > 0xFFF || idx >= txq->n_window))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
|
filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) +
|
||||||
@ -111,7 +111,7 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_txq *txq, u16 byte_cnt,
|
|||||||
num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
|
num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
|
||||||
|
|
||||||
bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
|
bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12));
|
||||||
scd_bc_tbl->tfd_offset[write_ptr] = bc_ent;
|
scd_bc_tbl->tfd_offset[idx] = bc_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -176,16 +176,12 @@ static void iwl_pcie_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
|
|||||||
/* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
|
/* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
|
||||||
* idx is bounded by n_window
|
* idx is bounded by n_window
|
||||||
*/
|
*/
|
||||||
int rd_ptr = txq->read_ptr;
|
int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
|
||||||
int idx = get_cmd_index(txq, rd_ptr);
|
|
||||||
|
|
||||||
lockdep_assert_held(&txq->lock);
|
lockdep_assert_held(&txq->lock);
|
||||||
|
|
||||||
/* We have only q->n_window txq->entries, but we use
|
|
||||||
* TFD_QUEUE_SIZE_MAX tfds
|
|
||||||
*/
|
|
||||||
iwl_pcie_gen2_tfd_unmap(trans, &txq->entries[idx].meta,
|
iwl_pcie_gen2_tfd_unmap(trans, &txq->entries[idx].meta,
|
||||||
iwl_pcie_get_tfd(trans_pcie, txq, rd_ptr));
|
iwl_pcie_get_tfd(trans_pcie, txq, idx));
|
||||||
|
|
||||||
/* free SKB */
|
/* free SKB */
|
||||||
if (txq->entries) {
|
if (txq->entries) {
|
||||||
@ -373,8 +369,9 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
|
|||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||||
|
int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
|
||||||
struct iwl_tfh_tfd *tfd =
|
struct iwl_tfh_tfd *tfd =
|
||||||
iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
|
iwl_pcie_get_tfd(trans_pcie, txq, idx);
|
||||||
dma_addr_t tb_phys;
|
dma_addr_t tb_phys;
|
||||||
bool amsdu;
|
bool amsdu;
|
||||||
int i, len, tb1_len, tb2_len, hdr_len;
|
int i, len, tb1_len, tb2_len, hdr_len;
|
||||||
@ -386,10 +383,10 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
|
|||||||
(*ieee80211_get_qos_ctl(hdr) &
|
(*ieee80211_get_qos_ctl(hdr) &
|
||||||
IEEE80211_QOS_CTL_A_MSDU_PRESENT);
|
IEEE80211_QOS_CTL_A_MSDU_PRESENT);
|
||||||
|
|
||||||
tb_phys = iwl_pcie_get_first_tb_dma(txq, txq->write_ptr);
|
tb_phys = iwl_pcie_get_first_tb_dma(txq, idx);
|
||||||
/* The first TB points to bi-directional DMA data */
|
/* The first TB points to bi-directional DMA data */
|
||||||
if (!amsdu)
|
if (!amsdu)
|
||||||
memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
|
memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr,
|
||||||
IWL_FIRST_TB_SIZE);
|
IWL_FIRST_TB_SIZE);
|
||||||
|
|
||||||
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
|
iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE);
|
||||||
@ -431,7 +428,7 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
|
|||||||
* building the A-MSDU might have changed this data, so memcpy
|
* building the A-MSDU might have changed this data, so memcpy
|
||||||
* it now
|
* it now
|
||||||
*/
|
*/
|
||||||
memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
|
memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr,
|
||||||
IWL_FIRST_TB_SIZE);
|
IWL_FIRST_TB_SIZE);
|
||||||
return tfd;
|
return tfd;
|
||||||
}
|
}
|
||||||
@ -484,6 +481,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||||||
struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
|
struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
|
||||||
struct iwl_cmd_meta *out_meta;
|
struct iwl_cmd_meta *out_meta;
|
||||||
struct iwl_txq *txq = trans_pcie->txq[txq_id];
|
struct iwl_txq *txq = trans_pcie->txq[txq_id];
|
||||||
|
int idx;
|
||||||
void *tfd;
|
void *tfd;
|
||||||
|
|
||||||
if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
|
if (WARN_ONCE(!test_bit(txq_id, trans_pcie->queue_used),
|
||||||
@ -497,16 +495,18 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|||||||
|
|
||||||
spin_lock(&txq->lock);
|
spin_lock(&txq->lock);
|
||||||
|
|
||||||
|
idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
|
||||||
|
|
||||||
/* Set up driver data for this TFD */
|
/* Set up driver data for this TFD */
|
||||||
txq->entries[txq->write_ptr].skb = skb;
|
txq->entries[idx].skb = skb;
|
||||||
txq->entries[txq->write_ptr].cmd = dev_cmd;
|
txq->entries[idx].cmd = dev_cmd;
|
||||||
|
|
||||||
dev_cmd->hdr.sequence =
|
dev_cmd->hdr.sequence =
|
||||||
cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
|
cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
|
||||||
INDEX_TO_SEQ(txq->write_ptr)));
|
INDEX_TO_SEQ(idx)));
|
||||||
|
|
||||||
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
||||||
out_meta = &txq->entries[txq->write_ptr].meta;
|
out_meta = &txq->entries[idx].meta;
|
||||||
out_meta->flags = 0;
|
out_meta->flags = 0;
|
||||||
|
|
||||||
tfd = iwl_pcie_gen2_build_tfd(trans, txq, dev_cmd, skb, out_meta);
|
tfd = iwl_pcie_gen2_build_tfd(trans, txq, dev_cmd, skb, out_meta);
|
||||||
@ -562,7 +562,7 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
void *dup_buf = NULL;
|
void *dup_buf = NULL;
|
||||||
dma_addr_t phys_addr;
|
dma_addr_t phys_addr;
|
||||||
int idx, i, cmd_pos;
|
int i, cmd_pos, idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
|
||||||
u16 copy_size, cmd_size, tb0_size;
|
u16 copy_size, cmd_size, tb0_size;
|
||||||
bool had_nocopy = false;
|
bool had_nocopy = false;
|
||||||
u8 group_id = iwl_cmd_groupid(cmd->id);
|
u8 group_id = iwl_cmd_groupid(cmd->id);
|
||||||
@ -651,7 +651,6 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans,
|
|||||||
goto free_dup_buf;
|
goto free_dup_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = get_cmd_index(txq, txq->write_ptr);
|
|
||||||
out_cmd = txq->entries[idx].cmd;
|
out_cmd = txq->entries[idx].cmd;
|
||||||
out_meta = &txq->entries[idx].meta;
|
out_meta = &txq->entries[idx].meta;
|
||||||
|
|
||||||
@ -938,7 +937,7 @@ void iwl_pcie_gen2_txq_unmap(struct iwl_trans *trans, int txq_id)
|
|||||||
txq_id, txq->read_ptr);
|
txq_id, txq->read_ptr);
|
||||||
|
|
||||||
if (txq_id != trans_pcie->cmd_queue) {
|
if (txq_id != trans_pcie->cmd_queue) {
|
||||||
int idx = get_cmd_index(txq, txq->read_ptr);
|
int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
|
||||||
struct sk_buff *skb = txq->entries[idx].skb;
|
struct sk_buff *skb = txq->entries[idx].skb;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!skb))
|
if (WARN_ON_ONCE(!skb))
|
||||||
@ -1070,7 +1069,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
|
|||||||
|
|
||||||
cmd->tfdq_addr = cpu_to_le64(txq->dma_addr);
|
cmd->tfdq_addr = cpu_to_le64(txq->dma_addr);
|
||||||
cmd->byte_cnt_addr = cpu_to_le64(txq->bc_tbl.dma);
|
cmd->byte_cnt_addr = cpu_to_le64(txq->bc_tbl.dma);
|
||||||
cmd->cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX));
|
cmd->cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(TFD_TX_CMD_SLOTS));
|
||||||
|
|
||||||
ret = iwl_trans_send_cmd(trans, &hcmd);
|
ret = iwl_trans_send_cmd(trans, &hcmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -106,7 +106,7 @@ static int iwl_queue_init(struct iwl_txq *q, int slots_num)
|
|||||||
q->n_window = slots_num;
|
q->n_window = slots_num;
|
||||||
|
|
||||||
/* slots_num must be power-of-two size, otherwise
|
/* slots_num must be power-of-two size, otherwise
|
||||||
* get_cmd_index is broken. */
|
* iwl_pcie_get_cmd_index is broken. */
|
||||||
if (WARN_ON(!is_power_of_2(slots_num)))
|
if (WARN_ON(!is_power_of_2(slots_num)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
|
|||||||
* idx is bounded by n_window
|
* idx is bounded by n_window
|
||||||
*/
|
*/
|
||||||
int rd_ptr = txq->read_ptr;
|
int rd_ptr = txq->read_ptr;
|
||||||
int idx = get_cmd_index(txq, rd_ptr);
|
int idx = iwl_pcie_get_cmd_index(txq, rd_ptr);
|
||||||
|
|
||||||
lockdep_assert_held(&txq->lock);
|
lockdep_assert_held(&txq->lock);
|
||||||
|
|
||||||
@ -1100,7 +1100,8 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
|||||||
for (;
|
for (;
|
||||||
txq->read_ptr != tfd_num;
|
txq->read_ptr != tfd_num;
|
||||||
txq->read_ptr = iwl_queue_inc_wrap(txq->read_ptr)) {
|
txq->read_ptr = iwl_queue_inc_wrap(txq->read_ptr)) {
|
||||||
struct sk_buff *skb = txq->entries[txq->read_ptr].skb;
|
int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);
|
||||||
|
struct sk_buff *skb = txq->entries[idx].skb;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!skb))
|
if (WARN_ON_ONCE(!skb))
|
||||||
continue;
|
continue;
|
||||||
@ -1109,7 +1110,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
|||||||
|
|
||||||
__skb_queue_tail(skbs, skb);
|
__skb_queue_tail(skbs, skb);
|
||||||
|
|
||||||
txq->entries[txq->read_ptr].skb = NULL;
|
txq->entries[idx].skb = NULL;
|
||||||
|
|
||||||
if (!trans->cfg->use_tfh)
|
if (!trans->cfg->use_tfh)
|
||||||
iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
|
iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
|
||||||
@ -1559,7 +1560,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
|||||||
goto free_dup_buf;
|
goto free_dup_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = get_cmd_index(txq, txq->write_ptr);
|
idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
|
||||||
out_cmd = txq->entries[idx].cmd;
|
out_cmd = txq->entries[idx].cmd;
|
||||||
out_meta = &txq->entries[idx].meta;
|
out_meta = &txq->entries[idx].meta;
|
||||||
|
|
||||||
@ -1751,7 +1752,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
|
|||||||
|
|
||||||
spin_lock_bh(&txq->lock);
|
spin_lock_bh(&txq->lock);
|
||||||
|
|
||||||
cmd_index = get_cmd_index(txq, index);
|
cmd_index = iwl_pcie_get_cmd_index(txq, index);
|
||||||
cmd = txq->entries[cmd_index].cmd;
|
cmd = txq->entries[cmd_index].cmd;
|
||||||
meta = &txq->entries[cmd_index].meta;
|
meta = &txq->entries[cmd_index].meta;
|
||||||
group_id = cmd->hdr.group_id;
|
group_id = cmd->hdr.group_id;
|
||||||
|
Loading…
Reference in New Issue
Block a user