static int msm_bus_node_debug(struct device *bus_dev, void *data)
{
	int j;
	int ret = 0;
	struct msm_bus_node_device_type *bus_node = NULL;

	bus_node = bus_dev->platform_data;
	if (!bus_node) {
		MSM_BUS_ERR("%s: Can't get device info", __func__);
		ret = -ENODEV;
		goto exit_node_debug;
	}

	MSM_BUS_DBG("Device = %d buswidth %u", bus_node->node_info->id,
				bus_node->node_info->buswidth);
	for (j = 0; j < bus_node->node_info->num_connections; j++) {
		struct msm_bus_node_device_type *bdev =
			(struct msm_bus_node_device_type *)
			bus_node->node_info->dev_connections[j]->platform_data;
		MSM_BUS_DBG("\n\t Connection[%d] %d", j, bdev->node_info->id);
	}

exit_node_debug:
	return ret;
}
Esempio n. 2
0
bool msm_bus_rpm_is_mem_interleaved(void)
{
	int status = 0;
	struct msm_rpm_iv_pair il[2];
	uint16_t id[2];

	il[0].value = 0;
	il[1].value = 0;
	status = msm_bus_board_rpm_get_il_ids(id);
	if (status) {
		MSM_BUS_DBG("Dynamic check not supported, "
			"default: Interleaved memory\n");
		goto inter;
	}

	il[0].id = id[0];
	il[1].id = id[1];
	status = msm_rpm_get_status(il, ARRAY_SIZE(il));
	if (status) {
		MSM_BUS_ERR("Status read for interleaving returned: %d\n"
			"Using interleaved memory by default\n",
			status);
		goto inter;
	}

	if ((il[0].value & 0xFFFF0000) != (il[1].value & 0xFFFF0000)) {
		MSM_BUS_DBG("Non-interleaved memory\n");
		return false;
	}

inter:
	MSM_BUS_DBG("Interleaved memory\n");
	return true;
}
int msm_bus_update_clks(struct msm_bus_node_device_type *nodedev,
		int ctx, int **dirty_nodes, int *num_dirty)
{
	int status = 0;
	struct nodeclk *nodeclk;
	struct nodeclk *busclk;
	struct msm_bus_node_device_type *bus_info = NULL;
	uint64_t req_clk;

	bus_info = nodedev->node_info->bus_device->platform_data;

	if (!bus_info) {
		MSM_BUS_ERR("%s: Unable to find bus device for device %d",
			__func__, nodedev->node_info->id);
		status = -ENODEV;
		goto exit_set_clks;
	}

	req_clk = nodedev->cur_clk_hz[ctx];
	busclk = &bus_info->clk[ctx];

	if (busclk->rate != req_clk) {
		busclk->rate = req_clk;
		busclk->dirty = 1;
		MSM_BUS_DBG("%s: Modifying bus clk %d Rate %llu", __func__,
					bus_info->node_info->id, req_clk);
		status = add_dirty_node(dirty_nodes, bus_info->node_info->id,
								num_dirty);

		if (status) {
			MSM_BUS_ERR("%s: Failed to add dirty node %d", __func__,
						bus_info->node_info->id);
			goto exit_set_clks;
		}
	}

	req_clk = nodedev->cur_clk_hz[ctx];
	nodeclk = &nodedev->clk[ctx];

	if (IS_ERR_OR_NULL(nodeclk))
		goto exit_set_clks;

	if (!nodeclk->dirty || (nodeclk->dirty && (nodeclk->rate < req_clk))) {
		nodeclk->rate = req_clk;
		nodeclk->dirty = 1;
		MSM_BUS_DBG("%s: Modifying node clk %d Rate %llu", __func__,
					nodedev->node_info->id, req_clk);
		status = add_dirty_node(dirty_nodes, nodedev->node_info->id,
								num_dirty);
		if (status) {
			MSM_BUS_ERR("%s: Failed to add dirty node %d", __func__,
						nodedev->node_info->id);
			goto exit_set_clks;
		}
	}

exit_set_clks:
	return status;
}
Esempio n. 4
0
static void msm_bus_bimc_config_limiter(
	struct msm_bus_fabric_registration *fab_pdata,
	struct msm_bus_inode_info *info)
{
	struct msm_bus_bimc_info *binfo;
	int mode, i, ports;

	binfo = (struct msm_bus_bimc_info *)fab_pdata->hw_data;
	ports = info->node_info->num_mports;

	if (!info->node_info->qport) {
		MSM_BUS_DBG("No QoS Ports to init\n");
		return;
	}

	if (info->cur_lim_bw)
		mode = BIMC_QOS_MODE_LIMITER;
	else
		mode = info->node_info->mode;

