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

Commit a0ec0169 authored by Golan Ben Ami's avatar Golan Ben Ami Committed by Luca Coelho
Browse files

iwlwifi: support new tx api



22560 devices use a new tx cmd api. Update the code to use
the new api.

Signed-off-by: default avatarGolan Ben Ami <golan.ben.ami@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 7b3e42ea
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -193,7 +193,8 @@ enum iwl_legacy_cmds {
	FW_GET_ITEM_CMD = 0x1a,

	/**
	 * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2,
	 * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
	 *	&struct iwl_tx_cmd_gen3,
	 *	response in &struct iwl_mvm_tx_resp or
	 *	&struct iwl_mvm_tx_resp_v3
	 */
+25 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 *
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
@@ -28,6 +29,7 @@
 *
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2018 Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -320,6 +322,29 @@ struct iwl_tx_cmd_gen2 {
	struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_7 */

/**
 * struct iwl_tx_cmd_gen3 - TX command struct to FW for 22560 devices
 * ( TX_CMD = 0x1c )
 * @len: in bytes of the payload, see below for details
 * @flags: combination of &enum iwl_tx_cmd_flags
 * @offload_assist: TX offload configuration
 * @dram_info: FW internal DRAM storage
 * @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
 *	cleared. Combination of RATE_MCS_*
 * @ttl: time to live - packet lifetime limit. The FW should drop if
 *	passed.
 * @hdr: 802.11 header
 */
struct iwl_tx_cmd_gen3 {
	__le16 len;
	__le16 flags;
	__le32 offload_assist;
	struct iwl_dram_sec_info dram_info;
	__le32 rate_n_flags;
	__le64 ttl;
	struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_8 */

/*
 * TX response related data
 */
+34 −14
Original line number Diff line number Diff line
@@ -484,13 +484,15 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,

	/* Make sure we zero enough of dev_cmd */
	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd));
	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) > sizeof(*tx_cmd));

	memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd));
	dev_cmd->hdr.cmd = TX_CMD;

	if (iwl_mvm_has_new_tx_api(mvm)) {
		struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
		u16 offload_assist = 0;
		u32 rate_n_flags = 0;
		u16 flags = 0;

		if (ieee80211_is_data_qos(hdr->frame_control)) {
			u8 *qc = ieee80211_get_qos_ctl(hdr);
@@ -507,7 +509,20 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
		    !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
			offload_assist |= BIT(TX_CMD_OFFLD_PAD);

		cmd->offload_assist |= cpu_to_le16(offload_assist);
		if (!info->control.hw_key)
			flags |= IWL_TX_FLAGS_ENCRYPT_DIS;

		/* For data packets rate info comes from the fw */
		if (!(ieee80211_is_data(hdr->frame_control) && sta)) {
			flags |= IWL_TX_FLAGS_CMD_RATE;
			rate_n_flags = iwl_mvm_get_tx_rate(mvm, info, sta);
		}

		if (mvm->trans->cfg->device_family >=
		    IWL_DEVICE_FAMILY_22560) {
			struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;

			cmd->offload_assist |= cpu_to_le32(offload_assist);

			/* Total # bytes to be transmitted */
			cmd->len = cpu_to_le16((u16)skb->len);
@@ -515,17 +530,22 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
			/* Copy MAC header from skb into command buffer */
			memcpy(cmd->hdr, hdr, hdrlen);

		if (!info->control.hw_key)
			cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_ENCRYPT_DIS);
			cmd->flags = cpu_to_le16(flags);
			cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
		} else {
			struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;

		/* For data packets rate info comes from the fw */
		if (ieee80211_is_data(hdr->frame_control) && sta)
			goto out;
			cmd->offload_assist |= cpu_to_le16(offload_assist);

			/* Total # bytes to be transmitted */
			cmd->len = cpu_to_le16((u16)skb->len);

		cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_CMD_RATE);
		cmd->rate_n_flags =
			cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta));
			/* Copy MAC header from skb into command buffer */
			memcpy(cmd->hdr, hdr, hdrlen);

			cmd->flags = cpu_to_le32(flags);
			cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
		}
		goto out;
	}

+22 −4
Original line number Diff line number Diff line
@@ -402,8 +402,14 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
	 * (This calculation modifies the TX command, so do it before the
	 * setup of the first TB)
	 */
	len = sizeof(struct iwl_tx_cmd_gen2) + sizeof(struct iwl_cmd_header) +
	      ieee80211_hdrlen(hdr->frame_control) - IWL_FIRST_TB_SIZE;
	if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
		len = sizeof(struct iwl_tx_cmd_gen2);
	else
		len = sizeof(struct iwl_tx_cmd_gen3);

	len += sizeof(struct iwl_cmd_header) +
		ieee80211_hdrlen(hdr->frame_control) -
		IWL_FIRST_TB_SIZE;

	/* do not align A-MSDU to dword as the subframe header aligns it */
	if (amsdu)
@@ -480,9 +486,9 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
			   struct iwl_device_cmd *dev_cmd, int txq_id)
{
	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
	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];
	u16 cmd_len;
	int idx;
	void *tfd;

@@ -497,6 +503,18 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,

	spin_lock(&txq->lock);

	if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
		struct iwl_tx_cmd_gen3 *tx_cmd_gen3 =
			(void *)dev_cmd->payload;

		cmd_len = le16_to_cpu(tx_cmd_gen3->len);
	} else {
		struct iwl_tx_cmd_gen2 *tx_cmd_gen2 =
			(void *)dev_cmd->payload;

		cmd_len = le16_to_cpu(tx_cmd_gen2->len);
	}

	if (iwl_queue_space(trans, txq) < txq->high_mark) {
		iwl_stop_queue(trans, txq);

@@ -535,7 +553,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
	}

	/* Set up entry for this TFD in Tx byte-count array */
	iwl_pcie_gen2_update_byte_tbl(trans_pcie, txq, le16_to_cpu(tx_cmd->len),
	iwl_pcie_gen2_update_byte_tbl(trans_pcie, txq, cmd_len,
				      iwl_pcie_gen2_get_num_tbs(trans, tfd));

	/* start timer if queue currently empty */