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

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

iwlwifi: support new rx_mpdu_desc api



22560 devices use a new rx_mpdu_desc 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 0307c839
Loading
Loading
Loading
Loading
+133 −46
Original line number Diff line number Diff line
@@ -377,78 +377,94 @@ enum iwl_rx_he_phy {
};

/**
 * struct iwl_rx_mpdu_desc - RX MPDU descriptor
 * struct iwl_rx_mpdu_desc_v1 - RX MPDU descriptor
 */
struct iwl_rx_mpdu_desc {
	/* DW2 */
struct iwl_rx_mpdu_desc_v1 {
	/* DW7 - carries rss_hash only when rpa_en == 1 */
	/**
	 * @mpdu_len: MPDU length
	 * @rss_hash: RSS hash value
	 */
	__le16 mpdu_len;
	__le32 rss_hash;
	/* DW8 - carries filter_match only when rpa_en == 1 */
	/**
	 * @mac_flags1: &enum iwl_rx_mpdu_mac_flags1
	 * @filter_match: filter match value
	 */
	u8 mac_flags1;
	__le32 filter_match;
	/* DW9 */
	/**
	 * @mac_flags2: &enum iwl_rx_mpdu_mac_flags2
	 * @rate_n_flags: RX rate/flags encoding
	 */
	u8 mac_flags2;
	/* DW3 */
	__le32 rate_n_flags;
	/* DW10 */
	/**
	 * @amsdu_info: &enum iwl_rx_mpdu_amsdu_info
	 * @energy_a: energy chain A
	 */
	u8 amsdu_info;
	u8 energy_a;
	/**
	 * @phy_info: &enum iwl_rx_mpdu_phy_info
	 * @energy_b: energy chain B
	 */
	__le16 phy_info;
	u8 energy_b;
	/**
	 * @mac_phy_idx: MAC/PHY index
	 * @channel: channel number
	 */
	u8 mac_phy_idx;
	/* DW4 - carries csum data only when rpa_en == 1 */
	u8 channel;
	/**
	 * @raw_csum: raw checksum (alledgedly unreliable)
	 * @mac_context: MAC context mask
	 */
	__le16 raw_csum;
	u8 mac_context;
	/* DW11 */
	/**
	 * @l3l4_flags: &enum iwl_rx_l3l4_flags
	 * @gp2_on_air_rise: GP2 timer value on air rise (INA)
	 */
	__le16 l3l4_flags;
	/* DW5 */
	__le32 gp2_on_air_rise;
	/* DW12 & DW13 */
	union {
		/**
	 * @status: &enum iwl_rx_mpdu_status
		 * @tsf_on_air_rise:
		 * TSF value on air rise (INA), only valid if
		 * %IWL_RX_MPDU_PHY_TSF_OVERLOAD isn't set
		 */
	__le16 status;
		__le64 tsf_on_air_rise;
		/**
	 * @hash_filter: hash filter value
		 * @he_phy_data:
		 * HE PHY data, see &enum iwl_rx_he_phy, valid
		 * only if %IWL_RX_MPDU_PHY_TSF_OVERLOAD is set
		 */
	u8 hash_filter;
		__le64 he_phy_data;
	};
} __packed;

/**
	 * @sta_id_flags: &enum iwl_rx_mpdu_sta_id_flags
 * struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor
 */
	u8 sta_id_flags;
	/* DW6 */
struct iwl_rx_mpdu_desc_v3 {
	/* DW7 - carries filter_match only when rpa_en == 1 */
	/**
	 * @reorder_data: &enum iwl_rx_mpdu_reorder_data
	 * @filter_match: filter match value
	 */
	__le32 reorder_data;
	/* DW7 - carries rss_hash only when rpa_en == 1 */
	__le32 filter_match;
	/* DW8 - carries rss_hash only when rpa_en == 1 */
	/**
	 * @rss_hash: RSS hash value
	 */
	__le32 rss_hash;
	/* DW8 - carries filter_match only when rpa_en == 1 */
	/* DW9 */
	/**
	 * @filter_match: filter match value
	 * @partial_hash: 31:0 ip/tcp header hash
	 *	w/o some fields (such as IP SRC addr)
	 */
	__le32 filter_match;
	/* DW9 */
	__le32 partial_hash;
	/* DW10 */
	/**
	 * @raw_xsum: raw xsum value
	 */
	__le32 raw_xsum;
	/* DW11 */
	/**
	 * @rate_n_flags: RX rate/flags encoding
	 */
	__le32 rate_n_flags;
	/* DW10 */
	/* DW12 */
	/**
	 * @energy_a: energy chain A
	 */
@@ -465,12 +481,12 @@ struct iwl_rx_mpdu_desc {
	 * @mac_context: MAC context mask
	 */
	u8 mac_context;
	/* DW11 */
	/* DW13 */
	/**
	 * @gp2_on_air_rise: GP2 timer value on air rise (INA)
	 */
	__le32 gp2_on_air_rise;
	/* DW12 & DW13 */
	/* DW14 & DW15 */
	union {
		/**
		 * @tsf_on_air_rise:
@@ -485,7 +501,78 @@ struct iwl_rx_mpdu_desc {
		 */
		__le64 he_phy_data;
	};
} __packed;
	/* DW16 & DW17 */
	/**
	 * @reserved: reserved
	 */
	__le32 reserved[2];
} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */

/**
 * struct iwl_rx_mpdu_desc - RX MPDU descriptor
 */
struct iwl_rx_mpdu_desc {
	/* DW2 */
	/**
	 * @mpdu_len: MPDU length
	 */
	__le16 mpdu_len;
	/**
	 * @mac_flags1: &enum iwl_rx_mpdu_mac_flags1
	 */
	u8 mac_flags1;
	/**
	 * @mac_flags2: &enum iwl_rx_mpdu_mac_flags2
	 */
	u8 mac_flags2;
	/* DW3 */
	/**
	 * @amsdu_info: &enum iwl_rx_mpdu_amsdu_info
	 */
	u8 amsdu_info;
	/**
	 * @phy_info: &enum iwl_rx_mpdu_phy_info
	 */
	__le16 phy_info;
	/**
	 * @mac_phy_idx: MAC/PHY index
	 */
	u8 mac_phy_idx;
	/* DW4 - carries csum data only when rpa_en == 1 */
	/**
	 * @raw_csum: raw checksum (alledgedly unreliable)
	 */
	__le16 raw_csum;
	/**
	 * @l3l4_flags: &enum iwl_rx_l3l4_flags
	 */
	__le16 l3l4_flags;
	/* DW5 */
	/**
	 * @status: &enum iwl_rx_mpdu_status
	 */
	__le16 status;
	/**
	 * @hash_filter: hash filter value
	 */
	u8 hash_filter;
	/**
	 * @sta_id_flags: &enum iwl_rx_mpdu_sta_id_flags
	 */
	u8 sta_id_flags;
	/* DW6 */
	/**
	 * @reorder_data: &enum iwl_rx_mpdu_reorder_data
	 */
	__le32 reorder_data;