	switch (mode) {
	case BIMC_QOS_MODE_BYPASS:
	case BIMC_QOS_MODE_FIXED:
		for (i = 0; i < ports; i++)
			bke_switch(binfo->base, info->node_info->qport[i],
				BKE_OFF, mode);
		break;
	case BIMC_QOS_MODE_REGULATOR:
	case BIMC_QOS_MODE_LIMITER:
		if (info->cur_lim_bw != info->cur_prg_bw) {
			MSM_BUS_DBG("Enabled BKE throttling node %d to %llu\n",
				info->node_info->id, info->cur_lim_bw);
			trace_bus_bimc_config_limiter(info->node_info->id,
				info->cur_lim_bw);
			for (i = 0; i < ports; i++) {
				/* If not in fixed mode, update bandwidth */
				struct msm_bus_bimc_qos_bw qbw;

				qbw.ws = info->node_info->ws;
				qbw.bw = info->cur_lim_bw;
				qbw.gp = info->node_info->bimc_gp;
				qbw.thmp = info->node_info->bimc_thmp;
				bimc_set_static_qos_bw(binfo->base,
					binfo->qos_freq,
					info->node_info->qport[i], &qbw);
				bke_switch(binfo->base,
					info->node_info->qport[i],
					BKE_ON, mode);
				info->cur_prg_bw = qbw.bw;
			}
		}
		break;
	default:
		break;
	}
}
int reset_pnodes(int curr, int pnode)
{
	struct msm_bus_inode_info *info;
	struct msm_bus_fabric_device *fabdev;
	int index, next_pnode;
	fabdev = msm_bus_get_fabric_device(GET_FABID(curr));
	if (!fabdev) {
		MSM_BUS_ERR("Fabric not found for: %d\n",
			(GET_FABID(curr)));
			return -ENXIO;
	}

	index = GET_INDEX(pnode);
	info = fabdev->algo->find_node(fabdev, curr);
	if (!info) {
		MSM_BUS_ERR("Cannot find node info!\n");
		return -ENXIO;
	}

	MSM_BUS_DBG("Starting the loop--remove\n");
	do {
		struct msm_bus_inode_info *hop;
		fabdev = msm_bus_get_fabric_device(GET_FABID(curr));
		if (!fabdev) {
			MSM_BUS_ERR("Fabric not found\n");
				return -ENXIO;
		}

		next_pnode = info->pnode[index].next;
		info->pnode[index].next = -2;
		curr = GET_NODE(next_pnode);
		index = GET_INDEX(next_pnode);
		if (IS_NODE(curr))
			hop = fabdev->algo->find_node(fabdev, curr);
		else
			hop = fabdev->algo->find_gw_node(fabdev, curr);
		if (!hop) {
			MSM_BUS_ERR("Null Info found for hop\n");
			return -ENXIO;
		}

		MSM_BUS_DBG("%d[%d] = %d\n", info->node_info->priv_id, index,
			info->pnode[index].next);
		MSM_BUS_DBG("num_pnodes: %d: %d\n", info->node_info->priv_id,
			info->num_pnodes);
		info = hop;
	} while (GET_NODE(info->pnode[index].next) != info->node_info->priv_id);

	info->pnode[index].next = -2;
	MSM_BUS_DBG("%d[%d] = %d\n", info->node_info->priv_id, index,
		info->pnode[index].next);
	MSM_BUS_DBG("num_pnodes: %d: %d\n", info->node_info->priv_id,
		info->num_pnodes);
	return 0;
}
Esempio n. 6
0
static int msm_bus_rpm_commit_arb(struct msm_bus_fabric_registration
	*fab_pdata, int ctx, void *rpm_data,
	struct commit_data *cd, bool valid)
{
	int i, status = 0, rsc_type, key;

	MSM_BUS_DBG("Context: %d\n", ctx);
	rsc_type = RPM_BUS_MASTER_REQ;
	key = RPM_MASTER_FIELD_BW;
	for (i = 0; i < fab_pdata->nmasters; i++) {
		if (cd->mas_arb[i].dirty) {
			MSM_BUS_DBG("MAS HWID: %d, BW: %llu DIRTY: %d\n",
				cd->mas_arb[i].hw_id,
				cd->mas_arb[i].bw,
				cd->mas_arb[i].dirty);
			status = msm_bus_rpm_req(ctx, rsc_type, key,
				&cd->mas_arb[i], valid);
			if (status) {
				MSM_BUS_ERR("RPM: Req fail: mas:%d, bw:%llu\n",
					cd->mas_arb[i].hw_id,
					cd->mas_arb[i].bw);
				break;
			} else {
				cd->mas_arb[i].dirty = false;
			}
		}
	}

