Loading Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt +19 −1 Original line number Diff line number Diff line Loading @@ -218,7 +218,16 @@ using the following properties: master-id, slave-id, arbitrated bandwidth in KBps, instantaneous bandwidth in KBps Example: The following are optional properties for client's device nodes: - qcom,msm-bus,alc-voter: Boolean alc_voter flag to indicate that client will vote as an Active Latency Client. - qcom,msm-bus,vectors-alc: Arrays of unsigned integers representing: first access latency, idle time in ns, this property is required if qcom,msm-bus,alc-voter is present. Example for default client: qcom,msm-bus,name = "client-name"; qcom,msm-bus,num-cases = <3>; Loading @@ -229,3 +238,12 @@ Example: <22 512 320000 3200000>, <26 512 3200000 3200000>, <22 512 160000 1600000>, <26 512 1600000 1600000>; Example for ALC client: qcom,msm-bus,name = "client-name"; qcom,msm-bus,num-cases = <2>; qcom,msm-bus,active-only; qcom,msm-bus,alc-voter; qcom,msm-bus,vectors-alc = <0 0>, <500 1600>; drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c +198 −9 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #define NUM_LNODES 3 #define MAX_STR_CL 50 #define MSM_BUS_MAS_ALC 144 struct bus_search_type { struct list_head link; struct list_head node_list; Loading Loading @@ -123,6 +125,9 @@ static void bcm_add_bus_req(struct device *dev) goto exit_bcm_add_bus_req; } if (cur_dev->node_info->bcm_req_idx != -1) goto exit_bcm_add_bus_req; if (!cur_dev->node_info->num_bcm_devs) goto exit_bcm_add_bus_req; Loading Loading @@ -179,8 +184,6 @@ static void bcm_add_bus_req(struct device *dev) cur_dev->node_info->bcm_req_idx = lnode_idx; memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX); memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX); MSM_BUS_ERR("%s: Added %d entry to bcm %d @ %d\n", __func__, lnode->bus_dev_id, bcm_dev->node_info->id, lnode_idx); } exit_bcm_add_bus_req: Loading Loading @@ -316,7 +319,6 @@ static int prune_path(struct list_head *route_list, int dest, int src, MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest); goto exit_prune_path; } MSM_BUS_ERR("%s: dest dev %d", __func__, dest); lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop, cl_name); bcm_add_bus_req(dest_dev); Loading Loading @@ -520,7 +522,6 @@ static void bcm_update_bus_req(struct device *dev, int ctx) max_ib = max(max_ib, max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX], bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX])); max_ab = max(max_ab, bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] + bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]); Loading @@ -531,9 +532,14 @@ static void bcm_update_bus_req(struct device *dev, int ctx) bcm_dev->lnode_list[i].lnode_ab[ctx]); } } bcm_dev->node_bw[ctx].max_ab = max_ab; bcm_dev->node_bw[ctx].max_ib = max_ib; max_ab = msm_bus_div64(max_ab, bcm_dev->bcmdev->unit_size); max_ib = msm_bus_div64(max_ib, bcm_dev->bcmdev->unit_size); bcm_dev->node_vec[ctx].vec_a = max_ab; bcm_dev->node_vec[ctx].vec_b = max_ib; } exit_bcm_update_bus_req: return; Loading Loading @@ -598,15 +604,51 @@ static void bcm_query_bus_req(struct device *dev, int ctx) } } max_query_ab = msm_bus_div64(max_query_ab, bcm_dev->bcmdev->unit_size); max_query_ib = msm_bus_div64(max_query_ib, bcm_dev->bcmdev->unit_size); bcm_dev->node_bw[ctx].max_query_ab = max_query_ab; bcm_dev->node_bw[ctx].max_query_ib = max_query_ib; } exit_bcm_query_bus_req: return; } static void bcm_update_alc_req(struct msm_bus_node_device_type *dev, int ctx) { struct msm_bus_node_device_type *bcm_dev = NULL; int i; uint64_t max_alc = 0; if (!dev || !to_msm_bus_node(dev->node_info->bus_device)) { MSM_BUS_ERR("Bus node pointer is Invalid"); goto exit_bcm_update_alc_req; } for (i = 0; i < dev->num_lnodes; i++) max_alc = max(max_alc, dev->lnode_list[i].alc_idx[ctx]); dev->node_bw[ctx].max_alc = max_alc; bcm_dev = to_msm_bus_node(dev->node_info->bcm_devs[0]); if (ctx == ACTIVE_CTX) { max_alc = max(max_alc, max(dev->node_bw[ACTIVE_CTX].max_alc, dev->node_bw[DUAL_CTX].max_alc)); } else { max_alc = dev->node_bw[ctx].max_alc; } bcm_dev->node_bw[ctx].max_alc = max_alc; bcm_dev->node_vec[ctx].vec_a = max_alc; bcm_dev->node_vec[ctx].vec_b = 0; exit_bcm_update_alc_req: return; } int bcm_remove_handoff_req(struct device *dev, void *data) { Loading Loading @@ -684,7 +726,6 @@ static void aggregate_bus_query_req(struct msm_bus_node_device_type *bus_dev, sum_ab += bus_dev->lnode_list[i].lnode_query_ab[ctx]; } MSM_BUS_ERR("aggregate: query_ab:%llu\n", sum_ab); bus_dev->node_bw[ctx].sum_query_ab = sum_ab; bus_dev->node_bw[ctx].max_query_ib = max_ib; Loading Loading @@ -870,6 +911,63 @@ static int update_path(struct device *src_dev, int dest, uint64_t act_req_ib, return ret; } static int update_alc_vote(struct device *alc_dev, uint64_t act_req_fa_lat, uint64_t act_req_idle_time, uint64_t slp_req_fa_lat, uint64_t slp_req_idle_time, uint64_t cur_fa_lat, uint64_t cur_idle_time, int idx, int ctx) { struct link_node *lnode = NULL; struct msm_bus_node_device_type *dev_info = NULL; int curr_idx, i; int ret = 0; if (IS_ERR_OR_NULL(alc_dev)) { MSM_BUS_ERR("%s: No source device", __func__); ret = -ENODEV; goto exit_update_alc_vote; } if (idx < 0) { MSM_BUS_ERR("%s: Invalid lnode idx %d", __func__, idx); ret = -ENXIO; goto exit_update_alc_vote; } dev_info = to_msm_bus_node(alc_dev); curr_idx = idx; if (curr_idx >= dev_info->num_lnodes) { MSM_BUS_ERR("%s: Invalid lnode Idx %d num lnodes %d", __func__, curr_idx, dev_info->num_lnodes); ret = -ENXIO; goto exit_update_alc_vote; } lnode = &dev_info->lnode_list[curr_idx]; if (!lnode) { MSM_BUS_ERR("%s: Invalid lnode ptr lnode %d", __func__, curr_idx); ret = -ENXIO; goto exit_update_alc_vote; } /* * Add aggregation and mapping logic once LUT is avail. * Use default values for time being. */ lnode->alc_idx[ACTIVE_CTX] = 12; lnode->alc_idx[DUAL_CTX] = 0; for (i = 0; i < NUM_CTX; i++) bcm_update_alc_req(dev_info, i); add_node_to_clist(dev_info); exit_update_alc_vote: return ret; } static int query_path(struct device *src_dev, int dest, uint64_t act_req_ib, uint64_t act_req_bw, uint64_t slp_req_ib, uint64_t slp_req_bw, uint64_t cur_ib, uint64_t cur_bw, Loading Loading @@ -1160,6 +1258,40 @@ static uint32_t register_client_adhoc(struct msm_bus_scale_pdata *pdata) } client->pdata = pdata; if (pdata->alc) { client->curr = -1; lnode = kzalloc(sizeof(int), GFP_KERNEL); if (ZERO_OR_NULL_PTR(lnode)) { MSM_BUS_ERR("%s: Error allocating lnode!", __func__); goto exit_lnode_malloc_fail; } client->src_pnode = lnode; client->src_devs = kzalloc(sizeof(struct device *), GFP_KERNEL); if (IS_ERR_OR_NULL(client->src_devs)) { MSM_BUS_ERR("%s: Error allocating src_dev!", __func__); goto exit_src_dev_malloc_fail; } src = MSM_BUS_MAS_ALC; dev = bus_find_device(&msm_bus_type, NULL, (void *) &src, msm_bus_device_match_adhoc); if (IS_ERR_OR_NULL(dev)) { MSM_BUS_ERR("%s:Failed to find alc device", __func__); goto exit_invalid_data; } gen_lnode(dev, MSM_BUS_MAS_ALC, 0, pdata->name); bcm_add_bus_req(dev); client->src_devs[0] = dev; handle = gen_handle(client); goto exit_register_client; } lnode = kcalloc(pdata->usecase->num_paths, sizeof(int), GFP_KERNEL); if (ZERO_OR_NULL_PTR(lnode)) { MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__); Loading Loading @@ -1293,6 +1425,58 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns, return ret; } static int update_client_alc(struct msm_bus_client *client, bool log_trns, unsigned int idx) { int lnode, cur_idx; uint64_t req_idle_time, req_fal, dual_idle_time, dual_fal, cur_idle_time, cur_fal; int ret = 0; struct msm_bus_scale_pdata *pdata; struct device *src_dev; if (!client) { MSM_BUS_ERR("Client handle Null"); ret = -ENXIO; goto exit_update_client_alc; } pdata = client->pdata; if (!pdata) { MSM_BUS_ERR("Client pdata Null"); ret = -ENXIO; goto exit_update_client_alc; } cur_idx = client->curr; client->curr = idx; req_fal = pdata->usecase_lat[idx].fal_ns; req_idle_time = pdata->usecase_lat[idx].idle_t_ns; lnode = client->src_pnode[0]; src_dev = client->src_devs[0]; if (pdata->active_only) { dual_fal = 0; dual_idle_time = 0; } else { dual_fal = req_fal; dual_idle_time = req_idle_time; } ret = update_alc_vote(src_dev, req_fal, req_idle_time, dual_fal, dual_idle_time, cur_fal, cur_idle_time, lnode, pdata->active_only); if (ret) { MSM_BUS_ERR("%s: Update path failed! %d ctx %d\n", __func__, ret, pdata->active_only); goto exit_update_client_alc; } commit_data(); exit_update_client_alc: return ret; } static int query_usecase(struct msm_bus_client *client, bool log_trns, unsigned int idx, struct msm_bus_tcs_usecase *tcs_usecase) Loading Loading @@ -1483,8 +1667,13 @@ static int update_request_adhoc(uint32_t cl, unsigned int index) MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__, cl, index, client->curr, client->pdata->usecase->num_paths); if (pdata->alc) ret = update_client_alc(client, log_transaction, index); else { msm_bus_dbg_client_data(client->pdata, index, cl); ret = update_client_paths(client, log_transaction, index); } if (ret) { pr_err("%s: Err updating path\n", __func__); goto exit_update_request; Loading drivers/soc/qcom/msm_bus/msm_bus_dbg.c +1 −2 Original line number Diff line number Diff line /* Copyright (c) 2010-2012, 2014-2016, The Linux Foundation. All rights /* Copyright (c) 2010-2012, 2014-2017, The Linux Foundation. All rights * reserved. * * This program is free software; you can redistribute it and/or modify Loading Loading @@ -439,7 +439,6 @@ static void msm_bus_dbg_free_client(uint32_t clid) list_for_each_entry(cldata, &cl_list, list) { if (cldata->clid == clid) { debugfs_remove(cldata->file); list_del(&cldata->list); kfree(cldata); break; Loading drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +27 −31 Original line number Diff line number Diff line Loading @@ -265,27 +265,23 @@ static int setrate_nodeclk(struct nodeclk *nclk, long rate) } static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm, struct tcs_cmd *cmd, uint64_t ib, uint64_t ab, bool commit) struct tcs_cmd *cmd, uint64_t vec_a, uint64_t vec_b, bool commit) { int ret = 0; bool valid = true; if (ib == 0 && ab == 0) { if (vec_a == 0 && vec_b == 0) valid = false; } else { do_div(ib, cur_bcm->bcmdev->unit_size); do_div(ab, cur_bcm->bcmdev->unit_size); } if (ib > BCM_TCS_CMD_VOTE_MASK) ib = BCM_TCS_CMD_VOTE_MASK; if (vec_a > BCM_TCS_CMD_VOTE_MASK) vec_a = BCM_TCS_CMD_VOTE_MASK; if (ab > BCM_TCS_CMD_VOTE_MASK) ab = BCM_TCS_CMD_VOTE_MASK; if (vec_b > BCM_TCS_CMD_VOTE_MASK) vec_b = BCM_TCS_CMD_VOTE_MASK; cmd->addr = cur_bcm->bcmdev->addr; cmd->data = BCM_TCS_CMD(commit, valid, ab, ib); cmd->data = BCM_TCS_CMD(commit, valid, vec_a, vec_b); cmd->complete = commit; return ret; Loading Loading @@ -333,8 +329,8 @@ static int tcs_cmd_list_gen(int *n_active, idx++; } tcs_cmd_gen(cur_bcm, &cmdlist_active[k], cur_bcm->node_bw[ACTIVE_CTX].max_ib, cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit); cur_bcm->node_vec[ACTIVE_CTX].vec_a, cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit); k++; last_tcs = k; cur_bcm->updated = true; Loading @@ -352,10 +348,10 @@ static int tcs_cmd_list_gen(int *n_active, continue; list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) { commit = false; if ((cur_bcm->node_bw[DUAL_CTX].max_ab == cur_bcm->node_bw[ACTIVE_CTX].max_ab) && (cur_bcm->node_bw[DUAL_CTX].max_ib == cur_bcm->node_bw[ACTIVE_CTX].max_ib)) { if ((cur_bcm->node_vec[DUAL_CTX].vec_a == cur_bcm->node_vec[ACTIVE_CTX].vec_a) && (cur_bcm->node_vec[DUAL_CTX].vec_b == cur_bcm->node_vec[ACTIVE_CTX].vec_b)) { if (last_tcs != -1 && list_is_last(&cur_bcm->link, &cur_bcm_clist[i])) { Loading @@ -378,11 +374,11 @@ static int tcs_cmd_list_gen(int *n_active, } tcs_cmd_gen(cur_bcm, &cmdlist_wake[k], cur_bcm->node_bw[ACTIVE_CTX].max_ib, cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit); cur_bcm->node_vec[ACTIVE_CTX].vec_a, cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit); tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k], cur_bcm->node_bw[DUAL_CTX].max_ib, cur_bcm->node_bw[DUAL_CTX].max_ab, commit); cur_bcm->node_vec[DUAL_CTX].vec_a, cur_bcm->node_vec[DUAL_CTX].vec_b, commit); k++; } } Loading Loading @@ -485,10 +481,10 @@ static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev) cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]); if (cur_bcm->node_bw[DUAL_CTX].max_ab == 0 && cur_bcm->node_bw[ACTIVE_CTX].max_ab == 0 && cur_bcm->node_bw[DUAL_CTX].max_ib == 0 && cur_bcm->node_bw[ACTIVE_CTX].max_ib == 0) { if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 && cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 && cur_bcm->node_vec[DUAL_CTX].vec_b == 0 && cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0) { cur_bcm->dirty = false; list_del_init(&cur_bcm->link); } Loading Loading @@ -550,10 +546,10 @@ int msm_bus_commit_data(struct list_head *clist) if (list_empty(&cur_bcm_clist[i])) continue; list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) { if ((cur_bcm->node_bw[DUAL_CTX].max_ab != cur_bcm->node_bw[ACTIVE_CTX].max_ab) || (cur_bcm->node_bw[DUAL_CTX].max_ib != cur_bcm->node_bw[ACTIVE_CTX].max_ib)) { if ((cur_bcm->node_vec[DUAL_CTX].vec_a != cur_bcm->node_vec[ACTIVE_CTX].vec_a) || (cur_bcm->node_vec[DUAL_CTX].vec_b != cur_bcm->node_vec[ACTIVE_CTX].vec_b)) { cnt_sleep++; cnt_wake++; } Loading @@ -563,7 +559,6 @@ int msm_bus_commit_data(struct list_head *clist) cnt_vcd++; } MSM_BUS_ERR("%s: cmd_gen\n", __func__); n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); n_wake = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); n_sleep = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); Loading Loading @@ -1086,6 +1081,7 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->name = pdata_node_info->name; node_info->id = pdata_node_info->id; node_info->bcm_req_idx = -1; node_info->bus_device_id = pdata_node_info->bus_device_id; node_info->mas_rpm_id = pdata_node_info->mas_rpm_id; node_info->slv_rpm_id = pdata_node_info->slv_rpm_id; Loading drivers/soc/qcom/msm_bus/msm_bus_of.c +38 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -46,6 +46,7 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev, { struct msm_bus_scale_pdata *pdata = NULL; struct msm_bus_paths *usecase = NULL; struct msm_bus_lat_vectors *usecase_lat = NULL; int i = 0, j, ret, num_usecases = 0, num_paths, len; const uint32_t *vec_arr = NULL; bool mem_err = false; Loading Loading @@ -85,6 +86,42 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev, pr_debug("Using dual context by default\n"); } pdata->alc = of_property_read_bool(of_node, "qcom,msm-bus,alc-voter"); if (pdata->alc) { usecase_lat = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_lat_vectors) * pdata->num_usecases), GFP_KERNEL); if (!usecase_lat) { mem_err = true; goto err; } vec_arr = of_get_property(of_node, "qcom,msm-bus,vectors-alc", &len); if (vec_arr == NULL) { pr_err("Error: Lat vector array not found\n"); goto err; } if (len != num_usecases * sizeof(uint32_t) * 2) { pr_err("Error: Length-error on getting vectors\n"); goto err; } for (i = 0; i < num_usecases; i++) { int index = i * 2; usecase_lat[i].fal_ns = (uint64_t) KBTOB(be32_to_cpu(vec_arr[index])); usecase_lat[i].idle_t_ns = (uint64_t) KBTOB(be32_to_cpu(vec_arr[index + 1])); } pdata->usecase_lat = usecase_lat; return pdata; } usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) * pdata->num_usecases), GFP_KERNEL); if (!usecase) { Loading Loading
Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt +19 −1 Original line number Diff line number Diff line Loading @@ -218,7 +218,16 @@ using the following properties: master-id, slave-id, arbitrated bandwidth in KBps, instantaneous bandwidth in KBps Example: The following are optional properties for client's device nodes: - qcom,msm-bus,alc-voter: Boolean alc_voter flag to indicate that client will vote as an Active Latency Client. - qcom,msm-bus,vectors-alc: Arrays of unsigned integers representing: first access latency, idle time in ns, this property is required if qcom,msm-bus,alc-voter is present. Example for default client: qcom,msm-bus,name = "client-name"; qcom,msm-bus,num-cases = <3>; Loading @@ -229,3 +238,12 @@ Example: <22 512 320000 3200000>, <26 512 3200000 3200000>, <22 512 160000 1600000>, <26 512 1600000 1600000>; Example for ALC client: qcom,msm-bus,name = "client-name"; qcom,msm-bus,num-cases = <2>; qcom,msm-bus,active-only; qcom,msm-bus,alc-voter; qcom,msm-bus,vectors-alc = <0 0>, <500 1600>;
drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c +198 −9 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #define NUM_LNODES 3 #define MAX_STR_CL 50 #define MSM_BUS_MAS_ALC 144 struct bus_search_type { struct list_head link; struct list_head node_list; Loading Loading @@ -123,6 +125,9 @@ static void bcm_add_bus_req(struct device *dev) goto exit_bcm_add_bus_req; } if (cur_dev->node_info->bcm_req_idx != -1) goto exit_bcm_add_bus_req; if (!cur_dev->node_info->num_bcm_devs) goto exit_bcm_add_bus_req; Loading Loading @@ -179,8 +184,6 @@ static void bcm_add_bus_req(struct device *dev) cur_dev->node_info->bcm_req_idx = lnode_idx; memset(lnode->lnode_ib, 0, sizeof(uint64_t) * NUM_CTX); memset(lnode->lnode_ab, 0, sizeof(uint64_t) * NUM_CTX); MSM_BUS_ERR("%s: Added %d entry to bcm %d @ %d\n", __func__, lnode->bus_dev_id, bcm_dev->node_info->id, lnode_idx); } exit_bcm_add_bus_req: Loading Loading @@ -316,7 +319,6 @@ static int prune_path(struct list_head *route_list, int dest, int src, MSM_BUS_ERR("%s: Can't find dest dev %d", __func__, dest); goto exit_prune_path; } MSM_BUS_ERR("%s: dest dev %d", __func__, dest); lnode_hop = gen_lnode(dest_dev, search_dev_id, lnode_hop, cl_name); bcm_add_bus_req(dest_dev); Loading Loading @@ -520,7 +522,6 @@ static void bcm_update_bus_req(struct device *dev, int ctx) max_ib = max(max_ib, max(bcm_dev->lnode_list[i].lnode_ib[ACTIVE_CTX], bcm_dev->lnode_list[i].lnode_ib[DUAL_CTX])); max_ab = max(max_ab, bcm_dev->lnode_list[i].lnode_ab[ACTIVE_CTX] + bcm_dev->lnode_list[i].lnode_ab[DUAL_CTX]); Loading @@ -531,9 +532,14 @@ static void bcm_update_bus_req(struct device *dev, int ctx) bcm_dev->lnode_list[i].lnode_ab[ctx]); } } bcm_dev->node_bw[ctx].max_ab = max_ab; bcm_dev->node_bw[ctx].max_ib = max_ib; max_ab = msm_bus_div64(max_ab, bcm_dev->bcmdev->unit_size); max_ib = msm_bus_div64(max_ib, bcm_dev->bcmdev->unit_size); bcm_dev->node_vec[ctx].vec_a = max_ab; bcm_dev->node_vec[ctx].vec_b = max_ib; } exit_bcm_update_bus_req: return; Loading Loading @@ -598,15 +604,51 @@ static void bcm_query_bus_req(struct device *dev, int ctx) } } max_query_ab = msm_bus_div64(max_query_ab, bcm_dev->bcmdev->unit_size); max_query_ib = msm_bus_div64(max_query_ib, bcm_dev->bcmdev->unit_size); bcm_dev->node_bw[ctx].max_query_ab = max_query_ab; bcm_dev->node_bw[ctx].max_query_ib = max_query_ib; } exit_bcm_query_bus_req: return; } static void bcm_update_alc_req(struct msm_bus_node_device_type *dev, int ctx) { struct msm_bus_node_device_type *bcm_dev = NULL; int i; uint64_t max_alc = 0; if (!dev || !to_msm_bus_node(dev->node_info->bus_device)) { MSM_BUS_ERR("Bus node pointer is Invalid"); goto exit_bcm_update_alc_req; } for (i = 0; i < dev->num_lnodes; i++) max_alc = max(max_alc, dev->lnode_list[i].alc_idx[ctx]); dev->node_bw[ctx].max_alc = max_alc; bcm_dev = to_msm_bus_node(dev->node_info->bcm_devs[0]); if (ctx == ACTIVE_CTX) { max_alc = max(max_alc, max(dev->node_bw[ACTIVE_CTX].max_alc, dev->node_bw[DUAL_CTX].max_alc)); } else { max_alc = dev->node_bw[ctx].max_alc; } bcm_dev->node_bw[ctx].max_alc = max_alc; bcm_dev->node_vec[ctx].vec_a = max_alc; bcm_dev->node_vec[ctx].vec_b = 0; exit_bcm_update_alc_req: return; } int bcm_remove_handoff_req(struct device *dev, void *data) { Loading Loading @@ -684,7 +726,6 @@ static void aggregate_bus_query_req(struct msm_bus_node_device_type *bus_dev, sum_ab += bus_dev->lnode_list[i].lnode_query_ab[ctx]; } MSM_BUS_ERR("aggregate: query_ab:%llu\n", sum_ab); bus_dev->node_bw[ctx].sum_query_ab = sum_ab; bus_dev->node_bw[ctx].max_query_ib = max_ib; Loading Loading @@ -870,6 +911,63 @@ static int update_path(struct device *src_dev, int dest, uint64_t act_req_ib, return ret; } static int update_alc_vote(struct device *alc_dev, uint64_t act_req_fa_lat, uint64_t act_req_idle_time, uint64_t slp_req_fa_lat, uint64_t slp_req_idle_time, uint64_t cur_fa_lat, uint64_t cur_idle_time, int idx, int ctx) { struct link_node *lnode = NULL; struct msm_bus_node_device_type *dev_info = NULL; int curr_idx, i; int ret = 0; if (IS_ERR_OR_NULL(alc_dev)) { MSM_BUS_ERR("%s: No source device", __func__); ret = -ENODEV; goto exit_update_alc_vote; } if (idx < 0) { MSM_BUS_ERR("%s: Invalid lnode idx %d", __func__, idx); ret = -ENXIO; goto exit_update_alc_vote; } dev_info = to_msm_bus_node(alc_dev); curr_idx = idx; if (curr_idx >= dev_info->num_lnodes) { MSM_BUS_ERR("%s: Invalid lnode Idx %d num lnodes %d", __func__, curr_idx, dev_info->num_lnodes); ret = -ENXIO; goto exit_update_alc_vote; } lnode = &dev_info->lnode_list[curr_idx]; if (!lnode) { MSM_BUS_ERR("%s: Invalid lnode ptr lnode %d", __func__, curr_idx); ret = -ENXIO; goto exit_update_alc_vote; } /* * Add aggregation and mapping logic once LUT is avail. * Use default values for time being. */ lnode->alc_idx[ACTIVE_CTX] = 12; lnode->alc_idx[DUAL_CTX] = 0; for (i = 0; i < NUM_CTX; i++) bcm_update_alc_req(dev_info, i); add_node_to_clist(dev_info); exit_update_alc_vote: return ret; } static int query_path(struct device *src_dev, int dest, uint64_t act_req_ib, uint64_t act_req_bw, uint64_t slp_req_ib, uint64_t slp_req_bw, uint64_t cur_ib, uint64_t cur_bw, Loading Loading @@ -1160,6 +1258,40 @@ static uint32_t register_client_adhoc(struct msm_bus_scale_pdata *pdata) } client->pdata = pdata; if (pdata->alc) { client->curr = -1; lnode = kzalloc(sizeof(int), GFP_KERNEL); if (ZERO_OR_NULL_PTR(lnode)) { MSM_BUS_ERR("%s: Error allocating lnode!", __func__); goto exit_lnode_malloc_fail; } client->src_pnode = lnode; client->src_devs = kzalloc(sizeof(struct device *), GFP_KERNEL); if (IS_ERR_OR_NULL(client->src_devs)) { MSM_BUS_ERR("%s: Error allocating src_dev!", __func__); goto exit_src_dev_malloc_fail; } src = MSM_BUS_MAS_ALC; dev = bus_find_device(&msm_bus_type, NULL, (void *) &src, msm_bus_device_match_adhoc); if (IS_ERR_OR_NULL(dev)) { MSM_BUS_ERR("%s:Failed to find alc device", __func__); goto exit_invalid_data; } gen_lnode(dev, MSM_BUS_MAS_ALC, 0, pdata->name); bcm_add_bus_req(dev); client->src_devs[0] = dev; handle = gen_handle(client); goto exit_register_client; } lnode = kcalloc(pdata->usecase->num_paths, sizeof(int), GFP_KERNEL); if (ZERO_OR_NULL_PTR(lnode)) { MSM_BUS_ERR("%s: Error allocating pathnode ptr!", __func__); Loading Loading @@ -1293,6 +1425,58 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns, return ret; } static int update_client_alc(struct msm_bus_client *client, bool log_trns, unsigned int idx) { int lnode, cur_idx; uint64_t req_idle_time, req_fal, dual_idle_time, dual_fal, cur_idle_time, cur_fal; int ret = 0; struct msm_bus_scale_pdata *pdata; struct device *src_dev; if (!client) { MSM_BUS_ERR("Client handle Null"); ret = -ENXIO; goto exit_update_client_alc; } pdata = client->pdata; if (!pdata) { MSM_BUS_ERR("Client pdata Null"); ret = -ENXIO; goto exit_update_client_alc; } cur_idx = client->curr; client->curr = idx; req_fal = pdata->usecase_lat[idx].fal_ns; req_idle_time = pdata->usecase_lat[idx].idle_t_ns; lnode = client->src_pnode[0]; src_dev = client->src_devs[0]; if (pdata->active_only) { dual_fal = 0; dual_idle_time = 0; } else { dual_fal = req_fal; dual_idle_time = req_idle_time; } ret = update_alc_vote(src_dev, req_fal, req_idle_time, dual_fal, dual_idle_time, cur_fal, cur_idle_time, lnode, pdata->active_only); if (ret) { MSM_BUS_ERR("%s: Update path failed! %d ctx %d\n", __func__, ret, pdata->active_only); goto exit_update_client_alc; } commit_data(); exit_update_client_alc: return ret; } static int query_usecase(struct msm_bus_client *client, bool log_trns, unsigned int idx, struct msm_bus_tcs_usecase *tcs_usecase) Loading Loading @@ -1483,8 +1667,13 @@ static int update_request_adhoc(uint32_t cl, unsigned int index) MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__, cl, index, client->curr, client->pdata->usecase->num_paths); if (pdata->alc) ret = update_client_alc(client, log_transaction, index); else { msm_bus_dbg_client_data(client->pdata, index, cl); ret = update_client_paths(client, log_transaction, index); } if (ret) { pr_err("%s: Err updating path\n", __func__); goto exit_update_request; Loading
drivers/soc/qcom/msm_bus/msm_bus_dbg.c +1 −2 Original line number Diff line number Diff line /* Copyright (c) 2010-2012, 2014-2016, The Linux Foundation. All rights /* Copyright (c) 2010-2012, 2014-2017, The Linux Foundation. All rights * reserved. * * This program is free software; you can redistribute it and/or modify Loading Loading @@ -439,7 +439,6 @@ static void msm_bus_dbg_free_client(uint32_t clid) list_for_each_entry(cldata, &cl_list, list) { if (cldata->clid == clid) { debugfs_remove(cldata->file); list_del(&cldata->list); kfree(cldata); break; Loading
drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +27 −31 Original line number Diff line number Diff line Loading @@ -265,27 +265,23 @@ static int setrate_nodeclk(struct nodeclk *nclk, long rate) } static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm, struct tcs_cmd *cmd, uint64_t ib, uint64_t ab, bool commit) struct tcs_cmd *cmd, uint64_t vec_a, uint64_t vec_b, bool commit) { int ret = 0; bool valid = true; if (ib == 0 && ab == 0) { if (vec_a == 0 && vec_b == 0) valid = false; } else { do_div(ib, cur_bcm->bcmdev->unit_size); do_div(ab, cur_bcm->bcmdev->unit_size); } if (ib > BCM_TCS_CMD_VOTE_MASK) ib = BCM_TCS_CMD_VOTE_MASK; if (vec_a > BCM_TCS_CMD_VOTE_MASK) vec_a = BCM_TCS_CMD_VOTE_MASK; if (ab > BCM_TCS_CMD_VOTE_MASK) ab = BCM_TCS_CMD_VOTE_MASK; if (vec_b > BCM_TCS_CMD_VOTE_MASK) vec_b = BCM_TCS_CMD_VOTE_MASK; cmd->addr = cur_bcm->bcmdev->addr; cmd->data = BCM_TCS_CMD(commit, valid, ab, ib); cmd->data = BCM_TCS_CMD(commit, valid, vec_a, vec_b); cmd->complete = commit; return ret; Loading Loading @@ -333,8 +329,8 @@ static int tcs_cmd_list_gen(int *n_active, idx++; } tcs_cmd_gen(cur_bcm, &cmdlist_active[k], cur_bcm->node_bw[ACTIVE_CTX].max_ib, cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit); cur_bcm->node_vec[ACTIVE_CTX].vec_a, cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit); k++; last_tcs = k; cur_bcm->updated = true; Loading @@ -352,10 +348,10 @@ static int tcs_cmd_list_gen(int *n_active, continue; list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) { commit = false; if ((cur_bcm->node_bw[DUAL_CTX].max_ab == cur_bcm->node_bw[ACTIVE_CTX].max_ab) && (cur_bcm->node_bw[DUAL_CTX].max_ib == cur_bcm->node_bw[ACTIVE_CTX].max_ib)) { if ((cur_bcm->node_vec[DUAL_CTX].vec_a == cur_bcm->node_vec[ACTIVE_CTX].vec_a) && (cur_bcm->node_vec[DUAL_CTX].vec_b == cur_bcm->node_vec[ACTIVE_CTX].vec_b)) { if (last_tcs != -1 && list_is_last(&cur_bcm->link, &cur_bcm_clist[i])) { Loading @@ -378,11 +374,11 @@ static int tcs_cmd_list_gen(int *n_active, } tcs_cmd_gen(cur_bcm, &cmdlist_wake[k], cur_bcm->node_bw[ACTIVE_CTX].max_ib, cur_bcm->node_bw[ACTIVE_CTX].max_ab, commit); cur_bcm->node_vec[ACTIVE_CTX].vec_a, cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit); tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k], cur_bcm->node_bw[DUAL_CTX].max_ib, cur_bcm->node_bw[DUAL_CTX].max_ab, commit); cur_bcm->node_vec[DUAL_CTX].vec_a, cur_bcm->node_vec[DUAL_CTX].vec_b, commit); k++; } } Loading Loading @@ -485,10 +481,10 @@ static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev) cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[0]); if (cur_bcm->node_bw[DUAL_CTX].max_ab == 0 && cur_bcm->node_bw[ACTIVE_CTX].max_ab == 0 && cur_bcm->node_bw[DUAL_CTX].max_ib == 0 && cur_bcm->node_bw[ACTIVE_CTX].max_ib == 0) { if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 && cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 && cur_bcm->node_vec[DUAL_CTX].vec_b == 0 && cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0) { cur_bcm->dirty = false; list_del_init(&cur_bcm->link); } Loading Loading @@ -550,10 +546,10 @@ int msm_bus_commit_data(struct list_head *clist) if (list_empty(&cur_bcm_clist[i])) continue; list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) { if ((cur_bcm->node_bw[DUAL_CTX].max_ab != cur_bcm->node_bw[ACTIVE_CTX].max_ab) || (cur_bcm->node_bw[DUAL_CTX].max_ib != cur_bcm->node_bw[ACTIVE_CTX].max_ib)) { if ((cur_bcm->node_vec[DUAL_CTX].vec_a != cur_bcm->node_vec[ACTIVE_CTX].vec_a) || (cur_bcm->node_vec[DUAL_CTX].vec_b != cur_bcm->node_vec[ACTIVE_CTX].vec_b)) { cnt_sleep++; cnt_wake++; } Loading @@ -563,7 +559,6 @@ int msm_bus_commit_data(struct list_head *clist) cnt_vcd++; } MSM_BUS_ERR("%s: cmd_gen\n", __func__); n_active = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); n_wake = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); n_sleep = kcalloc(cnt_vcd+1, sizeof(int), GFP_KERNEL); Loading Loading @@ -1086,6 +1081,7 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->name = pdata_node_info->name; node_info->id = pdata_node_info->id; node_info->bcm_req_idx = -1; node_info->bus_device_id = pdata_node_info->bus_device_id; node_info->mas_rpm_id = pdata_node_info->mas_rpm_id; node_info->slv_rpm_id = pdata_node_info->slv_rpm_id; Loading
drivers/soc/qcom/msm_bus/msm_bus_of.c +38 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -46,6 +46,7 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev, { struct msm_bus_scale_pdata *pdata = NULL; struct msm_bus_paths *usecase = NULL; struct msm_bus_lat_vectors *usecase_lat = NULL; int i = 0, j, ret, num_usecases = 0, num_paths, len; const uint32_t *vec_arr = NULL; bool mem_err = false; Loading Loading @@ -85,6 +86,42 @@ static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev, pr_debug("Using dual context by default\n"); } pdata->alc = of_property_read_bool(of_node, "qcom,msm-bus,alc-voter"); if (pdata->alc) { usecase_lat = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_lat_vectors) * pdata->num_usecases), GFP_KERNEL); if (!usecase_lat) { mem_err = true; goto err; } vec_arr = of_get_property(of_node, "qcom,msm-bus,vectors-alc", &len); if (vec_arr == NULL) { pr_err("Error: Lat vector array not found\n"); goto err; } if (len != num_usecases * sizeof(uint32_t) * 2) { pr_err("Error: Length-error on getting vectors\n"); goto err; } for (i = 0; i < num_usecases; i++) { int index = i * 2; usecase_lat[i].fal_ns = (uint64_t) KBTOB(be32_to_cpu(vec_arr[index])); usecase_lat[i].idle_t_ns = (uint64_t) KBTOB(be32_to_cpu(vec_arr[index + 1])); } pdata->usecase_lat = usecase_lat; return pdata; } usecase = devm_kzalloc(&pdev->dev, (sizeof(struct msm_bus_paths) * pdata->num_usecases), GFP_KERNEL); if (!usecase) { Loading