	union {
		struct iwl_rx_mpdu_desc_v1 v1;
		struct iwl_rx_mpdu_desc_v3 v3;
	};
} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */

#define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)

struct iwl_frame_release {
	u8 baid;
+6 −2
Original line number Diff line number Diff line
@@ -1150,6 +1150,10 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
	struct iwl_rx_mpdu_desc *desc;
	int bin_len = count / 2;
	int ret = -EINVAL;
	size_t mpdu_cmd_hdr_size =
		(mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ?
		sizeof(struct iwl_rx_mpdu_desc) :
		IWL_RX_DESC_SIZE_V1;

	if (!iwl_mvm_firmware_running(mvm))
		return -EIO;
@@ -1168,7 +1172,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
		goto out;

	/* avoid invalid memory access */
	if (bin_len < sizeof(*pkt) + sizeof(*desc))
	if (bin_len < sizeof(*pkt) + mpdu_cmd_hdr_size)
		goto out;

	/* check this is RX packet */
@@ -1179,7 +1183,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
	/* check the length in metadata matches actual received length */
	desc = (void *)pkt->data;
	if (le16_to_cpu(desc->mpdu_len) !=
	    (bin_len - sizeof(*desc) - sizeof(*pkt)))
	    (bin_len - mpdu_cmd_hdr_size - sizeof(*pkt)))
		goto out;

