From kvalo at kernel.org  Mon Sep  5 10:27:20 2022
From: kvalo at kernel.org (Kalle Valo)
Date: Mon, 05 Sep 2022 20:27:20 +0300
Subject: [PATCH 12/50] wifi: ath12k: add dp.h
In-Reply-To: <0eabd6c1b3ca4d8a8152ad5b4f3efee6@realtek.com> (Ping-Ke Shih's
	message of "Mon, 15 Aug 2022 01:56:29 +0000")
References: <20220812161003.27279-1-kvalo@kernel.org>
	<20220812161003.27279-13-kvalo@kernel.org>
	<0eabd6c1b3ca4d8a8152ad5b4f3efee6@realtek.com>
Message-ID: <87leqxag07.fsf@kernel.org>

Ping-Ke Shih <pkshih at realtek.com> writes:

>> -----Original Message-----
>> From: Kalle Valo <kvalo at kernel.org>
>> Sent: Saturday, August 13, 2022 12:09 AM
>> To: linux-wireless at vger.kernel.org
>> Cc: ath12k at lists.infradead.org
>> Subject: [PATCH 12/50] wifi: ath12k: add dp.h
>> 
>> From: Kalle Valo <quic_kvalo at quicinc.com>
>> 
>> (Patches split into one patch per file for easier review, but the final
>> commit will be one big patch. See the cover letter for more info.)
>> 
>> Signed-off-by: Kalle Valo <quic_kvalo at quicinc.com>
>> ---
>>  drivers/net/wireless/ath/ath12k/dp.h | 2017 ++++++++++++++++++++++++++++++++++
>>  1 file changed, 2017 insertions(+)
>> 
>> diff --git a/drivers/net/wireless/ath/ath12k/dp.h
>> b/drivers/net/wireless/ath/ath12k/dp.h
>> new file mode 100644
>> index 000000000000..cf9610dffbb8
>> --- /dev/null
>> +++ b/drivers/net/wireless/ath/ath12k/dp.h
>
> [...]
>
>> +
>> +struct htt_srng_setup_cmd {
>> +	u32 info0;
>> +	u32 ring_base_addr_lo;
>> +	u32 ring_base_addr_hi;
>> +	u32 info1;
>> +	u32 ring_head_off32_remote_addr_lo;
>> +	u32 ring_head_off32_remote_addr_hi;
>> +	u32 ring_tail_off32_remote_addr_lo;
>> +	u32 ring_tail_off32_remote_addr_hi;
>> +	u32 ring_msi_addr_lo;
>> +	u32 ring_msi_addr_hi;
>> +	u32 msi_data;
>> +	u32 intr_info;
>> +	u32 info2;
>> +} __packed;
>> +
>
> Should they be '__le32' instead of 'u32'?
>
> This struct is used to fill data of ath12k_htc_send(), and the fields of
> htc header are __le32: 
>
> struct ath12k_htc_hdr {
> 	__le32 htc_info;
> 	__le32 ctrl_info;
> } __packed __aligned(4);
>
> If above is correct, some struct(s) related to ath12k_htc_send() have
> similar problems:
> struct htt_ver_req_cmd
> struct htt_ppdu_stats_cfg_cmd
> struct htt_rx_ring_selection_cfg_cmd
> struct htt_ext_stats_cfg_cmd
> struct htt_tx_ring_selection_cfg_cmd  (miss __packed)

Good catch, we'll fix those and the missing __packed. Thanks for the review!

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


From kvalo at kernel.org  Mon Sep  5 10:31:24 2022
From: kvalo at kernel.org (Kalle Valo)
Date: Mon, 05 Sep 2022 20:31:24 +0300
Subject: [PATCH 31/50] wifi: ath12k: add mac.c
In-Reply-To: <c9c4f3027e294e148bd595e3db1a62a8@realtek.com> (Ping-Ke Shih's
	message of "Mon, 15 Aug 2022 06:09:40 +0000")
References: <20220812161003.27279-1-kvalo@kernel.org>
	<20220812161003.27279-32-kvalo@kernel.org>
	<c9c4f3027e294e148bd595e3db1a62a8@realtek.com>
Message-ID: <87h71laftf.fsf@kernel.org>

Ping-Ke Shih <pkshih at realtek.com> writes:

>> +static int get_num_chains(u32 mask)
>> +{
>> +	int num_chains = 0;
>> +
>> +	while (mask) {
>> +		if (mask & BIT(0))
>> +			num_chains++;
>> +		mask >>= 1;
>> +	}
>> +
>> +	return num_chains;
>> +}
>
> use hweight32()?

Yup, we'll fix that. Thanks!

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches


From pkshih at realtek.com  Wed Sep  7 00:36:56 2022
From: pkshih at realtek.com (Ping-Ke Shih)
Date: Wed, 7 Sep 2022 07:36:56 +0000
Subject: [PATCH 46/50] wifi: ath12k: add wmi.c
In-Reply-To: <20220812161003.27279-47-kvalo@kernel.org>
References: <20220812161003.27279-1-kvalo@kernel.org>
 <20220812161003.27279-47-kvalo@kernel.org>
Message-ID: <cfcc540a6cd7432fb214f7a059fd4c31@realtek.com>



> -----Original Message-----
> From: Kalle Valo <kvalo at kernel.org>
> Sent: Saturday, August 13, 2022 12:10 AM
> To: linux-wireless at vger.kernel.org
> Cc: ath12k at lists.infradead.org
> Subject: [PATCH 46/50] wifi: ath12k: add wmi.c
> 
> From: Kalle Valo <quic_kvalo at quicinc.com>
> 
> (Patches split into one patch per file for easier review, but the final
> commit will be one big patch. See the cover letter for more info.)
> 
> Signed-off-by: Kalle Valo <quic_kvalo at quicinc.com>
> ---
>  drivers/net/wireless/ath/ath12k/wmi.c | 6558 +++++++++++++++++++++++++++++++++
>  1 file changed, 6558 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> new file mode 100644
> index 000000000000..82aaedb5d0af
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -0,0 +1,6558 @@

[...]