	rsc_type = RPM_BUS_SLAVE_REQ;
	key = RPM_SLAVE_FIELD_BW;
	for (i = 0; i < fab_pdata->nslaves; i++) {
		if (cd->slv_arb[i].dirty) {
			MSM_BUS_DBG("SLV HWID: %d, BW: %llu DIRTY: %d\n",
				cd->slv_arb[i].hw_id,
				cd->slv_arb[i].bw,
				cd->slv_arb[i].dirty);
			status = msm_bus_rpm_req(ctx, rsc_type, key,
				&cd->slv_arb[i], valid);
			if (status) {
				MSM_BUS_ERR("RPM: Req fail: slv:%d, bw:%llu\n",
					cd->slv_arb[i].hw_id,
					cd->slv_arb[i].bw);
				break;
			} else {
				cd->slv_arb[i].dirty = false;
			}
		}
	}

	return status;
}
static u64 *get_th_params(struct platform_device *pdev,
		const struct device_node *node, const char *prop,
		int *nports)
{
	int size = 0, ret;
	u64 *ret_arr = NULL;
	int *arr = NULL;
	int i;

	if (of_get_property(node, prop, &size)) {
		*nports = size / sizeof(int);
	} else {
		pr_debug("Property %s not available\n", prop);
		*nports = 0;
		return NULL;
	}

	ret_arr = devm_kzalloc(&pdev->dev, (*nports * sizeof(u64)),
							GFP_KERNEL);
	arr = kzalloc(size, GFP_KERNEL);
	if ((size > 0) && (ZERO_OR_NULL_PTR(arr)
			|| ZERO_OR_NULL_PTR(ret_arr))) {
		if (arr)
			kfree(arr);
		else if (ret_arr)
			devm_kfree(&pdev->dev, ret_arr);
		pr_err("Error: Failed to alloc mem for %s\n", prop);
		return NULL;
	}

	ret = of_property_read_u32_array(node, prop, (u32 *)arr, *nports);
	if (ret) {
		pr_err("Error in reading property: %s\n", prop);
		goto err;
	}

	for (i = 0; i < *nports; i++)
		ret_arr[i] = (uint64_t)KBTOB(arr[i]);

	MSM_BUS_DBG("%s: num entries %d prop %s", __func__, *nports, prop);

	for (i = 0; i < *nports; i++)
		MSM_BUS_DBG("Th %d val %llu", i, ret_arr[i]);

	kfree(arr);
	return ret_arr;
err:
	kfree(arr);
	devm_kfree(&pdev->dev, ret_arr);
	return NULL;
}
Esempio n. 8
0
static void bimc_set_static_qos_bw(void __iomem *base, unsigned int qos_freq,
	int mport, struct msm_bus_bimc_qos_bw *qbw)
{
	int32_t bw_mbps, thh = 0, thm, thl, gc;
	int32_t gp;
	u64 temp;

	if (qos_freq == 0) {
		MSM_BUS_DBG("No QoS Frequency.\n");
		return;
	}

	if (!(qbw->bw && qbw->gp)) {
		MSM_BUS_DBG("No QoS Bandwidth or Window size\n");
		return;
	}

	/* Convert bandwidth to MBPS */
	temp = qbw->bw;
	bimc_div(&temp, 1000000);
	bw_mbps = temp;

	/* Grant period in clock cycles
	 * Grant period from bandwidth structure
	 * is in nano seconds, QoS freq is in KHz.
	 * Divide by 1000 to get clock cycles.
	 */
	gp = (qos_freq * qbw->gp) / (1000 * NSEC_PER_USEC);

	/* Grant count = BW in MBps * Grant period
	 * in micro seconds
	 */
	gc = bw_mbps * (qbw->gp / NSEC_PER_USEC);
	gc = min(gc, MAX_GC);

	/* Medium threshold = -((Medium Threshold percentage *
	 * Grant count) / 100)
	 */
	thm = -((qbw->thmp * gc) / 100);
	qbw->thm = thm;

	/* Low threshold = -(Grant count) */
	thl = -gc;
	qbw->thl = thl;

	MSM_BUS_DBG("%s: BKE parameters: gp %d, gc %d, thm %d thl %d thh %d",
			__func__, gp, gc, thm, thl, thh);

	trace_bus_bke_params(gc, gp, thl, thm, thl);
	set_qos_bw_regs(base, mport, thh, thm, thl, gp, gc);
}
Esempio n. 9
0
static uint64_t get_vfe_bw(void)
{
	int vfe_id = MSM_BUS_MASTER_VFE;
	int iid = msm_bus_board_get_iid(vfe_id);
	int fabid;
	struct msm_bus_fabric_device *fabdev;
	struct msm_bus_inode_info *info;
	uint64_t vfe_bw = 0;

	fabid = GET_FABID(iid);
	fabdev = msm_bus_get_fabric_device(fabid);
	if (!fabdev) {
		MSM_BUS_ERR("Fabric not found for: %d\n", fabid);
		goto exit_get_vfe_bw;
	}
	info = fabdev->algo->find_node(fabdev, iid);
	if (!info) {
		MSM_BUS_ERR("%s: Can't find node %d", __func__,
						vfe_id);
		goto exit_get_vfe_bw;
	}

	vfe_bw = get_node_sumab(info);
	MSM_BUS_DBG("vfe_ab %llu", vfe_bw);

exit_get_vfe_bw:
	return vfe_bw;
}
static int msm_bus_dev_init_qos(struct device *dev, void *data)
{
	int ret = 0;
	struct msm_bus_node_device_type *node_dev = NULL;

	node_dev = dev->platform_data;

	if (!node_dev) {
		MSM_BUS_ERR("%s: Unable to get node device info" , __func__);
		ret = -ENXIO;
		goto exit_init_qos;
	}

	MSM_BUS_DBG("Device = %d", node_dev->node_info->id);

	if (node_dev->ap_owned) {
		struct msm_bus_node_device_type *bus_node_info;

		bus_node_info = node_dev->node_info->bus_device->platform_data;

		if (!bus_node_info) {
			MSM_BUS_ERR("%s: Unable to get bus device infofor %d",
				__func__,
				node_dev->node_info->id);
			ret = -ENXIO;
			goto exit_init_qos;
		}

		if (bus_node_info->fabdev &&
			bus_node_info->fabdev->noc_ops.qos_init) {
			int ret = 0;

			if (node_dev->ap_owned &&
				(node_dev->node_info->qos_params.mode) != -1) {

				if (bus_node_info->fabdev->bypass_qos_prg)
					goto exit_init_qos;

				ret = msm_bus_qos_enable_clk(node_dev);
				if (ret < 0) {
					MSM_BUS_ERR("Can't Enable QoS clk %d",
					node_dev->node_info->id);
					goto exit_init_qos;
				}

				bus_node_info->fabdev->noc_ops.qos_init(
					node_dev,
					bus_node_info->fabdev->qos_base,
					bus_node_info->fabdev->base_offset,
					bus_node_info->fabdev->qos_off,
					bus_node_info->fabdev->qos_freq);
				msm_bus_qos_disable_clk(node_dev, ret);
			}
		} else
			MSM_BUS_ERR("%s: Skipping QOS init for %d",
				__func__, node_dev->node_info->id);
	}
exit_init_qos:
	return ret;
}
static int flush_clk_data(struct device *node_device, int ctx)
{
	struct msm_bus_node_device_type *node;
	struct nodeclk *nodeclk = NULL;
	int ret = 0;

	node = node_device->platform_data;
	if (!node) {
		MSM_BUS_ERR("%s: Unable to find bus device for device %d",
			__func__, node->node_info->id);
		ret = -ENODEV;
		goto exit_flush_clk_data;
	}

	nodeclk = &node->clk[ctx];
	if (node->node_info->is_fab_dev) {
		if (nodeclk->rate != node->cur_clk_hz[ctx]) {
			nodeclk->rate = node->cur_clk_hz[ctx];
			nodeclk->dirty = true;
		}
	}

	if (nodeclk && nodeclk->clk && nodeclk->dirty) {
		long rounded_rate;

		if (nodeclk->rate) {
			rounded_rate = clk_round_rate(nodeclk->clk,
							nodeclk->rate);
			ret = setrate_nodeclk(nodeclk, rounded_rate);

			if (ret) {
				MSM_BUS_ERR("%s: Failed to set_rate %lu for %d",
					__func__, rounded_rate,
						node->node_info->id);
				ret = -ENODEV;
				goto exit_flush_clk_data;
			}

			ret = enable_nodeclk(nodeclk);
		} else
			ret = disable_nodeclk(nodeclk);

		if (ret) {
			MSM_BUS_ERR("%s: Failed to enable for %d", __func__,
						node->node_info->id);
			ret = -ENODEV;
			goto exit_flush_clk_data;
		}
		MSM_BUS_DBG("%s: Updated %d clk to %llu", __func__,
				node->node_info->id, nodeclk->rate);

	}
exit_flush_clk_data:
	/* Reset the aggregated clock rate for fab devices*/
	if (node->node_info->is_fab_dev)
		node->cur_clk_hz[ctx] = 0;

	nodeclk->dirty = 0;
	return ret;
}
Esempio n. 12
0
static int msm_bus_bimc_commit(struct msm_bus_fabric_registration
	*fab_pdata, void *hw_data, void **cdata)
{
	MSM_BUS_DBG("\nReached BIMC Commit\n");
	msm_bus_remote_hw_commit(fab_pdata, hw_data, cdata);
	return 0;
}
Esempio n. 13
0
static uint32_t noc_sat_field(uint64_t bw, uint32_t ws, uint32_t qos_freq)
{
	uint32_t sat_field = 0, win;

	if (bw) {
		/* Limit to max bw and scale bw to 100 KB increments */
		uint64_t tbw, tscale;
		uint64_t bw_scaled = min_t(uint64_t, bw, MAX_BW(qos_freq));
		uint32_t rem = noc_div(&bw_scaled, 100000);

		/**
		 * Calculate saturation from windows size.
		 * WS must be at least one arb period.
		 * Saturation must not exceed max field size
		 *
		 * Bandwidth is in 100KB increments
		 * Window size is in ns
		 * qos_freq is in KHz
		 */
		win = max(ws, 1000000 / qos_freq);
		tbw = bw_scaled * win * qos_freq;
		tscale = 10000000ULL * BW_SCALE * SAT_SCALE;
		rem = noc_div(&tbw, tscale);
		sat_field = (uint32_t)min_t(uint64_t, tbw, MAX_SAT_FIELD);
	}

	MSM_BUS_DBG("NOC: sat_field: %d\n", sat_field);
	return sat_field;
}
Esempio n. 14
0
static void init_health_regs(struct msm_bus_bimc_info *binfo,
				struct msm_bus_inode_info *info,
				struct msm_bus_bimc_qos_mode *qmode,
				int mode)
{
	int i;

	if (mode == BIMC_QOS_MODE_LIMITER) {
		qmode->rl.qhealth[0].limit_commands = 1;
		qmode->rl.qhealth[1].limit_commands = 0;
		qmode->rl.qhealth[2].limit_commands = 0;
		qmode->rl.qhealth[3].limit_commands = 0;

		if (!info->node_info->qport) {
			MSM_BUS_DBG("No QoS Ports to init\n");
			return;
		}

		for (i = 0; i < info->node_info->num_mports; i++) {
			/* If not in bypass mode, update priority */
			if (mode != BIMC_QOS_MODE_BYPASS)
				msm_bus_bimc_set_qos_prio(binfo->base,
				info->node_info->qport[i], mode, qmode);
		}
	}
}
/**
 * msm_bus_scale_unregister_client() - Unregister the client from the bus driver
 * @cl: Handle to the client
 */