	local_bh_disable();
+6 −3
Original line number Diff line number Diff line
@@ -621,7 +621,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,

	if (iwl_mvm_has_new_rx_api(mvm)) {
		op_mode->ops = &iwl_mvm_ops_mq;
		trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
		trans->rx_mpdu_cmd_hdr_size =
			(trans->cfg->device_family >=
			 IWL_DEVICE_FAMILY_22560) ?
			sizeof(struct iwl_rx_mpdu_desc) :
			IWL_RX_DESC_SIZE_V1;
	} else {
		op_mode->ops = &iwl_mvm_ops;
		trans->rx_mpdu_cmd_hdr_size =
@@ -704,8 +708,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
	}

	/* the hardware splits the A-MSDU */
	if (mvm->trans->cfg->device_family >=
	    IWL_DEVICE_FAMILY_22560)
	if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
		trans_cfg.rx_buf_size = IWL_AMSDU_2K;
	else if (mvm->cfg->mq_rx_supported)
		trans_cfg.rx_buf_size = IWL_AMSDU_4K;
+73 −22
Original line number Diff line number Diff line
@@ -215,15 +215,14 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
}

static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
					struct iwl_rx_mpdu_desc *desc,
					struct ieee80211_rx_status *rx_status)
					struct ieee80211_rx_status *rx_status,
					u32 rate_n_flags, int energy_a,
					int energy_b)
{
	int energy_a, energy_b, max_energy;
	u32 rate_flags = le32_to_cpu(desc->rate_n_flags);
	int max_energy;
	u32 rate_flags = rate_n_flags;

	energy_a = desc->energy_a;
	energy_a = energy_a ? -energy_a : S8_MIN;
	energy_b = desc->energy_b;
	energy_b = energy_b ? -energy_b : S8_MIN;
	max_energy = max(energy_a, energy_b);

@@ -368,7 +367,8 @@ static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
		tid = IWL_MAX_TID_COUNT;

	/* If this wasn't a part of an A-MSDU the sub-frame index will be 0 */
	sub_frame_idx = desc->amsdu_info & IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
	sub_frame_idx = desc->amsdu_info &
		IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;

	if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
		     dup_data->last_seq[tid] == hdr->seq_ctrl &&
@@ -862,23 +862,41 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
	struct ieee80211_rx_status *rx_status;
	struct iwl_rx_packet *pkt = rxb_addr(rxb);
	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
	struct ieee80211_hdr *hdr = (void *)(pkt->data + sizeof(*desc));
	struct ieee80211_hdr *hdr;
	u32 len = le16_to_cpu(desc->mpdu_len);
	u32 rate_n_flags = le32_to_cpu(desc->rate_n_flags);
	u32 rate_n_flags, gp2_on_air_rise;
	u16 phy_info = le16_to_cpu(desc->phy_info);
	struct ieee80211_sta *sta = NULL;
	struct sk_buff *skb;
	u8 crypt_len = 0;
	u8 crypt_len = 0, channel, energy_a, energy_b;
	struct ieee80211_radiotap_he *he = NULL;
	struct ieee80211_radiotap_he_mu *he_mu = NULL;
	u32 he_type = 0xffffffff;
	/* this is invalid e.g. because puncture type doesn't allow 0b11 */
#define HE_PHY_DATA_INVAL ((u64)-1)
	u64 he_phy_data = HE_PHY_DATA_INVAL;
	size_t desc_size;

	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
		return;

	if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
		rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
		channel = desc->v3.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
		energy_a = desc->v3.energy_a;
		energy_b = desc->v3.energy_b;
		desc_size = sizeof(*desc);
	} else {
		rate_n_flags = le32_to_cpu(desc->v1.rate_n_flags);
		channel = desc->v1.channel;
		gp2_on_air_rise = le32_to_cpu(desc->v1.gp2_on_air_rise);
		energy_a = desc->v1.energy_a;
		energy_b = desc->v1.energy_b;
		desc_size = IWL_RX_DESC_SIZE_V1;
	}

	hdr = (void *)(pkt->data + desc_size);
	/* Dont use dev_alloc_skb(), we'll have enough headroom once
	 * ieee80211_hdr pulled.
	 */
