Commit d93185a9 authored by Kalle Valo's avatar Kalle Valo
Browse files
ath.git patches for v5.19. Major changes:

ath11k

* enable keepalive during WoWLAN suspend

* implement remain-on-channel support
parents e99a2d6b 25c321e8
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -1233,6 +1233,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
{
	const struct firmware *fw;
	char boardname[100];

	if (bd_ie_type == ATH10K_BD_IE_BOARD) {
		if (!ar->hw_params.fw.board) {
@@ -1240,9 +1241,19 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)
			return -EINVAL;
		}

		scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",
			  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));

		ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
								ar->hw_params.fw.dir,
								boardname);
		if (IS_ERR(ar->normal_mode_fw.board)) {
			fw = ath10k_fetch_fw_file(ar,
						  ar->hw_params.fw.dir,
						  ar->hw_params.fw.board);
			ar->normal_mode_fw.board = fw;
		}

		if (IS_ERR(ar->normal_mode_fw.board))
			return PTR_ERR(ar->normal_mode_fw.board);

+9 −4
Original line number Diff line number Diff line
@@ -2692,8 +2692,10 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
						    struct ieee80211_sta *sta)
{
	struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;

	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
		switch (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
		switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
			return MODE_11AC_VHT160;
		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
@@ -6926,6 +6928,9 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
					 struct ieee80211_sta *sta,
					 u32 rate_ctrl_flag, u8 nss)
{
	struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;

	if (nss > sta->deflink.rx_nss) {
		ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
			    nss, sta->deflink.rx_nss);
@@ -6933,19 +6938,19 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
	}

	if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
		if (!sta->deflink.vht_cap.vht_supported) {
		if (!vht_cap->vht_supported) {
			ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
				    sta->addr);
			return -EINVAL;
		}
	} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
		if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) {
		if (!ht_cap->ht_supported || vht_cap->vht_supported) {
			ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
				    sta->addr);
			return -EINVAL;
		}
	} else {
		if (sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported)
		if (ht_cap->ht_supported || vht_cap->vht_supported)
			return -EINVAL;
	}

+177 −1
Original line number Diff line number Diff line
@@ -9,6 +9,8 @@
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
#include <linux/of_address.h>
#include <linux/iommu.h>
#include "ahb.h"
#include "debug.h"
#include "hif.h"
@@ -757,6 +759,172 @@ static int ath11k_ahb_setup_resources(struct ath11k_base *ab)
	return 0;
}

static int ath11k_ahb_setup_msa_resources(struct ath11k_base *ab)
{
	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
	struct device *dev = ab->dev;
	struct device_node *node;
	struct resource r;
	int ret;

	node = of_parse_phandle(dev->of_node, "memory-region", 0);
	if (!node)
		return -ENOENT;

	ret = of_address_to_resource(node, 0, &r);
	of_node_put(node);
	if (ret) {
		dev_err(dev, "failed to resolve msa fixed region\n");
		return ret;
	}

	ab_ahb->fw.msa_paddr = r.start;
	ab_ahb->fw.msa_size = resource_size(&r);

	node = of_parse_phandle(dev->of_node, "memory-region", 1);
	if (!node)
		return -ENOENT;

	ret = of_address_to_resource(node, 0, &r);
	of_node_put(node);
	if (ret) {
		dev_err(dev, "failed to resolve ce fixed region\n");
		return ret;
	}

	ab_ahb->fw.ce_paddr = r.start;
	ab_ahb->fw.ce_size = resource_size(&r);

	return 0;
}

static int ath11k_ahb_fw_resources_init(struct ath11k_base *ab)
{
	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
	struct device *host_dev = ab->dev;
	struct platform_device_info info = {0};
	struct iommu_domain *iommu_dom;
	struct platform_device *pdev;
	struct device_node *node;
	int ret;

	/* Chipsets not requiring MSA need not initialize
	 * MSA resources, return success in such cases.
	 */
	if (!ab->hw_params.fixed_fw_mem)
		return 0;

	ret = ath11k_ahb_setup_msa_resources(ab);
	if (ret) {
		ath11k_err(ab, "failed to setup msa resources\n");
		return ret;
	}

	node = of_get_child_by_name(host_dev->of_node, "wifi-firmware");
	if (!node) {
		ab_ahb->fw.use_tz = true;
		return 0;
	}

	info.fwnode = &node->fwnode;
	info.parent = host_dev;
	info.name = node->name;
	info.dma_mask = DMA_BIT_MASK(32);

	pdev = platform_device_register_full(&info);
	if (IS_ERR(pdev)) {
		of_node_put(node);
		return PTR_ERR(pdev);
	}

	ret = of_dma_configure(&pdev->dev, node, true);
	if (ret) {
		ath11k_err(ab, "dma configure fail: %d\n", ret);
		goto err_unregister;
	}

	ab_ahb->fw.dev = &pdev->dev;

	iommu_dom = iommu_domain_alloc(&platform_bus_type);
	if (!iommu_dom) {
		ath11k_err(ab, "failed to allocate iommu domain\n");
		ret = -ENOMEM;
		goto err_unregister;
	}

	ret = iommu_attach_device(iommu_dom, ab_ahb->fw.dev);
	if (ret) {
		ath11k_err(ab, "could not attach device: %d\n", ret);
		goto err_iommu_free;
	}

	ret = iommu_map(iommu_dom, ab_ahb->fw.msa_paddr,
			ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size,
			IOMMU_READ | IOMMU_WRITE);
	if (ret) {
		ath11k_err(ab, "failed to map firmware region: %d\n", ret);
		goto err_iommu_detach;
	}

	ret = iommu_map(iommu_dom, ab_ahb->fw.ce_paddr,
			ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size,
			IOMMU_READ | IOMMU_WRITE);
	if (ret) {
		ath11k_err(ab, "failed to map firmware CE region: %d\n", ret);
		goto err_iommu_unmap;
	}

	ab_ahb->fw.use_tz = false;
	ab_ahb->fw.iommu_domain = iommu_dom;
	of_node_put(node);

	return 0;

err_iommu_unmap:
	iommu_unmap(iommu_dom, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);

err_iommu_detach:
	iommu_detach_device(iommu_dom, ab_ahb->fw.dev);

err_iommu_free:
	iommu_domain_free(iommu_dom);

err_unregister:
	platform_device_unregister(pdev);
	of_node_put(node);

	return ret;
}