void msm_bus_scale_unregister_client(uint32_t cl)
{
	int i;
	struct msm_bus_client *client = (struct msm_bus_client *)(cl);
	bool warn = false;
	if (IS_ERR_OR_NULL(client))
		return;

	for (i = 0; i < client->pdata->usecase->num_paths; i++) {
		if ((client->pdata->usecase[0].vectors[i].ab) ||
			(client->pdata->usecase[0].vectors[i].ib)) {
			warn = true;
			break;
		}
	}

	if (warn) {
		int num_paths = client->pdata->usecase->num_paths;
		int ab[num_paths], ib[num_paths];
		WARN(1, "%s called unregister with non-zero vectors\n",
			client->pdata->name);

		/*
		 * Save client values and zero them out to
		 * cleanly unregister
		 */
		for (i = 0; i < num_paths; i++) {
			ab[i] = client->pdata->usecase[0].vectors[i].ab;
			ib[i] = client->pdata->usecase[0].vectors[i].ib;
			client->pdata->usecase[0].vectors[i].ab = 0;
			client->pdata->usecase[0].vectors[i].ib = 0;
		}

		msm_bus_scale_client_update_request(cl, 0);

		/* Restore client vectors if required for re-registering. */
		for (i = 0; i < num_paths; i++) {
			client->pdata->usecase[0].vectors[i].ab = ab[i];
			client->pdata->usecase[0].vectors[i].ib = ib[i];
		}
	} else if (client->curr != 0)
		msm_bus_scale_client_update_request(cl, 0);

	MSM_BUS_DBG("Unregistering client %d\n", cl);
#ifdef SEC_FEATURE_USE_RT_MUTEX
	rt_mutex_lock(&msm_bus_lock);
#else
	mutex_lock(&msm_bus_lock);
#endif
	msm_bus_scale_client_reset_pnodes(cl);
	msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_UNREGISTER, cl);