@@ -925,8 +943,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;

		if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) {
			he_phy_data =
				le64_to_cpu(desc->he_phy_data);
			if (mvm->trans->cfg->device_family >=
			    IWL_DEVICE_FAMILY_22560)
				he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
			else
				he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

			if (he_type == RATE_MCS_HE_TYPE_MU) {
				he_mu = skb_put_data(skb, &mu_known,
@@ -940,6 +961,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		__skb_pull(skb, radiotap_len);
	}

	rx_status = IEEE80211_SKB_RXCB(skb);

	if (iwl_mvm_rx_crypto(mvm, hdr, rx_status, phy_info, desc,
			      le32_to_cpu(pkt->len_n_flags), queue,
			      &crypt_len)) {
@@ -962,14 +985,28 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
		rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;

	if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
		rx_status->mactime = le64_to_cpu(desc->tsf_on_air_rise);
		u64 tsf_on_air_rise;

		if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
			tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
		else
			tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);

		rx_status->mactime = tsf_on_air_rise;
		/* TSF as indicated by the firmware is at INA time */
		rx_status->flag |= RX_FLAG_MACTIME_PLCP_START;
	} else if (he_type == RATE_MCS_HE_TYPE_SU) {
		u64 he_phy_data;

		if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
			he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
		else
			he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

		he->data1 |=
			cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN);
		if (FIELD_GET(IWL_RX_HE_PHY_UPLINK,
			      le64_to_cpu(desc->he_phy_data)))
			      he_phy_data))
			he->data3 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA3_UL_DL);

@@ -980,7 +1017,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
			rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
			if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
				      le64_to_cpu(desc->he_phy_data)))
				      he_phy_data))
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT;
		}
	} else if (he_mu && he_phy_data != HE_PHY_DATA_INVAL) {
@@ -1005,16 +1042,23 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
						   he_phy_data),
					 IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW);
	}
	rx_status->device_timestamp = le32_to_cpu(desc->gp2_on_air_rise);
	rx_status->band = desc->channel > 14 ? NL80211_BAND_5GHZ :
	rx_status->device_timestamp = gp2_on_air_rise;
	rx_status->band = channel > 14 ? NL80211_BAND_5GHZ :
		NL80211_BAND_2GHZ;
	rx_status->freq = ieee80211_channel_to_frequency(desc->channel,
	rx_status->freq = ieee80211_channel_to_frequency(channel,
							 rx_status->band);
	iwl_mvm_get_signal_strength(mvm, desc, rx_status);
	iwl_mvm_get_signal_strength(mvm, rx_status, rate_n_flags, energy_a,
				    energy_b);

	/* update aggregation data for monitor sake on default queue */
	if (!queue && (phy_info & IWL_RX_MPDU_PHY_AMPDU)) {
		bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE;
		u64 he_phy_data;

		if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
			he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
		else
			he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

		rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
		rx_status->ampdu_reference = mvm->ampdu_ref;
@@ -1027,7 +1071,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			    he_type == RATE_MCS_HE_TYPE_MU) {
				rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN;
				if (FIELD_GET(IWL_RX_HE_PHY_DELIM_EOF,
					      le64_to_cpu(desc->he_phy_data)))
					      he_phy_data))
					rx_status->flag |=
						RX_FLAG_AMPDU_EOF_BIT;
			}
@@ -1327,12 +1371,19 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
			break;
		case RATE_MCS_HE_TYPE_MU: {
			u16 val;
			u64 he_phy_data;

			if (mvm->trans->cfg->device_family >=
			    IWL_DEVICE_FAMILY_22560)
				he_phy_data = le64_to_cpu(desc->v3.he_phy_data);
			else
				he_phy_data = le64_to_cpu(desc->v1.he_phy_data);

			if (he_phy_data == HE_PHY_DATA_INVAL)
				break;

			val = FIELD_GET(IWL_RX_HE_PHY_HE_LTF_NUM_MASK,
					le64_to_cpu(desc->he_phy_data));
					he_phy_data);

			he->data2 |=
				cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN);