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

Commit c1d17bef authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cnss2: Remove unnecessary logs for Bus BW voting"

parents 4b9bef81 a7a321cc
Loading
Loading
Loading
Loading
+103 −48
Original line number Diff line number Diff line
@@ -2230,75 +2230,130 @@ int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
	return ret;
}

/**
 * cnss_register_bus_scale() - Setup interconnect voting data
 * @plat_priv: Platform data structure
 *
 * For different interconnect path configured in device tree setup voting data
 * for list of bandwidth requirements.
 *
 * Result: 0 for success. -EINVAL if not configured
 */
static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
{
	int ret = 0, len = 0, i, j;
	struct cnss_bus_bw_info *bus_bw_info;
	const u32 *cfg_arr;

	bus_bw_info = &plat_priv->bus_bw_info;

	bus_bw_info->cnss_path =
		of_icc_get(&plat_priv->plat_dev->dev, NULL);

	if (!bus_bw_info->cnss_path) {
		cnss_pr_err("Skip Bus BW setup. Interconnect not configured\n");
		return 0;
	}
	int ret = -EINVAL;
	u32 idx, i, j, cfg_arr_size, *cfg_arr;
	struct cnss_bus_bw_info *bus_bw_info, *tmp;
	struct device *dev = &plat_priv->plat_dev->dev;

	if (IS_ERR(bus_bw_info->cnss_path))  {
		ret = PTR_ERR(bus_bw_info->cnss_path);
		if (ret != -EPROBE_DEFER) {
			cnss_pr_err("Failed to get Interconnect path: %d!\n",
				    ret);
			goto out;
		}
	INIT_LIST_HEAD(&plat_priv->icc.list_head);
	ret = of_property_read_u32(dev->of_node,
				   "qcom,icc-path-count",
				   &plat_priv->icc.path_count);
	if (ret) {
		cnss_pr_err("Platform Bus Interconnect path not configured\n");
		return -EINVAL;
	}
	ret = of_property_read_u32(plat_priv->plat_dev->dev.of_node,
				   "qcom,bus-bw-cfg-num",
				   &bus_bw_info->num_cfg);
				   "qcom,bus-bw-cfg-count",
				   &plat_priv->icc.bus_bw_cfg_count);
	if (ret) {
		cnss_pr_err("Failed to get Bus BW Config table size\n");
		goto cleanup;
	}
	cfg_arr_size = plat_priv->icc.path_count *
			 plat_priv->icc.bus_bw_cfg_count * CNSS_ICC_VOTE_MAX;
	cfg_arr = kzalloc(cfg_arr_size, GFP_KERNEL);
	if (!cfg_arr) {
		cnss_pr_err("Failed to alloc cfg table mem\n");
		ret = -ENOMEM;
		goto cleanup;
	}

	ret = of_property_read_u32_array(plat_priv->plat_dev->dev.of_node,
					 "qcom,bus-bw-cfg", cfg_arr,
					 cfg_arr_size);
	if (ret) {
		cnss_pr_err("Invalid Bus BW Config Table\n");
		goto cleanup;
	}

	cnss_pr_dbg("ICC Path_Count: %d BW_CFG_Count: %d\n",
		    plat_priv->icc.path_count, plat_priv->icc.bus_bw_cfg_count);

	for (idx = 0; idx < plat_priv->icc.path_count; idx++) {
		bus_bw_info = devm_kzalloc(dev, sizeof(*bus_bw_info),
					   GFP_KERNEL);
		if (!bus_bw_info) {
			ret = -ENOMEM;
			goto out;
		}
		ret = of_property_read_string_index(dev->of_node,
						    "interconnect-names", idx,
						    &bus_bw_info->icc_name);
		if (ret)
			goto out;

	cfg_arr = of_get_property(plat_priv->plat_dev->dev.of_node,
				  "qcom,bus-bw-cfg", &len);
	if (!cfg_arr) {
		cnss_pr_err("Bus BW Config Table not setup!\n");
		ret = -EINVAL;
		bus_bw_info->icc_path =
			of_icc_get(&plat_priv->plat_dev->dev,
				   bus_bw_info->icc_name);

		if (IS_ERR(bus_bw_info->icc_path))  {
			ret = PTR_ERR(bus_bw_info->icc_path);
			if (ret != -EPROBE_DEFER) {
				cnss_pr_err("Failed to get Interconnect path for %s. Err: %d\n",
					    bus_bw_info->icc_name, ret);
				goto out;
			}
		}

	bus_bw_info->cfg_table = kcalloc(bus_bw_info->num_cfg,
		bus_bw_info->cfg_table =
			devm_kcalloc(dev, plat_priv->icc.bus_bw_cfg_count,
				     sizeof(*bus_bw_info->cfg_table),
				     GFP_KERNEL);
		if (!bus_bw_info->cfg_table) {
		cnss_pr_err("No mem for Bus BW config table\n");
		return -ENOMEM;
	}
	for (i = 0, j = 0; i < bus_bw_info->num_cfg; i++, j += 2) {
		bus_bw_info->cfg_table[i].ab = be32_to_cpu(cfg_arr[j]);
		bus_bw_info->cfg_table[i].ib = be32_to_cpu(cfg_arr[j + 1]);
		cnss_pr_dbg("Bandwidth Type: %d bw_cfg.ab: %d bw_cfg.ib: %d\n",
			    i, bus_bw_info->cfg_table[i].ab,
			    bus_bw_info->cfg_table[i].ib);
			ret = -ENOMEM;
			goto out;
		}
		cnss_pr_dbg("ICC Vote CFG for path: %s\n",
			    bus_bw_info->icc_name);
		for (i = 0, j = (idx * plat_priv->icc.bus_bw_cfg_count *
		     CNSS_ICC_VOTE_MAX);
		     i < plat_priv->icc.bus_bw_cfg_count;
		     i++, j += 2) {
			bus_bw_info->cfg_table[i].avg_bw = cfg_arr[j];
			bus_bw_info->cfg_table[i].peak_bw = cfg_arr[j + 1];
			cnss_pr_dbg("ICC Vote BW: %d avg: %d peak: %d\n",
				    i, bus_bw_info->cfg_table[i].avg_bw,
				    bus_bw_info->cfg_table[i].peak_bw);
		}
		list_add_tail(&bus_bw_info->list,
			      &plat_priv->icc.list_head);
	}
	kfree(cfg_arr);
	return 0;
out:
	list_for_each_entry_safe(bus_bw_info, tmp,
				 &plat_priv->icc.list_head, list) {
		list_del(&bus_bw_info->list);
	}
cleanup:
	kfree(cfg_arr);
	memset(&plat_priv->icc, 0, sizeof(plat_priv->icc));
	return ret;
}

static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv)
{
	struct cnss_bus_bw_info *bus_bw_info;

	bus_bw_info = &plat_priv->bus_bw_info;
	struct cnss_bus_bw_info *bus_bw_info, *tmp;

	if (bus_bw_info->cnss_path)
		icc_put(bus_bw_info->cnss_path);

	kfree(bus_bw_info->cfg_table);
	list_for_each_entry_safe(bus_bw_info, tmp,
				 &plat_priv->icc.list_head, list) {
		list_del(&bus_bw_info->list);
		if (bus_bw_info->icc_path)
			icc_put(bus_bw_info->icc_path);
	}
	memset(&plat_priv->icc, 0, sizeof(plat_priv->icc));
}

static ssize_t recovery_store(struct device *dev,
+36 −6
Original line number Diff line number Diff line
@@ -140,18 +140,48 @@ struct cnss_esoc_info {
};
#endif

/**
 * struct cnss_bus_bw_cfg - Interconnect vote data
 * @avg_bw: Vote for average bandwidth
 * @peak_bw: Vote for peak bandwidth
 */
struct cnss_bus_bw_cfg {
	u32 ab;
	u32 ib;
	u32 avg_bw;
	u32 peak_bw;
};

/* Number of bw votes (avg, peak) entries that ICC requires */
#define CNSS_ICC_VOTE_MAX 2

/**
 * struct cnss_bus_bw_info - Bus bandwidth config for interconnect path
 * @list: Kernel linked list
 * @icc_name: Name of interconnect path as defined in Device tree
 * @icc_path: Interconnect path data structure
 * @cfg_table: Interconnect vote data for average and peak bandwidth
 */
struct cnss_bus_bw_info {
	struct icc_path *cnss_path;
	int current_bw_vote;
	u32 num_cfg;
	struct list_head list;
	const char *icc_name;
	struct icc_path *icc_path;
	struct cnss_bus_bw_cfg *cfg_table;
};

/**
 * struct cnss_interconnect_cfg - CNSS platform interconnect config
 * @list_head: List of interconnect path bandwidth configs
 * @path_count: Count of interconnect path configured in device tree
 * @current_bw_vote: WLAN driver provided bandwidth vote
 * @bus_bw_cfg_count: Number of bandwidth configs for voting. It is the array
 *                    size of struct cnss_bus_bw_info.cfg_table
 */
struct cnss_interconnect_cfg {
	struct list_head list_head;
	u32 path_count;
	int current_bw_vote;
	u32 bus_bw_cfg_count;
};

struct cnss_fw_mem {
	size_t size;
	void *va;
@@ -360,7 +390,7 @@ struct cnss_plat_data {
#if IS_ENABLED(CONFIG_ESOC)
	struct cnss_esoc_info esoc_info;
#endif
	struct cnss_bus_bw_info bus_bw_info;
	struct cnss_interconnect_cfg icc;
	struct notifier_block modem_nb;
	struct notifier_block reboot_nb;
	struct notifier_block panic_nb;
+45 −37
Original line number Diff line number Diff line
@@ -509,43 +509,59 @@ static int cnss_pci_force_wake_put(struct cnss_pci_data *pci_priv)
	return ret;
}

int cnss_request_bus_bandwidth(struct device *dev, int bandwidth)
/**
 * cnss_setup_bus_bandwidth() - Setup interconnect vote for given bandwidth
 * @plat_priv: Platform private data struct
 * @bw: bandwidth
 * @save: toggle flag to save bandwidth to current_bw_vote
 *
 * Setup bandwidth votes for configured interconnect paths
 *
 * Return: 0 for success
 */
static int cnss_setup_bus_bandwidth(struct cnss_plat_data *plat_priv,
				    u32 bw, bool save)
{
	int ret = 0;
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
	struct cnss_bus_bw_info *bus_bw_info;

	if (!plat_priv)
		return -ENODEV;
	if (!plat_priv->icc.path_count)
		return -ENOTSUPP;

	bus_bw_info = &plat_priv->bus_bw_info;
	if (!bus_bw_info->cnss_path || bandwidth > bus_bw_info->num_cfg)
	if (bw >= plat_priv->icc.bus_bw_cfg_count) {
		cnss_pr_err("Invalid bus bandwidth Type: %d", bw);
		return -EINVAL;
	}

	switch (bandwidth) {
	case CNSS_BUS_WIDTH_NONE:
	case CNSS_BUS_WIDTH_IDLE:
	case CNSS_BUS_WIDTH_LOW:
	case CNSS_BUS_WIDTH_MEDIUM:
	case CNSS_BUS_WIDTH_HIGH:
	case CNSS_BUS_WIDTH_VERY_HIGH:
	case CNSS_BUS_WIDTH_LOW_LATENCY:
		ret = icc_set_bw(bus_bw_info->cnss_path,
				 bus_bw_info->cfg_table[bandwidth].ab,
				 bus_bw_info->cfg_table[bandwidth].ib);
		if (!ret)
			bus_bw_info->current_bw_vote = bandwidth;
		else
			cnss_pr_err("Could not set bus bandwidth: %d, err = %d\n",
				    bandwidth, ret);
	list_for_each_entry(bus_bw_info, &plat_priv->icc.list_head, list) {
		ret = icc_set_bw(bus_bw_info->icc_path,
				 bus_bw_info->cfg_table[bw].avg_bw,
				 bus_bw_info->cfg_table[bw].peak_bw);
		if (ret) {
			cnss_pr_err("Could not set BW Cfg: %d, err = %d ICC Path: %s Val: %d %d\n",
				    bw, ret, bus_bw_info->icc_name,
				    bus_bw_info->cfg_table[bw].avg_bw,
				    bus_bw_info->cfg_table[bw].peak_bw);
			break;
	default:
		cnss_pr_err("Invalid bus bandwidth: %d", bandwidth);
		ret = -EINVAL;
		}

	}
	if (ret == 0 && save)
		plat_priv->icc.current_bw_vote = bw;
	return ret;
}

int cnss_request_bus_bandwidth(struct device *dev, int bandwidth)
{
	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);

	if (!plat_priv)
		return -ENODEV;

	if (bandwidth < 0)
		return -EINVAL;

	return cnss_setup_bus_bandwidth(plat_priv, (u32)bandwidth, true);
}
EXPORT_SYMBOL(cnss_request_bus_bandwidth);

int cnss_pci_debug_reg_read(struct cnss_pci_data *pci_priv, u32 offset,
@@ -2987,7 +3003,6 @@ int cnss_auto_suspend(struct device *dev)
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
	struct cnss_plat_data *plat_priv;
	struct cnss_bus_bw_info *bus_bw_info;

	if (!pci_priv)
		return -ENODEV;
@@ -3008,18 +3023,11 @@ int cnss_auto_suspend(struct device *dev)

	cnss_pci_set_monitor_wake_intr(pci_priv, true);

	bus_bw_info = &plat_priv->bus_bw_info;
	if (!bus_bw_info->cnss_path)
		goto out;

	/* For suspend temporarily set bandwidth vote to NONE and dont save in
	 * current_bw_vote as in resume path we should vote for last used
	 * bandwidth vote. Also ignore error if bw voting is not setup.
	 */
	icc_set_bw(bus_bw_info->cnss_path,
		   bus_bw_info->cfg_table[CNSS_BUS_WIDTH_NONE].ab,
		   bus_bw_info->cfg_table[CNSS_BUS_WIDTH_NONE].ib);
out:
	cnss_setup_bus_bandwidth(plat_priv, CNSS_BUS_WIDTH_NONE, false);
	return 0;
}
EXPORT_SYMBOL(cnss_auto_suspend);
@@ -3048,7 +3056,7 @@ int cnss_auto_resume(struct device *dev)
	cnss_pci_set_auto_suspended(pci_priv, 0);
	mutex_unlock(&pci_priv->bus_lock);

	cnss_request_bus_bandwidth(dev, plat_priv->bus_bw_info.current_bw_vote);
	cnss_request_bus_bandwidth(dev, plat_priv->icc.current_bw_vote);

	return 0;
}