#ifdef SEC_FEATURE_USE_RT_MUTEX
	rt_mutex_unlock(&msm_bus_lock);
#else
	mutex_unlock(&msm_bus_lock);
#endif
	kfree(client->src_pnode);
	kfree(client);
}
/**
 * msm_bus_commit_fn() - Commits the data for fabric to rpm
 * @dev: fabric device
 * @data: NULL
 */
static int msm_bus_commit_fn(struct device *dev, void *data)
{
	int ret = 0;
	struct msm_bus_fabric_device *fabdev = to_msm_bus_fabric_device(dev);
	MSM_BUS_DBG("Committing: fabid: %d\n", fabdev->id);
	ret = fabdev->algo->commit(fabdev);
	return ret;
}
/**
 * add_path_node: Adds the path information to the current node
 * @info: Internal node info structure
 * @next: Combination of the id and index of the next node
 * Function returns: Number of pnodes (path_nodes) on success,
 * error on failure.
 *
 * Every node maintains the list of path nodes. A path node is
 * reached by finding the node-id and index stored at the current
 * node. This makes updating the paths with requested bw and clock
 * values efficient, as it avoids lookup for each update-path request.
 */
static int add_path_node(struct msm_bus_inode_info *info, int next)
{
	struct path_node *pnode;
	int i;
	if (ZERO_OR_NULL_PTR(info)) {
		MSM_BUS_ERR("Cannot find node info!: id :%d\n",
				info->node_info->priv_id);
		return -ENXIO;
	}

	for (i = 0; i <= info->num_pnodes; i++) {
		if (info->pnode[i].next == -2) {
			MSM_BUS_DBG("Reusing pnode for info: %d at index: %d\n",
				info->node_info->priv_id, i);
			info->pnode[i].clk[DUAL_CTX] = 0;
			info->pnode[i].clk[ACTIVE_CTX] = 0;
			info->pnode[i].bw[DUAL_CTX] = 0;
			info->pnode[i].bw[ACTIVE_CTX] = 0;
			info->pnode[i].next = next;
			MSM_BUS_DBG("%d[%d] : (%d, %d)\n",
				info->node_info->priv_id, i, GET_NODE(next),
				GET_INDEX(next));
			return i;
		}
	}

	info->num_pnodes++;
	pnode = krealloc(info->pnode,
		((info->num_pnodes + 1) * sizeof(struct path_node))
		, GFP_KERNEL);
	if (ZERO_OR_NULL_PTR(pnode)) {
		MSM_BUS_ERR("Error creating path node!\n");
		info->num_pnodes--;
		return -ENOMEM;
	}
	info->pnode = pnode;
	info->pnode[info->num_pnodes].clk[DUAL_CTX] = 0;
	info->pnode[info->num_pnodes].clk[ACTIVE_CTX] = 0;
	info->pnode[info->num_pnodes].bw[DUAL_CTX] = 0;
	info->pnode[info->num_pnodes].bw[ACTIVE_CTX] = 0;
	info->pnode[info->num_pnodes].next = next;
	MSM_BUS_DBG("%d[%d] : (%d, %d)\n", info->node_info->priv_id,
		info->num_pnodes, GET_NODE(next), GET_INDEX(next));
	return info->num_pnodes;
}
Esempio n. 18
0
static int msm_bus_commit_limiter(struct device *dev, void *data)
{
	int ret = 0;
	struct msm_bus_fabric_device *fabdev = to_msm_bus_fabric_device(dev);

	MSM_BUS_DBG("fabid: %d\n", fabdev->id);
	program_nr_limits(fabdev);
	return ret;
}
static int msm_bus_rpm_req(int ctx, uint32_t rsc_type, uint32_t key,
	struct msm_bus_node_hw_info *hw_info, bool valid)
{
	struct msm_rpm_request *rpm_req;
	int ret = 0, msg_id;