> +
> +static int ath12k_pull_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
> +				     const void *ptr,
> +				     struct ath12k_wmi_service_ext_arg *arg)
> +{
> +	const struct wmi_service_ready_ext_event *ev = ptr;
> +
> +	if (!ev)
> +		return -EINVAL;
> +
> +	/* Move this to host based bitmap */
> +	arg->default_conc_scan_config_bits =
> +		le32_to_cpu(ev->default_conc_scan_config_bits);
> +	arg->default_fw_config_bits = le32_to_cpu(ev->default_fw_config_bits);
> +	arg->he_cap_info = le32_to_cpu(ev->he_cap_info);
> +	arg->mpdu_density = le32_to_cpu(ev->mpdu_density);
> +	arg->max_bssid_rx_filters = le32_to_cpu(ev->max_bssid_rx_filters);
> +	memcpy(&arg->ppet, &ev->ppet, sizeof(arg->ppet));

Originally, I would like to say the memcpy() statement can be replaced by
arg->ppet = ev->ppet;

But I found the struct(s) are different:

arg->ppet is 

struct ath12k_wmi_ppe_threshold_arg {
	u32 numss_m1;
	u32 ru_bit_mask;
	u32 ppet16_ppet8_ru3_ru0[PSOC_HOST_MAX_NUM_SS];
};

ev->ppet is

struct ath12k_wmi_ppe_threshold_params {
	__le32 numss_m1; /** NSS - 1*/
	union {
		__le32 ru_count;
		__le32 ru_mask;
	} __packed;
	__le32 ppet16_ppet8_ru3_ru0[WMI_MAX_NUM_SS];
} __packed;

Then, using memcpy() doesn't work on big-endian machine.

> +
> +	return 0;
> +}
> +
> +static int
> +ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
> +				      struct ath12k_wmi_svc_rdy_ext_parse *svc,
> +				      u8 hw_mode_id, u8 phy_id,
> +				      struct ath12k_pdev *pdev)
> +{
> +	const struct ath12k_wmi_mac_phy_caps_params *mac_phy_caps;
> +	const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps;
> +	const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps;
> +	const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps;
> +	struct ath12k_band_cap *cap_band;
> +	struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
> +	u32 phy_map;
> +	u32 hw_idx, phy_idx = 0;
> +
> +	if (!hw_caps || !wmi_hw_mode_caps || !svc->soc_hal_reg_caps)
> +		return -EINVAL;
> +
> +	for (hw_idx = 0; hw_idx < le32_to_cpu(hw_caps->num_hw_modes); hw_idx++) {
> +		if (hw_mode_id == le32_to_cpu(wmi_hw_mode_caps[hw_idx].hw_mode_id))
> +			break;
> +
> +		phy_map = le32_to_cpu(wmi_hw_mode_caps[hw_idx].phy_id_map);
> +		while (phy_map) {
> +			phy_map >>= 1;
> +			phy_idx++;
> +		}

phy_idx = fls(phy_map)

> +	}
> +
> +	if (hw_idx == le32_to_cpu(hw_caps->num_hw_modes))
> +		return -EINVAL;
> +
> +	phy_idx += phy_id;
> +	if (phy_id >= le32_to_cpu(svc->soc_hal_reg_caps->num_phy))
> +		return -EINVAL;
> +
> +	mac_phy_caps = wmi_mac_phy_caps + phy_idx;
> +
> +	pdev->pdev_id = le32_to_cpu(mac_phy_caps->pdev_id);
> +	pdev_cap->supported_bands |= le32_to_cpu(mac_phy_caps->supported_bands);
> +	pdev_cap->ampdu_density = le32_to_cpu(mac_phy_caps->ampdu_density);
> +
> +	/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from
> +	 * band to band for a single radio, need to see how this should be
> +	 * handled.
> +	 */
> +	if (le32_to_cpu(mac_phy_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {
> +		pdev_cap->tx_chain_mask = le32_to_cpu(mac_phy_caps->tx_chain_mask_2g);
> +		pdev_cap->rx_chain_mask = le32_to_cpu(mac_phy_caps->rx_chain_mask_2g);
> +	} else if (le32_to_cpu(mac_phy_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {
> +		pdev_cap->vht_cap = le32_to_cpu(mac_phy_caps->vht_cap_info_5g);
> +		pdev_cap->vht_mcs = le32_to_cpu(mac_phy_caps->vht_supp_mcs_5g);
> +		pdev_cap->he_mcs = le32_to_cpu(mac_phy_caps->he_supp_mcs_5g);
> +		pdev_cap->tx_chain_mask = le32_to_cpu(mac_phy_caps->tx_chain_mask_5g);
> +		pdev_cap->rx_chain_mask = le32_to_cpu(mac_phy_caps->rx_chain_mask_5g);
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	/* tx/rx chainmask reported from fw depends on the actual hw chains used,
> +	 * For example, for 4x4 capable macphys, first 4 chains can be used for first
> +	 * mac and the remaing 4 chains can be used for the second mac or vice-versa.
> +	 * In this case, tx/rx chainmask 0xf will be advertised for first mac and 0xf0
> +	 * will be advertised for second mac or vice-versa. Compute the shift value
> +	 * for tx/rx chainmask which will be used to advertise supported ht/vht rates to
> +	 * mac80211.
> +	 */
> +	pdev_cap->tx_chain_mask_shift =
> +			find_first_bit((unsigned long *)&pdev_cap->tx_chain_mask, 32);
> +	pdev_cap->rx_chain_mask_shift =
> +			find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);
> +
> +	if (le32_to_cpu(mac_phy_caps->supported_bands) & WMI_HOST_WLAN_2G_CAP) {
> +		cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
> +		cap_band->phy_id = le32_to_cpu(mac_phy_caps->phy_id);
> +		cap_band->max_bw_supported =
> +			le32_to_cpu(mac_phy_caps->max_bw_supported_2g);
> +		cap_band->ht_cap_info = le32_to_cpu(mac_phy_caps->ht_cap_info_2g);
> +		cap_band->he_cap_info[0] = le32_to_cpu(mac_phy_caps->he_cap_info_2g);
> +		cap_band->he_cap_info[1] = le32_to_cpu(mac_phy_caps->he_cap_info_2g_ext);
> +		cap_band->he_mcs = le32_to_cpu(mac_phy_caps->he_supp_mcs_2g);
> +		memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_2g,
> +		       sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
> +		memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet2g,
> +		       sizeof(struct ath12k_wmi_ppe_threshold_arg));

These two copy __le32 to u32.

> +	}
> +
> +	if (le32_to_cpu(mac_phy_caps->supported_bands) & WMI_HOST_WLAN_5G_CAP) {
> +		cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
> +		cap_band->phy_id = le32_to_cpu(mac_phy_caps->phy_id);
> +		cap_band->max_bw_supported =
> +			le32_to_cpu(mac_phy_caps->max_bw_supported_5g);
> +		cap_band->ht_cap_info = le32_to_cpu(mac_phy_caps->ht_cap_info_5g);
> +		cap_band->he_cap_info[0] = le32_to_cpu(mac_phy_caps->he_cap_info_5g);
> +		cap_band->he_cap_info[1] = le32_to_cpu(mac_phy_caps->he_cap_info_5g_ext);
> +		cap_band->he_mcs = le32_to_cpu(mac_phy_caps->he_supp_mcs_5g);
> +		memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
> +		       sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
> +		memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
> +		       sizeof(struct ath12k_wmi_ppe_threshold_arg));

copy __le32 to u32

> +
> +		cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];
> +		cap_band->max_bw_supported =
> +			le32_to_cpu(mac_phy_caps->max_bw_supported_5g);
> +		cap_band->ht_cap_info = le32_to_cpu(mac_phy_caps->ht_cap_info_5g);
> +		cap_band->he_cap_info[0] = le32_to_cpu(mac_phy_caps->he_cap_info_5g);
> +		cap_band->he_cap_info[1] = le32_to_cpu(mac_phy_caps->he_cap_info_5g_ext);
> +		cap_band->he_mcs = le32_to_cpu(mac_phy_caps->he_supp_mcs_5g);
> +		memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
> +		       sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
> +		memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
> +		       sizeof(struct ath12k_wmi_ppe_threshold_arg));

and, these two.

It seems like we don't have a simple way to convert struct with __le32 to
another struct with cpu order. The only way is to convert fields of struct
one by one.

> +	}
> +
> +	return 0;
> +}
> +

[...]

> +int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id,
> +			 struct sk_buff *frame)
> +{
> +	struct ath12k_wmi_pdev *wmi = ar->wmi;
> +	struct wmi_mgmt_send_cmd *cmd;
> +	struct wmi_tlv *frame_tlv;
> +	struct sk_buff *skb;
> +	u32 buf_len;
> +	int ret, len;
> +
> +	buf_len = frame->len < WMI_MGMT_SEND_DOWNLD_LEN ?
> +		  frame->len : WMI_MGMT_SEND_DOWNLD_LEN;

buf_len = min(frame->len, WMI_MGMT_SEND_DOWNLD_LEN);

[...]

> +
> +int ath12k_wmi_vdev_install_key(struct ath12k *ar,
> +				struct wmi_vdev_install_key_arg *arg)
> +{
> +	struct ath12k_wmi_pdev *wmi = ar->wmi;
> +	struct wmi_vdev_install_key_cmd *cmd;
> +	struct wmi_tlv *tlv;
> +	struct sk_buff *skb;
> +	int ret, len;
> +	int key_len_aligned = roundup(arg->key_len, sizeof(uint32_t));

Not sure why 'uint32_t'?  Maybe, just '4' like other wmi functions.

mac80211 defines 
struct ieee80211_key_conf {
	u8 key[];
};

And, this driver defines
struct wmi_vdev_install_key_arg {
	const void *key_data;
};

> +
> +	len = sizeof(*cmd) + TLV_HDR_SIZE + key_len_aligned;
> +
> +	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
> +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_VDEV_INSTALL_KEY_CMD,
> +						 sizeof(*cmd));
> +	cmd->vdev_id = cpu_to_le32(arg->vdev_id);
> +	ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
> +	cmd->key_idx = cpu_to_le32(arg->key_idx);
> +	cmd->key_flags = cpu_to_le32(arg->key_flags);
> +	cmd->key_cipher = cpu_to_le32(arg->key_cipher);
> +	cmd->key_len = cpu_to_le32(arg->key_len);
> +	cmd->key_txmic_len = cpu_to_le32(arg->key_txmic_len);
> +	cmd->key_rxmic_len = cpu_to_le32(arg->key_rxmic_len);
> +
> +	if (arg->key_rsc_counter)
> +		cmd->key_rsc_counter = cpu_to_le64(arg->key_rsc_counter);
> +
> +	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
> +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, key_len_aligned);
> +	memcpy(tlv->value, arg->key_data, key_len_aligned);

If arg->key_len wasn't align of 4, this could access out of range of arg->key_data.

[...]

> +
> +int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
> +				   struct ath12k_wmi_peer_assoc_arg *arg)
> +{
> +	struct ath12k_wmi_pdev *wmi = ar->wmi;
> +	struct wmi_peer_assoc_complete_cmd *cmd;
> +	struct ath12k_wmi_vht_rate_set_params *mcs;
> +	struct ath12k_wmi_he_rate_set_params *he_mcs;
> +	struct sk_buff *skb;
> +	struct wmi_tlv *tlv;
> +	void *ptr;
> +	u32 peer_legacy_rates_align;
> +	u32 peer_ht_rates_align;
> +	int i, ret, len;
> +
> +	peer_legacy_rates_align = roundup(arg->peer_legacy_rates.num_rates,
> +					  sizeof(u32));
> +	peer_ht_rates_align = roundup(arg->peer_ht_rates.num_rates,
> +				      sizeof(u32));
> +
> +	len = sizeof(*cmd) +
> +	      TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) +
> +	      TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) +
> +	      sizeof(*mcs) + TLV_HDR_SIZE +
> +	      (sizeof(*he_mcs) * arg->peer_he_mcs_count);
> +
> +	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	ptr = skb->data;
> +
> +	cmd = ptr;
> +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PEER_ASSOC_COMPLETE_CMD,
> +						 sizeof(*cmd));
> +
> +	cmd->vdev_id = cpu_to_le32(arg->vdev_id);
> +
> +	cmd->peer_new_assoc = cpu_to_le32(arg->peer_new_assoc);
> +	cmd->peer_associd = cpu_to_le32(arg->peer_associd);
> +
> +	ath12k_wmi_copy_peer_flags(cmd, arg,
> +				   test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED,
> +					    &ar->ab->dev_flags));
> +
> +	ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_mac);
> +
> +	cmd->peer_rate_caps = cpu_to_le32(arg->peer_rate_caps);
> +	cmd->peer_caps = cpu_to_le32(arg->peer_caps);
> +	cmd->peer_listen_intval = cpu_to_le32(arg->peer_listen_intval);
> +	cmd->peer_ht_caps = cpu_to_le32(arg->peer_ht_caps);
> +	cmd->peer_max_mpdu = cpu_to_le32(arg->peer_max_mpdu);
> +	cmd->peer_mpdu_density = cpu_to_le32(arg->peer_mpdu_density);
> +	cmd->peer_vht_caps = cpu_to_le32(arg->peer_vht_caps);
> +	cmd->peer_phymode = cpu_to_le32(arg->peer_phymode);
> +
> +	/* Update 11ax capabilities */
> +	cmd->peer_he_cap_info = cpu_to_le32(arg->peer_he_cap_macinfo[0]);
> +	cmd->peer_he_cap_info_ext = cpu_to_le32(arg->peer_he_cap_macinfo[1]);
> +	cmd->peer_he_cap_info_internal = cpu_to_le32(arg->peer_he_cap_macinfo_internal);
> +	cmd->peer_he_caps_6ghz = cpu_to_le32(arg->peer_he_caps_6ghz);
> +	cmd->peer_he_ops = cpu_to_le32(arg->peer_he_ops);
> +	memcpy(&cmd->peer_he_cap_phy, &arg->peer_he_cap_phyinfo,
> +	       sizeof(arg->peer_he_cap_phyinfo));
> +	memcpy(&cmd->peer_ppet, &arg->peer_ppet,
> +	       sizeof(arg->peer_ppet));

copy u32 to __le32

[...]

> +
> +int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar,
> +				   struct ath12k_wmi_scan_req_arg *arg)
> +{
> +	struct ath12k_wmi_pdev *wmi = ar->wmi;
> +	struct wmi_start_scan_cmd *cmd;
> +	struct ath12k_wmi_ssid_params *ssid = NULL;
> +	struct ath12k_wmi_mac_addr_params *bssid;
> +	struct sk_buff *skb;
> +	struct wmi_tlv *tlv;
> +	void *ptr;
> +	int i, ret, len;
> +	u32 *tmp_ptr;
> +	u8 extraie_len_with_pad = 0;
> +	struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL;
> +	struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL;
> +
> +	len = sizeof(*cmd);
> +
> +	len += TLV_HDR_SIZE;
> +	if (arg->num_chan)
> +		len += arg->num_chan * sizeof(u32);
> +
> +	len += TLV_HDR_SIZE;
> +	if (arg->num_ssids)
> +		len += arg->num_ssids * sizeof(*ssid);
> +
> +	len += TLV_HDR_SIZE;
> +	if (arg->num_bssid)
> +		len += sizeof(*bssid) * arg->num_bssid;
> +
> +	len += TLV_HDR_SIZE;
> +	if (arg->extraie.len)
> +		extraie_len_with_pad =
> +			roundup(arg->extraie.len, sizeof(u32));
> +	len += extraie_len_with_pad;
> +
> +	if (arg->num_hint_bssid)
> +		len += TLV_HDR_SIZE +
> +		       arg->num_hint_bssid * sizeof(*hint_bssid);
> +
> +	if (arg->num_hint_s_ssid)
> +		len += TLV_HDR_SIZE +
> +		       arg->num_hint_s_ssid * sizeof(*s_ssid);
> +
> +	skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	ptr = skb->data;
> +
> +	cmd = ptr;
> +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_START_SCAN_CMD,
> +						 sizeof(*cmd));
> +
> +	cmd->scan_id = cpu_to_le32(arg->scan_id);
> +	cmd->scan_req_id = cpu_to_le32(arg->scan_req_id);
> +	cmd->vdev_id = cpu_to_le32(arg->vdev_id);
> +	cmd->scan_priority = cpu_to_le32(arg->scan_priority);
> +	cmd->notify_scan_events = cpu_to_le32(arg->notify_scan_events);
> +
> +	ath12k_wmi_copy_scan_event_cntrl_flags(cmd, arg);
> +
> +	cmd->dwell_time_active = cpu_to_le32(arg->dwell_time_active);
> +	cmd->dwell_time_active_2g = cpu_to_le32(arg->dwell_time_active_2g);
> +	cmd->dwell_time_passive = cpu_to_le32(arg->dwell_time_passive);
> +	cmd->dwell_time_active_6g = cpu_to_le32(arg->dwell_time_active_6g);
> +	cmd->dwell_time_passive_6g = cpu_to_le32(arg->dwell_time_passive_6g);
> +	cmd->min_rest_time = cpu_to_le32(arg->min_rest_time);
> +	cmd->max_rest_time = cpu_to_le32(arg->max_rest_time);
> +	cmd->repeat_probe_time = cpu_to_le32(arg->repeat_probe_time);
> +	cmd->probe_spacing_time = cpu_to_le32(arg->probe_spacing_time);
> +	cmd->idle_time = cpu_to_le32(arg->idle_time);
> +	cmd->max_scan_time = cpu_to_le32(arg->max_scan_time);
> +	cmd->probe_delay = cpu_to_le32(arg->probe_delay);
> +	cmd->burst_duration = cpu_to_le32(arg->burst_duration);
> +	cmd->num_chan = cpu_to_le32(arg->num_chan);
> +	cmd->num_bssid = cpu_to_le32(arg->num_bssid);
> +	cmd->num_ssids = cpu_to_le32(arg->num_ssids);
> +	cmd->ie_len = cpu_to_le32(arg->extraie.len);
> +	cmd->n_probes = cpu_to_le32(arg->n_probes);
> +
> +	ptr += sizeof(*cmd);
> +
> +	len = arg->num_chan * sizeof(u32);
> +
> +	tlv = ptr;
> +	tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, len);
> +	ptr += TLV_HDR_SIZE;
> +	tmp_ptr = (u32 *)ptr;
> +
> +	for (i = 0; i < arg->num_chan; ++i)
> +		tmp_ptr[i] = arg->chan_list[i];

