Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ecab561 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Luca Coelho
Browse files

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: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent fbfe378f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
	ctxt_info->hcmd_cfg.cmd_queue_addr =
		cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue]->dma_addr);
	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 */
	ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
+7 −6
Original line number Diff line number Diff line
@@ -661,10 +661,16 @@ static inline void iwl_pcie_sw_reset(struct iwl_trans *trans)
	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,
				     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)
@@ -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);
}

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)
{
	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+1 −1
Original line number Diff line number Diff line
@@ -1176,7 +1176,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,

		sequence = le16_to_cpu(pkt->hdr.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)
			iwl_op_mode_rx(trans->op_mode, &rxq->napi,
+1 −1
Original line number Diff line number Diff line
@@ -2835,7 +2835,7 @@ static struct iwl_trans_dump_data
	spin_lock_bh(&cmdq->lock);
	ptr = cmdq->write_ptr;
	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;

		cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
+20 −21
Original line number Diff line number Diff line
@@ -88,14 +88,14 @@ static void iwl_pcie_gen2_update_byte_tbl(struct iwl_txq *txq, u16 byte_cnt,
					  int num_tbs)
{
	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;
	u16 len = byte_cnt;
	__le16 bc_ent;

	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;

	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;

	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
	 * idx is bounded by n_window
	 */
	int rd_ptr = txq->read_ptr;
	int idx = get_cmd_index(txq, rd_ptr);
	int idx = iwl_pcie_get_cmd_index(txq, txq->read_ptr);

	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_get_tfd(trans_pcie, txq, rd_ptr));
				iwl_pcie_get_tfd(trans_pcie, txq, idx));

	/* free SKB */
	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 ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	int idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
	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;
	bool amsdu;
	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_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 */
	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_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
		 * 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);
		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_cmd_meta *out_meta;
	struct iwl_txq *txq = trans_pcie->txq[txq_id];
	int idx;
	void *tfd;

	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);

	idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);

	/* Set up driver data for this TFD */
	txq->entries[txq->write_ptr].skb = skb;
	txq->entries[txq->write_ptr].cmd = dev_cmd;
	txq->entries[idx].skb = skb;
	txq->entries[idx].cmd = dev_cmd;

	dev_cmd->hdr.sequence =
		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 */
	out_meta = &txq->entries[txq->write_ptr].meta;
	out_meta = &txq->entries[idx].meta;
	out_meta->flags = 0;

	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;
	void *dup_buf = NULL;
	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;
	bool had_nocopy = false;
	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;
	}

	idx = get_cmd_index(txq, txq->write_ptr);
	out_cmd = txq->entries[idx].cmd;
	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);

		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;

			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->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);
	if (ret)
Loading