	if (ctx == ACTIVE_CTX)
		ctx = MSM_RPM_CTX_ACTIVE_SET;
	else if (ctx == DUAL_CTX)
		ctx = MSM_RPM_CTX_SLEEP_SET;

	rpm_req = msm_rpm_create_request(ctx, rsc_type, hw_info->hw_id, 1);
	if (rpm_req == NULL) {
		MSM_BUS_WARN("RPM: Couldn't create RPM Request\n");
		return -ENXIO;
	}

	if (valid) {
		ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)
			&hw_info->bw, (int)(sizeof(uint64_t)));
		if (ret) {
			MSM_BUS_WARN("RPM: Add KVP failed for RPM Req:%u\n",
				rsc_type);
			goto free_rpm_request;
		}

		MSM_BUS_DBG("Added Key: %d, Val: %llu, size: %zu\n", key,
			hw_info->bw, sizeof(uint64_t));
	} else {
		/* Invalidate RPM requests */
		ret = msm_rpm_add_kvp_data(rpm_req, 0, NULL, 0);
		if (ret) {
			MSM_BUS_WARN("RPM: Add KVP failed for RPM Req:%u\n",
				rsc_type);
			goto free_rpm_request;
		}
	}

	msg_id = msm_rpm_send_request(rpm_req);
	if (!msg_id) {
		MSM_BUS_WARN("RPM: No message ID for req\n");
		ret = -ENXIO;
		goto free_rpm_request;
	}

	ret = msm_rpm_wait_for_ack(msg_id);
	if (ret) {
		MSM_BUS_WARN("RPM: Ack failed\n");
		goto free_rpm_request;
	}

