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

Commit c47de665 authored by Sara Sharon's avatar Sara Sharon Committed by Luca Coelho
Browse files

iwlwifi: mvm: support new TX API



Support the new TX command API for a000 devices.
Command is a very slim version of current TX command.
Generalize iwl_mvm_tx_mpdu to get rid of TX command dependencies.

Signed-off-by: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 69964905
Loading
Loading
Loading
Loading
+41 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
 * GPL LICENSE SUMMARY
 *
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2016 Intel Deutschland GmbH
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 *
 * 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
@@ -32,6 +32,7 @@
 * BSD LICENSE
 *
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -123,6 +124,20 @@ enum iwl_tx_flags {
	TX_CMD_FLG_HCCA_CHUNK		= BIT(31)
}; /* TX_FLAGS_BITS_API_S_VER_1 */

/**
 * enum iwl_tx_cmd_flags - bitmasks for tx_flags in TX command for a000
 * @IWL_TX_FLAGS_CMD_RATE: use rate from the TX command
 * @IWL_TX_FLAGS_ENCRYPT_DIS: frame should not be encrypted, even if it belongs
 *	to a secured STA
 * @IWL_TX_FLAGS_HIGH_PRI: high priority frame (like EAPOL) - can affect rate
 *	selection, retry limits and BT kill
 */
enum iwl_tx_cmd_flags {
	IWL_TX_FLAGS_CMD_RATE		= BIT(0),
	IWL_TX_FLAGS_ENCRYPT_DIS	= BIT(1),
	IWL_TX_FLAGS_HIGH_PRI		= BIT(2),
}; /* TX_FLAGS_BITS_API_S_VER_3 */

/**
 * enum iwl_tx_pm_timeouts - pm timeout values in TX command
 * @PM_FRAME_NONE: no need to suspend sleep mode
@@ -301,6 +316,31 @@ struct iwl_tx_cmd {
	struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_6 */

struct iwl_dram_sec_info {
	__le32 pn_low;
	__le16 pn_high;
	__le16 aux_info;
} __packed; /* DRAM_SEC_INFO_API_S_VER_1 */

/**
 * struct iwl_tx_cmd_gen2 - TX command struct to FW for a000 devices
 * ( TX_CMD = 0x1c )
 * @len: in bytes of the payload, see below for details
 * @offload_assist: TX offload configuration
 * @tx_flags: combination of &iwl_tx_cmd_flags
 * @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_*
 */
struct iwl_tx_cmd_gen2 {
	__le16 len;
	__le16 offload_assist;
	__le32 flags;
	struct iwl_dram_sec_info dram_info;
	__le32 rate_n_flags;
	struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_7 */

/*
 * TX response related data
 */
+50 −16
Original line number Diff line number Diff line
@@ -475,6 +475,39 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,

	memset(dev_cmd, 0, sizeof(*dev_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 = iwl_mvm_tx_csum(mvm, skb, hdr, info);

		/* padding is inserted later in transport */
		/* FIXME - check for AMSDU may need to be removed */
		if (ieee80211_hdrlen(hdr->frame_control) % 4 &&
		    !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
			offload_assist |= BIT(TX_CMD_OFFLD_PAD);

		cmd->offload_assist |= cpu_to_le16(offload_assist);

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

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

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

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

		goto out;
	}

	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;

	if (info->control.hw_key)
@@ -484,6 +517,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,

	iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, hdrlen);

out:
	return dev_cmd;
}

@@ -541,7 +578,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
	struct ieee80211_tx_info info;
	struct iwl_device_cmd *dev_cmd;
	struct iwl_tx_cmd *tx_cmd;
	u8 sta_id;
	int hdrlen = ieee80211_hdrlen(hdr->frame_control);
	int queue;
@@ -616,11 +652,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
	/* From now on, we cannot access info->control */
	iwl_mvm_skb_prepare_status(skb, dev_cmd);

	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, hdrlen);

	if (iwl_trans_tx(mvm->trans, skb, dev_cmd, queue)) {
		iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
		return -1;
@@ -881,7 +912,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct iwl_mvm_sta *mvmsta;
	struct iwl_device_cmd *dev_cmd;
	struct iwl_tx_cmd *tx_cmd;
	__le16 fc;
	u16 seq_number = 0;
	u8 tid = IWL_MAX_TID_COUNT;
@@ -904,8 +934,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
	if (!dev_cmd)
		goto drop;

	tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;

	/*
	 * we handle that entirely ourselves -- for uAPSD the firmware
	 * will always send a notification, and for PS-Poll responses
@@ -926,18 +954,27 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
		if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
			goto drop_unlock_sta;

		seq_number = mvmsta->tid_data[tid].seq_number;
		seq_number &= IEEE80211_SCTL_SEQ;
		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
		hdr->seq_ctrl |= cpu_to_le16(seq_number);
		is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU;
		if (WARN_ON_ONCE(is_ampdu &&
				 mvmsta->tid_data[tid].state != IWL_AGG_ON))
			goto drop_unlock_sta;

		seq_number = mvmsta->tid_data[tid].seq_number;
		seq_number &= IEEE80211_SCTL_SEQ;

		if (!iwl_mvm_has_new_tx_api(mvm)) {
			struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;

			hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
			hdr->seq_ctrl |= cpu_to_le16(seq_number);
			/* update the tx_cmd hdr as it was already copied */
			tx_cmd->hdr->seq_ctrl = hdr->seq_ctrl;
		}
	}

	if (iwl_mvm_is_dqa_supported(mvm) || is_ampdu)
		txq_id = mvmsta->tid_data[tid].txq_id;

	if (sta->tdls && !iwl_mvm_is_dqa_supported(mvm)) {
		/* default to TID 0 for non-QoS packets */
		u8 tdls_tid = tid == IWL_MAX_TID_COUNT ? 0 : tid;
@@ -945,9 +982,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
		txq_id = mvmsta->hw_queue[tid_to_mac80211_ac[tdls_tid]];
	}

	/* Copy MAC header from skb into command buffer */
	memcpy(tx_cmd->hdr, hdr, hdrlen);

	WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);

	/* Check if TXQ needs to be allocated or re-activated */