nit.
memcpy(tmp_ptr, arg->chan_list, arg->num_chan);

[...]

> +
> +int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,
> +				       struct ath12k_wmi_scan_chan_list_arg *arg)
> +{
> +	struct ath12k_wmi_pdev *wmi = ar->wmi;
> +	struct wmi_scan_chan_list_cmd *cmd;
> +	struct sk_buff *skb;
> +	struct ath12k_wmi_channel_params *chan_info;
> +	struct ath12k_wmi_channel_arg *channel_arg;
> +	struct wmi_tlv *tlv;
> +	void *ptr;
> +	int i, ret, len;
> +	u16 num_send_chans, num_sends = 0, max_chan_limit = 0;
> +	__le32 *reg1, *reg2;
> +
> +	channel_arg = &arg->channel[0];
> +	while (arg->nallchans) {
> +		len = sizeof(*cmd) + TLV_HDR_SIZE;
> +		max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
> +			sizeof(*chan_info);
> +
> +		if (arg->nallchans > max_chan_limit)
> +			num_send_chans = max_chan_limit;
> +		else
> +			num_send_chans = arg->nallchans;

num_send_chans = min(arg->nallchans, max_chan_limit);


[...]

> +static void
> +ath12k_wmi_copy_resource_config(struct ath12k_wmi_resource_config_params *wmi_cfg,
> +				struct ath12k_wmi_resource_config_arg *tg_cfg)
> +{
> +	wmi_cfg->num_vdevs = cpu_to_le32(tg_cfg->num_vdevs);
> +	wmi_cfg->num_peers = cpu_to_le32(tg_cfg->num_peers);
> +	wmi_cfg->num_offload_peers = cpu_to_le32(tg_cfg->num_offload_peers);
> +	wmi_cfg->num_offload_reorder_buffs =
> +		cpu_to_le32(tg_cfg->num_offload_reorder_buffs);
> +	wmi_cfg->num_peer_keys = cpu_to_le32(tg_cfg->num_peer_keys);
> +	wmi_cfg->num_tids = cpu_to_le32(tg_cfg->num_tids);
> +	wmi_cfg->ast_skid_limit = cpu_to_le32(tg_cfg->ast_skid_limit);
> +	wmi_cfg->tx_chain_mask = cpu_to_le32(tg_cfg->tx_chain_mask);
> +	wmi_cfg->rx_chain_mask = cpu_to_le32(tg_cfg->rx_chain_mask);
> +	wmi_cfg->rx_timeout_pri[0] = cpu_to_le32(tg_cfg->rx_timeout_pri[0]);
> +	wmi_cfg->rx_timeout_pri[1] = cpu_to_le32(tg_cfg->rx_timeout_pri[1]);
> +	wmi_cfg->rx_timeout_pri[2] = cpu_to_le32(tg_cfg->rx_timeout_pri[2]);
> +	wmi_cfg->rx_timeout_pri[3] = cpu_to_le32(tg_cfg->rx_timeout_pri[3]);
> +	wmi_cfg->rx_decap_mode = cpu_to_le32(tg_cfg->rx_decap_mode);
> +	wmi_cfg->scan_max_pending_req = cpu_to_le32(tg_cfg->scan_max_pending_req);
> +	wmi_cfg->bmiss_offload_max_vdev = cpu_to_le32(tg_cfg->bmiss_offload_max_vdev);
> +	wmi_cfg->roam_offload_max_vdev = cpu_to_le32(tg_cfg->roam_offload_max_vdev);
> +	wmi_cfg->roam_offload_max_ap_profiles =
> +		cpu_to_le32(tg_cfg->roam_offload_max_ap_profiles);
> +	wmi_cfg->num_mcast_groups = cpu_to_le32(tg_cfg->num_mcast_groups);
> +	wmi_cfg->num_mcast_table_elems = cpu_to_le32(tg_cfg->num_mcast_table_elems);
> +	wmi_cfg->mcast2ucast_mode = cpu_to_le32(tg_cfg->mcast2ucast_mode);
> +	wmi_cfg->tx_dbg_log_size = cpu_to_le32(tg_cfg->tx_dbg_log_size);
> +	wmi_cfg->num_wds_entries = cpu_to_le32(tg_cfg->num_wds_entries);
> +	wmi_cfg->dma_burst_size = cpu_to_le32(tg_cfg->dma_burst_size);
> +	wmi_cfg->mac_aggr_delim = cpu_to_le32(tg_cfg->mac_aggr_delim);
> +	wmi_cfg->rx_skip_defrag_timeout_dup_detection_check =
> +		cpu_to_le32(tg_cfg->rx_skip_defrag_timeout_dup_detection_check);
> +	wmi_cfg->vow_config = cpu_to_le32(tg_cfg->vow_config);
> +	wmi_cfg->gtk_offload_max_vdev = cpu_to_le32(tg_cfg->gtk_offload_max_vdev);
> +	wmi_cfg->num_msdu_desc = cpu_to_le32(tg_cfg->num_msdu_desc);
> +	wmi_cfg->max_frag_entries = cpu_to_le32(tg_cfg->max_frag_entries);
> +	wmi_cfg->num_tdls_vdevs = cpu_to_le32(tg_cfg->num_tdls_vdevs);
> +	wmi_cfg->num_tdls_conn_table_entries =
> +		cpu_to_le32(tg_cfg->num_tdls_conn_table_entries);
> +	wmi_cfg->beacon_tx_offload_max_vdev =
> +		cpu_to_le32(tg_cfg->beacon_tx_offload_max_vdev);
> +	wmi_cfg->num_multicast_filter_entries =
> +		cpu_to_le32(tg_cfg->num_multicast_filter_entries);
> +	wmi_cfg->num_wow_filters = cpu_to_le32(tg_cfg->num_wow_filters);
> +	wmi_cfg->num_keep_alive_pattern = cpu_to_le32(tg_cfg->num_keep_alive_pattern);
> +	wmi_cfg->keep_alive_pattern_size = cpu_to_le32(tg_cfg->keep_alive_pattern_size);
> +	wmi_cfg->max_tdls_concurrent_sleep_sta =
> +		cpu_to_le32(tg_cfg->max_tdls_concurrent_sleep_sta);
> +	wmi_cfg->max_tdls_concurrent_buffer_sta =
> +		cpu_to_le32(tg_cfg->max_tdls_concurrent_buffer_sta);
> +	wmi_cfg->wmi_send_separate = cpu_to_le32(tg_cfg->wmi_send_separate);
> +	wmi_cfg->num_ocb_vdevs = cpu_to_le32(tg_cfg->num_ocb_vdevs);
> +	wmi_cfg->num_ocb_channels = cpu_to_le32(tg_cfg->num_ocb_channels);
> +	wmi_cfg->num_ocb_schedules = cpu_to_le32(tg_cfg->num_ocb_schedules);
> +	wmi_cfg->bpf_instruction_size = cpu_to_le32(tg_cfg->bpf_instruction_size);
> +	wmi_cfg->max_bssid_rx_filters = cpu_to_le32(tg_cfg->max_bssid_rx_filters);
> +	wmi_cfg->use_pdev_id = cpu_to_le32(tg_cfg->use_pdev_id);
> +	wmi_cfg->flag1 = cpu_to_le32(tg_cfg->atf_config);
> +	wmi_cfg->peer_map_unmap_version = cpu_to_le32(tg_cfg->peer_map_unmap_version);
> +	wmi_cfg->sched_params = cpu_to_le32(tg_cfg->sched_params);
> +	wmi_cfg->twt_ap_pdev_count = cpu_to_le32(tg_cfg->twt_ap_pdev_count);
> +	wmi_cfg->twt_ap_sta_count = cpu_to_le32(tg_cfg->twt_ap_sta_count);
> +	wmi_cfg->host_service_flags |=
> +		cpu_to_le32(1 << WMI_RSRC_CFG_HOST_SVC_FLAG_REG_CC_EXT_SUPPORT_BIT);

Why not just '=' instead of '|=' ?

> +}
> +

[...]

> +
> +int ath12k_wmi_pdev_lro_cfg(struct ath12k *ar,
> +			    int pdev_id)
> +{
> +	struct ath12k_wmi_pdev_lro_config_cmd *cmd;
> +	struct sk_buff *skb;
> +	int ret;
> +
> +	skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, sizeof(*cmd));
> +	if (!skb)
> +		return -ENOMEM;
> +
> +	cmd = (struct ath12k_wmi_pdev_lro_config_cmd *)skb->data;
> +	cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_LRO_INFO_CMD,
> +						 sizeof(*cmd));
> +
> +	get_random_bytes(cmd->th_4, sizeof(uint32_t) * ATH12K_IPV4_TH_SEED_SIZE);
> +	get_random_bytes(cmd->th_6, sizeof(uint32_t) * ATH12K_IPV6_TH_SEED_SIZE);

get_random_bytes(cmd->th_4, sizeof(cmd->th_4));
get_random_bytes(cmd->th_6, sizeof(cmd->th_6));

> +
> +	cmd->pdev_id = cpu_to_le32(pdev_id);
> +
> +	ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_LRO_CONFIG_CMDID);
> +	if (ret) {
> +		ath12k_warn(ar->ab,
> +			    "failed to send lro cfg req wmi cmd\n");
> +		goto err;
> +	}
> +
> +	ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
> +		   "WMI lro cfg cmd pdev_id 0x%x\n", pdev_id);
> +	return 0;
> +err:
> +	dev_kfree_skb(skb);
> +	return ret;
> +}
> +

