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

Commit 4a46609f authored by David Dai's avatar David Dai Committed by Gerrit - the friendly Code Review server
Browse files

msm: msm_bus: add regulator voting as part of sbm disconnect



There may be a scenario where a client is holding a non zero bandwidth
vote on a target slave config device, but have removed their vote
on the respective multimedia GDSC and MMCX. This can be problematic
when MMCX is collapsed but the config slave is still connected creating
a window where a faulty transaction to collapsed slave can be difficult
to diagnose. This can be prevented by holding a vote on MMCX as part of
the bandwidth vote to the multimedia config slave.

Change-Id: I7e26ab7e036cc064f1c9092783c99eb1666399ef
Signed-off-by: default avatarDavid Dai <daidavid1@codeaurora.org>
parent d60d4256
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -145,6 +145,8 @@ qcom,sbm-offset: The offset used to determine location of Sideband
			remove bandwidth votes.
qcom,disable-ports:	The ports to disable on the sideband manager when the
			requirement bandwidth affecting	the node reduces to 0.
node-reg-names:		Names of the regulator associated with bus node used
			to grab the phandle of the regulator.

Example:

+47 −4
Original line number Diff line number Diff line
@@ -1010,7 +1010,7 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data)

static int msm_bus_dev_sbm_config(struct device *dev, bool enable)
{
	int ret = 0;
	int ret = 0, idx = 0;
	struct msm_bus_node_device_type *node_dev = NULL;
	struct msm_bus_node_device_type *fab_dev = NULL;

@@ -1024,12 +1024,33 @@ static int msm_bus_dev_sbm_config(struct device *dev, bool enable)
		return 0;

	if ((node_dev->node_bw[DUAL_CTX].sum_ab ||
		node_dev->node_bw[DUAL_CTX].max_ib) && !enable)
		node_dev->node_bw[DUAL_CTX].max_ib ||
		!node_dev->is_connected) && !enable)
		return 0;
	else if ((!node_dev->node_bw[DUAL_CTX].sum_ab &&
		!node_dev->node_bw[DUAL_CTX].max_ib) && enable)
	else if (((!node_dev->node_bw[DUAL_CTX].sum_ab &&
		!node_dev->node_bw[DUAL_CTX].max_ib) ||
		node_dev->is_connected) && enable)
		return 0;

	if (enable) {
		for (idx = 0; idx < node_dev->num_regs; idx++) {
			if (!node_dev->node_regs[idx].reg)
				node_dev->node_regs[idx].reg =
				devm_regulator_get(dev,
				node_dev->node_regs[idx].name);

			if ((IS_ERR_OR_NULL(node_dev->node_regs[idx].reg)))
				return -ENXIO;
			ret = regulator_enable(node_dev->node_regs[idx].reg);
			if (ret) {
				MSM_BUS_ERR("%s: Failed to enable reg:%s\n",
				__func__, node_dev->node_regs[idx].name);
				return ret;
			}
		}
		node_dev->is_connected = true;
	}

	fab_dev = to_msm_bus_node(node_dev->node_info->bus_device);
	if (!fab_dev) {
		MSM_BUS_ERR("%s: Unable to get bus device info for %d",
@@ -1046,6 +1067,25 @@ static int msm_bus_dev_sbm_config(struct device *dev, bool enable)
			fab_dev->fabdev->sbm_offset,
			enable);
	}

	if (!enable) {
		for (idx = 0; idx < node_dev->num_regs; idx++) {
			if (!node_dev->node_regs[idx].reg)
				node_dev->node_regs[idx].reg =
				devm_regulator_get(dev,
					node_dev->node_regs[idx].name);

			if ((IS_ERR_OR_NULL(node_dev->node_regs[idx].reg)))
				return -ENXIO;
			ret = regulator_disable(node_dev->node_regs[idx].reg);
			if (ret) {
				MSM_BUS_ERR("%s: Failed to disable reg:%s\n",
				__func__, node_dev->node_regs[idx].name);
				return ret;
			}
		}
		node_dev->is_connected = false;
	}
	return ret;
}

@@ -1563,6 +1603,9 @@ static struct device *msm_bus_device_init(
					pdata->qos_bcms[i].vec.vec_b;
		}
	}
	bus_node->num_regs = pdata->num_regs;
	if (bus_node->num_regs)
		bus_node->node_regs = pdata->node_regs;

	bus_dev->of_node = pdata->of_node;

+21 −1
Original line number Diff line number Diff line
@@ -522,10 +522,12 @@ static int get_bus_node_device_data(
{
	bool enable_only;
	bool setrate_only;
	int num_elems = 0, num_bcms = 0, i = 0, ret = 0;
	int num_elems = 0, num_bcms = 0, i = 0, ret = 0, num_regs = 0;
	uint32_t *vec_arr = NULL;
	struct qos_bcm_type *qos_bcms = NULL;
	struct device_node *qos_clk_node = NULL;
	const char *reg_name;
	struct property *prop;

	node_device->node_info = get_node_info_data(dev_node, pdev);
	if (IS_ERR_OR_NULL(node_device->node_info)) {
@@ -696,6 +698,24 @@ static int get_bus_node_device_data(
			scnprintf(node_device->clk[DUAL_CTX].reg_name,
				MAX_REG_NAME, "%c", '\0');

		num_regs = of_property_count_strings(dev_node,
							"node-reg-names");
		if (num_regs < 0)
			node_device->num_regs = 0;
		else {
			i = 0;
			node_device->num_regs = num_regs;
			node_device->node_regs = devm_kzalloc(&pdev->dev,
				(num_regs * sizeof(struct node_regulator)),
								GFP_KERNEL);

			of_property_for_each_string(dev_node, "node-reg-names",
							prop, reg_name) {
				scnprintf(node_device->node_regs[i].name,
					MAX_REG_NAME, "%s", reg_name);
				i++;
			}
		}
	}
	return 0;
}
+8 −0
Original line number Diff line number Diff line
@@ -79,6 +79,11 @@ struct nodevector {
	uint64_t query_vec_b;
};

struct node_regulator {
	char name[MAX_REG_NAME];
	struct regulator *reg;
};

struct qos_bcm_type {
	int qos_bcm_id;
	struct nodevector vec;
@@ -215,6 +220,8 @@ struct msm_bus_node_device_type {
	struct nodeclk *node_qos_clks;
	uint32_t num_qos_bcms;
	struct qos_bcm_type *qos_bcms;
	uint32_t num_regs;
	struct node_regulator *node_regs;
	unsigned int ap_owned;
	struct device_node *of_node;
	struct device dev;
@@ -223,6 +230,7 @@ struct msm_bus_node_device_type {
	bool query_dirty;
	struct list_head dev_link;
	struct list_head devlist;
	bool is_connected;
};

static inline struct msm_bus_node_device_type *to_msm_bus_node(struct device *d)