free_rpm_request:
	msm_rpm_free_request(rpm_req);

	return ret;
}
Esempio n. 20
0
static int msm_bus_bimc_allocate_commit_data(struct msm_bus_fabric_registration
	*fab_pdata, void **cdata, int ctx)
{
	struct msm_bus_bimc_commit **cd = (struct msm_bus_bimc_commit **)cdata;
	struct msm_bus_bimc_info *binfo =
		(struct msm_bus_bimc_info *)fab_pdata->hw_data;

	MSM_BUS_DBG("Allocating BIMC commit data\n");
	*cd = kzalloc(sizeof(struct msm_bus_bimc_commit), GFP_KERNEL);
	if (!*cd) {
		MSM_BUS_DBG("Couldn't alloc mem for cdata\n");
		return -ENOMEM;
	}

	(*cd)->mas = binfo->cdata[ctx].mas;
	(*cd)->slv = binfo->cdata[ctx].slv;

	return 0;
}
Esempio n. 21
0
static uint64_t get_mdp_bw(void)
{
	int ids[] = {MSM_BUS_MASTER_MDP_PORT0, MSM_BUS_MASTER_MDP_PORT1};
	int i;
	uint64_t mdp_ab = 0;
	uint32_t ff = 0;

	for (i = 0; i < ARRAY_SIZE(ids); i++) {
		int iid = msm_bus_board_get_iid(ids[i]);
		int fabid;
		struct msm_bus_fabric_device *fabdev;
		struct msm_bus_inode_info *info;

		fabid = GET_FABID(iid);
		fabdev = msm_bus_get_fabric_device(fabid);
		if (!fabdev) {
			MSM_BUS_ERR("Fabric not found for: %d\n", fabid);
			continue;
		}
		info = fabdev->algo->find_node(fabdev, iid);
		if (!info) {
			MSM_BUS_ERR("%s: Can't find node %d", __func__,
								ids[i]);
			continue;
		}

		mdp_ab += get_node_sumab(info);
		MSM_BUS_DBG("mdp_ab %llu", mdp_ab);
		ff = info->node_info->ff;
	}

	if (ff) {
		mdp_ab = msm_bus_div64(2 * ff, 100 * mdp_ab);
	} else {
		MSM_BUS_ERR("MDP FF is 0");
		mdp_ab = 0;
	}


	MSM_BUS_DBG("MDP BW %llu\n", mdp_ab);
	return mdp_ab;
}
Esempio n. 22
0
/**
 * Calculates bw hardware is using from register values
 * bw returned is in bytes/sec
 */
static uint64_t noc_bw(uint32_t bw_field, uint32_t qos_freq)
{
	uint64_t res;
	uint32_t rem, scale;

	res = 2 * qos_freq * bw_field;
	scale = BW_SCALE * 1000;
	rem = noc_div(&res, scale);
	MSM_BUS_DBG("NOC: Calculated bw: %llu\n", res * 1000000ULL);
	return res * 1000000ULL;
}
Esempio n. 23
0
static uint64_t get_node_sumab(struct msm_bus_inode_info *info)
{
	int i;
	uint64_t maxab = 0;

	for (i = 0; i <= info->num_pnodes; i++)
		maxab += info->pnode[i].bw[DUAL_CTX];

	MSM_BUS_DBG("%s: Node %d numpnodes %d maxib %llu", __func__,
		info->num_pnodes, info->node_info->id, maxab);
	return maxab;
}
Esempio n. 24
0
static void bimc_init_mas_reg(struct msm_bus_bimc_info *binfo,
	struct msm_bus_inode_info *info,
	struct msm_bus_bimc_qos_mode *qmode, int mode)
{
	int i;

	switch (mode) {
	case BIMC_QOS_MODE_FIXED:
		qmode->fixed.prio_level = info->node_info->prio_lvl;
		qmode->fixed.areq_prio_rd = info->node_info->prio_rd;
		qmode->fixed.areq_prio_wr = info->node_info->prio_wr;
		break;
	case BIMC_QOS_MODE_LIMITER:
		qmode->rl.qhealth[0].limit_commands = 1;
		qmode->rl.qhealth[1].limit_commands = 0;
		qmode->rl.qhealth[2].limit_commands = 0;
		qmode->rl.qhealth[3].limit_commands = 0;
		break;
	default:
		break;
	}

	if (!info->node_info->qport) {
		MSM_BUS_DBG("No QoS Ports to init\n");
		return;
	}