[...]

> +
> +static int ath12k_wmi_hw_mode_caps_parse(struct ath12k_base *soc,
> +					 u16 tag, u16 len,
> +					 const void *ptr, void *data)
> +{
> +	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;
> +	struct ath12k_wmi_hw_mode_cap_params *hw_mode_cap;
> +	u32 phy_map = 0;
> +
> +	if (tag != WMI_TAG_HW_MODE_CAPABILITIES)
> +		return -EPROTO;
> +
> +	if (svc_rdy_ext->n_hw_mode_caps >= svc_rdy_ext->arg.num_hw_modes)
> +		return -ENOBUFS;
> +
> +	hw_mode_cap = container_of(ptr, struct ath12k_wmi_hw_mode_cap_params,
> +				   hw_mode_id);
> +	svc_rdy_ext->n_hw_mode_caps++;
> +
> +	phy_map = le32_to_cpu(hw_mode_cap->phy_id_map);
> +	while (phy_map) {
> +		svc_rdy_ext->tot_phy_id++;
> +		phy_map = phy_map >> 1;
> +	}

svc_rdy_ext->tot_phy_id = fls(phy_map);
or
svc_rdy_ext->tot_phy_id += fls(phy_map);

> +
> +	return 0;
> +}
> +
> +static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
> +				   u16 len, const void *ptr, void *data)
> +{
> +	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;
> +	const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps;
> +	enum wmi_host_hw_mode_config_type mode, pref;
> +	u32 i;
> +	int ret;
> +
> +	svc_rdy_ext->n_hw_mode_caps = 0;
> +	svc_rdy_ext->hw_mode_caps = ptr;
> +
> +	ret = ath12k_wmi_tlv_iter(soc, ptr, len,
> +				  ath12k_wmi_hw_mode_caps_parse,
> +				  svc_rdy_ext);
> +	if (ret) {
> +		ath12k_warn(soc, "failed to parse tlv %d\n", ret);
> +		return ret;
> +	}
> +
> +	i = 0;
> +	while (i < svc_rdy_ext->n_hw_mode_caps) {

for (i = 0; i < svc_rdy_ext->n_hw_mode_caps; i++) {

> +		hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
> +		mode = le32_to_cpu(hw_mode_caps->hw_mode_id);
> +		pref = soc->wmi_ab.preferred_hw_mode;
> +
> +		if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
> +			svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps;
> +			soc->wmi_ab.preferred_hw_mode = mode;
> +		}
> +		i++;

With 'for', remove this i++.

> +	}
> +
> +	ath12k_dbg(soc, ATH12K_DBG_WMI, "preferred_hw_mode:%d\n",
> +		   soc->wmi_ab.preferred_hw_mode);
> +	if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +

[...]

> +
> +static int ath12k_wmi_ext_hal_reg_caps(struct ath12k_base *soc,
> +				       u16 len, const void *ptr, void *data)
> +{
> +	struct ath12k_wmi_pdev *wmi_handle = &soc->wmi_ab.wmi[0];
> +	struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data;
> +	struct ath12k_wmi_hal_reg_capabilities_ext_arg reg_cap;
> +	int ret;
> +	u32 i;
> +
> +	svc_rdy_ext->n_ext_hal_reg_caps = 0;
> +	svc_rdy_ext->ext_hal_reg_caps = ptr;
> +	ret = ath12k_wmi_tlv_iter(soc, ptr, len,
> +				  ath12k_wmi_ext_hal_reg_caps_parse,
> +				  svc_rdy_ext);
> +	if (ret) {
> +		ath12k_warn(soc, "failed to parse tlv %d\n", ret);
> +		return ret;
> +	}
> +
> +	for (i = 0; i < svc_rdy_ext->arg.num_phy; i++) {
> +		ret = ath12k_pull_reg_cap_svc_rdy_ext(wmi_handle,
> +						      svc_rdy_ext->soc_hal_reg_caps,
> +						      svc_rdy_ext->ext_hal_reg_caps, i,
> +						      &reg_cap);
> +		if (ret) {
> +			ath12k_warn(soc, "failed to extract reg cap %d\n", i);
> +			return ret;
> +		}
> +
> +		memcpy(&soc->hal_reg_cap[reg_cap.phy_id],
> +		       &reg_cap, sizeof(reg_cap));

soc->hal_reg_cap[reg_cap.phy_id] = reg_cap;

> +	}
> +	return 0;
> +}
> +

[...]

> +
> +static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
> +{

[...]

> +
> +	/* Avoid multiple overwrites to default regd, during core
> +	 * stop-start after mac registration.
> +	 */
> +	if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
> +	    !memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
> +		    (char *)reg_info->alpha2, 2))