static int ath11k_ahb_fw_resource_deinit(struct ath11k_base *ab)
{
	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
	struct iommu_domain *iommu;
	size_t unmapped_size;

	if (ab_ahb->fw.use_tz)
		return 0;

	iommu = ab_ahb->fw.iommu_domain;

	unmapped_size = iommu_unmap(iommu, ab_ahb->fw.msa_paddr, ab_ahb->fw.msa_size);
	if (unmapped_size != ab_ahb->fw.msa_size)
		ath11k_err(ab, "failed to unmap firmware: %zu\n",
			   unmapped_size);

	unmapped_size = iommu_unmap(iommu, ab_ahb->fw.ce_paddr, ab_ahb->fw.ce_size);
	if (unmapped_size != ab_ahb->fw.ce_size)
		ath11k_err(ab, "failed to unmap firmware CE memory: %zu\n",
			   unmapped_size);

	iommu_detach_device(iommu, ab_ahb->fw.dev);
	iommu_domain_free(iommu);

	platform_device_unregister(to_platform_device(ab_ahb->fw.dev));

	return 0;
}

static int ath11k_ahb_probe(struct platform_device *pdev)
{
	struct ath11k_base *ab;
@@ -816,10 +984,14 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
	if (ret)
		goto err_core_free;

	ret = ath11k_hal_srng_init(ab);
	ret = ath11k_ahb_fw_resources_init(ab);
	if (ret)
		goto err_core_free;

	ret = ath11k_hal_srng_init(ab);
	if (ret)
		goto err_fw_deinit;

	ret = ath11k_ce_alloc_pipes(ab);
	if (ret) {
		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
@@ -856,6 +1028,9 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
err_hal_srng_deinit:
	ath11k_hal_srng_deinit(ab);

err_fw_deinit:
	ath11k_ahb_fw_resource_deinit(ab);

err_core_free:
	ath11k_core_free(ab);
	platform_set_drvdata(pdev, NULL);
@@ -891,6 +1066,7 @@ static int ath11k_ahb_remove(struct platform_device *pdev)
qmi_fail:
	ath11k_ahb_free_irq(ab);
	ath11k_hal_srng_deinit(ab);
	ath11k_ahb_fw_resource_deinit(ab);
	ath11k_ce_free_pipes(ab);
	ath11k_core_free(ab);
	platform_set_drvdata(pdev, NULL);
+9 −0
Original line number Diff line number Diff line
@@ -12,6 +12,15 @@ struct ath11k_base;

struct ath11k_ahb {
	struct rproc *tgt_rproc;
	struct {
		struct device *dev;
		struct iommu_domain *iommu_domain;
		dma_addr_t msa_paddr;
		u32 msa_size;
		dma_addr_t ce_paddr;
		u32 ce_size;
		bool use_tz;
	} fw;
};

static inline struct ath11k_ahb *ath11k_ahb_priv(struct ath11k_base *ab)
+9 −1
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 0,
		.ce_window_idx = 0,
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
	},
	{
		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -185,6 +186,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 0,
		.ce_window_idx = 0,
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
	},
	{
		.name = "qca6390 hw2.0",
@@ -259,6 +261,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 0,
		.ce_window_idx = 0,
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
	},
	{
		.name = "qcn9074 hw1.0",
@@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 3,
		.ce_window_idx = 2,
		.fixed_fw_mem = false,
		.support_off_channel_tx = false,
	},
	{
		.name = "wcn6855 hw2.0",
@@ -407,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 0,
		.ce_window_idx = 0,
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
	},
	{
		.name = "wcn6855 hw2.1",
@@ -480,6 +485,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 0,
		.ce_window_idx = 0,
		.fixed_fw_mem = false,
		.support_off_channel_tx = true,
	},
	{
		.name = "wcn6750 hw1.0",
@@ -553,6 +559,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.dp_window_idx = 1,
		.ce_window_idx = 2,
		.fixed_fw_mem = true,
		.support_off_channel_tx = false,
	},
};

@@ -1620,9 +1627,11 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)

		ieee80211_stop_queues(ar->hw);
		ath11k_mac_drain_tx(ar);
		ar->state_11d = ATH11K_11D_IDLE;
		complete(&ar->completed_11d_scan);
		complete(&ar->scan.started);
		complete(&ar->scan.completed);
		complete(&ar->scan.on_channel);
		complete(&ar->peer_assoc_done);
		complete(&ar->peer_delete_done);
		complete(&ar->install_key_done);
@@ -1768,7 +1777,6 @@ static void ath11k_core_reset(struct work_struct *work)
						ATH11K_RECOVER_START_TIMEOUT_HZ);

	ath11k_hif_power_down(ab);
	ath11k_qmi_free_resource(ab);
	ath11k_hif_power_up(ab);

	ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
Loading