	for (i = 0; i < info->node_info->num_mports; i++) {
		/* If not in bypass mode, update priority */
		if (mode != BIMC_QOS_MODE_BYPASS) {
			msm_bus_bimc_set_qos_prio(binfo->base,
				info->node_info->
				qport[i], mode, qmode);

			/* If not in fixed mode, update bandwidth */
			if (mode != BIMC_QOS_MODE_FIXED) {
				struct msm_bus_bimc_qos_bw qbw;
				qbw.ws = info->node_info->ws;
				qbw.bw = info->node_info->bimc_bw[0];
				qbw.gp = info->node_info->bimc_gp;
				qbw.thmp = info->node_info->bimc_thmp;
				bimc_set_static_qos_bw(binfo->base,
					binfo->qos_freq,
					info->node_info->qport[i], &qbw);
			}
		}

		/* set mode */
		msm_bus_bimc_set_qos_mode(binfo->base,
					info->node_info->qport[i],
					mode);
	}
}
Esempio n. 25
0
bool msm_bus_rpm_is_mem_interleaved(void)
{
	int status = 0;
	struct msm_rpm_iv_pair il[2];
	uint16_t id[2];

	il[0].value = 0;
	il[1].value = 0;
	status = msm_bus_board_rpm_get_il_ids(id);
	if (status) {
		MSM_BUS_DBG("Dynamic check not supported, "
			"default: Interleaved memory\n");
		goto inter;
	}

	il[0].id = id[0];
	il[1].id = id[1];
	status = msm_rpm_get_status(il, ARRAY_SIZE(il));
	if (status) {
		MSM_BUS_ERR("Status read for interleaving returned: %d\n"
			"Using interleaved memory by default\n",
			status);
		goto inter;
	}

	/*
	 * If the start address of EBI1-CH0 is the same as
	 * the start address of EBI1-CH1, the memory is interleaved.
	 * The start addresses are stored in the 16 MSBs of the status
	 * register
	 */
	if ((il[0].value & 0xFFFF0000) != (il[1].value & 0xFFFF0000)) {
		MSM_BUS_DBG("Non-interleaved memory\n");
		return false;
	}

inter:
	MSM_BUS_DBG("Interleaved memory\n");
	return true;
}
Esempio n. 26
0
/**
 * Calculates ws hardware is using from register values
 * ws returned is in nanoseconds
 */
static uint32_t noc_ws(uint64_t bw, uint32_t sat, uint32_t qos_freq)
{
	if (bw && qos_freq) {
		uint32_t bwf = bw * qos_freq;
		uint64_t scale = 1000000000000LL * BW_SCALE *
			SAT_SCALE * sat;
		noc_div(&scale, bwf);
		MSM_BUS_DBG("NOC: Calculated ws: %llu\n", scale);
		return scale;
	}

	return 0;
}
Esempio n. 27
0
static int msm_bus_rpm_compare_cdata(
	struct msm_bus_fabric_registration *fab_pdata,
	struct commit_data *cd1, struct commit_data *cd2)
{
	size_t n;
	int ret;

	n = sizeof(struct msm_bus_node_hw_info) * fab_pdata->nmasters * 2;
	ret = memcmp(cd1->mas_arb, cd2->mas_arb, n);
	if (ret) {
		MSM_BUS_DBG("Master Arb Data not equal\n");
		return ret;
	}

	n = sizeof(struct msm_bus_node_hw_info) * fab_pdata->nslaves * 2;
	ret = memcmp(cd1->slv_arb, cd2->slv_arb, n);
	if (ret) {
		MSM_BUS_DBG("Master Arb Data not equal\n");
		return ret;
	}

	return 0;
}
Esempio n. 28
0
static uint64_t get_node_maxib(struct msm_bus_inode_info *info)
{
	int i, ctx;
	uint64_t maxib = 0;

	for (i = 0; i <= info->num_pnodes; i++) {
		for (ctx = 0; ctx < NUM_CTX; ctx++)
			maxib = max(info->pnode[i].clk[ctx], maxib);
	}

	MSM_BUS_DBG("%s: Node %d numpnodes %d maxib %llu", __func__,
		info->num_pnodes, info->node_info->id, maxib);
	return maxib;
}
/**
 * msm_bus_scale_unregister_client() - Unregister the client from the bus driver
 * @cl: Handle to the client
 */
void msm_bus_scale_unregister_client(uint32_t cl)
{
	struct msm_bus_client *client = (struct msm_bus_client *)(cl);
	if (IS_ERR(client) || (!client))
		return;
	if (client->curr != 0)
		msm_bus_scale_client_update_request(cl, 0);
	MSM_BUS_DBG("Unregistering client %d\n", cl);
	mutex_lock(&msm_bus_lock);
	msm_bus_scale_client_reset_pnodes(cl);
	msm_bus_dbg_client_data(client->pdata, MSM_BUS_DBG_UNREGISTER, cl);
	mutex_unlock(&msm_bus_lock);
	kfree(client->src_pnode);
	kfree(client);
}
void msm_bus_scale_client_reset_pnodes(uint32_t cl)
{
	int i, src, pnode, index;
	struct msm_bus_client *client = (struct msm_bus_client *)(cl);
	if (IS_ERR(client)) {
		MSM_BUS_ERR("msm_bus_scale_reset_pnodes error\n");
		return;
	}
	index = 0;
	for (i = 0; i < client->pdata->usecase->num_paths; i++) {
		src = msm_bus_board_get_iid(
			client->pdata->usecase[index].vectors[i].src);
		pnode = client->src_pnode[i];
		MSM_BUS_DBG("(%d, %d)\n", GET_NODE(pnode), GET_INDEX(pnode));
		reset_pnodes(src, pnode);
	}
}