cast "(char *)" is unnecessary.


> +		goto mem_free;
> +
> +	/* Intersect new rules with default regd if a new country setting was
> +	 * requested, i.e a default regd was already set during initialization
> +	 * and the regd coming from this event has a valid country info.
> +	 */

[...]

> +
> +static void ath12k_mgmt_rx_event(struct ath12k_base *ab, struct sk_buff *skb)
> +{

[...]

> +
> +	if ((test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) ||
> +	    (rx_ev.status & (WMI_RX_STATUS_ERR_DECRYPT |
> +	    WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {

nit: coding style

	if ((test_bit(ATH12K_CAC_RUNNING, &ar->dev_flags)) ||
	    (rx_ev.status & (WMI_RX_STATUS_ERR_DECRYPT |
			     WMI_RX_STATUS_ERR_KEY_CACHE_MISS |
			     WMI_RX_STATUS_ERR_CRC))) {

> +		dev_kfree_skb(skb);
> +		goto exit;
> +	}
> +

[...]

> +
> +static int ath12k_connect_pdev_htc_service(struct ath12k_base *ab,
> +					   u32 pdev_idx)
> +{
> +	int status;
> +	u32 svc_id[] = { ATH12K_HTC_SVC_ID_WMI_CONTROL,
> +			 ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1,
> +			 ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2 };
> +

nit.
coding style: no blank line within declaration.

> +	struct ath12k_htc_svc_conn_req conn_req = {};
> +	struct ath12k_htc_svc_conn_resp conn_resp = {};
> +
> +	/* these fields are the same for all service endpoints */
> +	conn_req.ep_ops.ep_tx_complete = ath12k_wmi_htc_tx_complete;
> +	conn_req.ep_ops.ep_rx_complete = ath12k_wmi_op_rx;
> +	conn_req.ep_ops.ep_tx_credits = ath12k_wmi_op_ep_tx_credits;

[...]




From pkshih at realtek.com  Mon Sep 12 21:28:18 2022
From: pkshih at realtek.com (Ping-Ke Shih)
Date: Tue, 13 Sep 2022 04:28:18 +0000
Subject: [PATCH 03/50] wifi: ath12k: add ce.c
In-Reply-To: <20220812161003.27279-4-kvalo@kernel.org>
References: <20220812161003.27279-1-kvalo@kernel.org>
 <20220812161003.27279-4-kvalo@kernel.org>
Message-ID: <3634f14f162a4a9fb9c1c89647b9a29d@realtek.com>


> -----Original Message-----
> From: Kalle Valo <kvalo at kernel.org>
> Sent: Saturday, August 13, 2022 12:09 AM
> To: linux-wireless at vger.kernel.org
> Cc: ath12k at lists.infradead.org
> Subject: [PATCH 03/50] wifi: ath12k: add ce.c
> 
> From: Kalle Valo <quic_kvalo at quicinc.com>
> 
> (Patches split into one patch per file for easier review, but the final
> commit will be one big patch. See the cover letter for more info.)
> 
> Signed-off-by: Kalle Valo <quic_kvalo at quicinc.com>
> ---
>  drivers/net/wireless/ath/ath12k/ce.c | 971 +++++++++++++++++++++++++++++++++++
>  1 file changed, 971 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/ce.c b/drivers/net/wireless/ath/ath12k/ce.c
> new file mode 100644
> index 000000000000..5694eef37232
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath12k/ce.c

[...]

> +
> +static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
> +					 struct sk_buff *skb, dma_addr_t paddr)
> +{
> +	struct ath12k_base *ab = pipe->ab;
> +	struct ath12k_ce_ring *ring = pipe->dest_ring;
> +	struct hal_srng *srng;
> +	unsigned int write_index;
> +	unsigned int nentries_mask = ring->nentries_mask;
> +	struct hal_ce_srng_dest_desc *desc;
> +	int ret;
> +

[...]

> +
> +	ring->skb[write_index] = skb;
> +	write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
> +	ring->write_index = write_index;
> +
> +	pipe->rx_buf_needed--;
> +
> +	ret = 0;

nit.
I think '= 0' can be initializer like other functions.

> +exit:
> +	ath12k_hal_srng_access_end(ab, srng);
> +
> +	spin_unlock_bh(&srng->lock);
> +
> +	return ret;
> +}
> +
> +static int ath12k_ce_rx_post_pipe(struct ath12k_ce_pipe *pipe)
> +{

[...]

> +
> +		ATH12K_SKB_RXCB(skb)->paddr = paddr;
> +
> +		ret = ath12k_ce_rx_buf_enqueue_pipe(pipe, skb, paddr);
> +

nit.
this blank line can be removed.

> +		if (ret) {
> +			ath12k_warn(ab, "failed to enqueue rx buf: %d\n", ret);
> +			dma_unmap_single(ab->dev, paddr,
> +					 skb->len + skb_tailroom(skb),
> +					 DMA_FROM_DEVICE);
> +			dev_kfree_skb_any(skb);
> +			goto exit;
> +		}
> +	}
> +
> +exit:
> +	spin_unlock_bh(&ab->ce.ce_lock);
> +	return ret;
> +}
> +

[...]

> +
> +int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id,
> +		   u16 transfer_id)
> +{

[...]

> +
> +	ath12k_hal_srng_access_end(ab, srng);
> +
> +	spin_unlock_bh(&srng->lock);
> +
> +	spin_unlock_bh(&ab->ce.ce_lock);

Two unlock are duplicate of err_unlock. I think they can be merged to a single
copy to reduce maintain effort. If my opinion is accepted, maybe rename
err_unlock to out_unlock because it becomes a normal flow.

> +
> +	return 0;
> +
> +err_unlock:
> +	spin_unlock_bh(&srng->lock);
> +
> +	spin_unlock_bh(&ab->ce.ce_lock);
> +
> +	return ret;
> +}
> +

These opinions are not very important. Just for reference.

Ping-Ke



From pkshih at realtek.com  Mon Sep 12 23:18:01 2022
From: pkshih at realtek.com (Ping-Ke Shih)
Date: Tue, 13 Sep 2022 06:18:01 +0000
Subject: [PATCH 05/50] wifi: ath12k: add core.c
In-Reply-To: <20220812161003.27279-6-kvalo@kernel.org>
References: <20220812161003.27279-1-kvalo@kernel.org>
 <20220812161003.27279-6-kvalo@kernel.org>
Message-ID: <6cce0974d5bb40c2a2a40b4abeb41e74@realtek.com>


> -----Original Message-----
> From: Kalle Valo <kvalo at kernel.org>
> Sent: Saturday, August 13, 2022 12:09 AM
> To: linux-wireless at vger.kernel.org
> Cc: ath12k at lists.infradead.org
> Subject: [PATCH 05/50] wifi: ath12k: add core.c
> 
> From: Kalle Valo <quic_kvalo at quicinc.com>
> 
> (Patches split into one patch per file for easier review, but the final
> commit will be one big patch. See the cover letter for more info.)
> 
> Signed-off-by: Kalle Valo <quic_kvalo at quicinc.com>
> ---
>  drivers/net/wireless/ath/ath12k/core.c | 937 +++++++++++++++++++++++++++++++++
>  1 file changed, 937 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
> new file mode 100644
> index 000000000000..476c5ba55fb2
> --- /dev/null
> +++ b/drivers/net/wireless/ath/ath12k/core.c
> @@ -0,0 +1,937 @@
> +// SPDX-License-Identifier: BSD-3-Clause-Clear
> +/*
> + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
> + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
> + */

[...]

> +
> +static int ath12k_core_start(struct ath12k_base *ab,
> +			     enum ath12k_firmware_mode mode)
> +{
> +	int ret;
> +
> +	ret = ath12k_wmi_attach(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to attach wmi: %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = ath12k_htc_init(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to init htc: %d\n", ret);
> +		goto err_wmi_detach;
> +	}
> +
> +	ret = ath12k_hif_start(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to start HIF: %d\n", ret);
> +		goto err_wmi_detach;
> +	}
> +
> +	ret = ath12k_htc_wait_target(&ab->htc);
> +	if (ret) {
> +		ath12k_err(ab, "failed to connect to HTC: %d\n", ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ret = ath12k_dp_htt_connect(&ab->dp);
> +	if (ret) {
> +		ath12k_err(ab, "failed to connect to HTT: %d\n", ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ret = ath12k_wmi_connect(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to connect wmi: %d\n", ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ret = ath12k_htc_start(&ab->htc);
> +	if (ret) {
> +		ath12k_err(ab, "failed to start HTC: %d\n", ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ret = ath12k_wmi_wait_for_service_ready(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to receive wmi service ready event: %d\n",
> +			   ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ret = ath12k_mac_allocate(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n",
> +			   ret);
> +		goto err_hif_stop;
> +	}
> +
> +	ath12k_dp_cc_config(ab);
> +
> +	ath12k_dp_pdev_pre_alloc(ab);
> +
> +	ret = ath12k_dp_rx_pdev_reo_setup(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
> +		goto err_mac_destroy;
> +	}
> +
> +	ret = ath12k_wmi_cmd_init(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to send wmi init cmd: %d\n", ret);
> +		goto err_reo_cleanup;
> +	}
> +
> +	ret = ath12k_wmi_wait_for_unified_ready(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to receive wmi unified ready event: %d\n",
> +			   ret);
> +		goto err_reo_cleanup;
> +	}
> +
> +	/* put hardware to DBS mode */
> +	if (ab->hw_params->single_pdev_only) {
> +		ret = ath12k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
> +		if (ret) {
> +			ath12k_err(ab, "failed to send dbs mode: %d\n", ret);
> +			goto err_hif_stop;

Should it goto err_reo_cleanup?

> +		}
> +	}
> +
> +	ret = ath12k_dp_tx_htt_h2t_ver_req_msg(ab);
> +	if (ret) {
> +		ath12k_err(ab, "failed to send htt version request message: %d\n",
> +			   ret);
> +		goto err_reo_cleanup;
> +	}
> +
> +	return 0;
> +
> +err_reo_cleanup:
> +	ath12k_dp_rx_pdev_reo_cleanup(ab);
> +err_mac_destroy:
> +	ath12k_mac_destroy(ab);
> +err_hif_stop:
> +	ath12k_hif_stop(ab);
> +err_wmi_detach:
> +	ath12k_wmi_detach(ab);
> +	return ret;
> +}
> +

[...]

> +
> +MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11be wireless LAN cards.");
> +MODULE_LICENSE("Dual BSD/GPL");

// SPDX-License-Identifier: BSD-3-Clause-Clear

Out of curiosity, SPDX license and MODULE_LICENSE() are different. 
Could I know the rules?

Ping-Ke



