Loading Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt +14 −4 Original line number Diff line number Diff line Loading @@ -57,11 +57,16 @@ qcom,qos-off: Parameter that represents the delta between QoS register address space for different devices. Typically these optional properties are used for devices that represent fabric devices. qcom,util-fact: Parameter that represents the DDR utilization factor. It is represented as actual util-factor * 100. qcom,agg-scheme: Parameter that represents the aggregation scheme to be used for the node. This parameter defaults to LEGACY scheme. The valid options are LEGACY/SCHEME_1. qcom,util-fact: Parameter that represents the DDR utilization factor to be used in LEGACY scheme. It is represented as actual util-factor * 100. qcom,vrail-comp: Parameter that represents the voltage rail compensation to push the bus to the next level if needed. It is represented as actual vrail-comp * 100. the bus to the next level if needed in LEGACY and SCHEME 1 aggregation schemes. It is represented as actual vrail-comp * 100. qcom,util-levels: Array of tuples that represent a bandwidth threshold and util factor to be used uptil the given threshold. qcom,bus-type: Parameter that represents the bus type such as BIMC or NOC. Typically these optional properties are used for devices that represent fabric devices. Loading Loading @@ -148,6 +153,9 @@ Example: label = "fab-snoc"; qcom,fab-dev; qcom,bypass-qos-prg; qcom,agg-scheme = <SCHEME_1>; qcom,util-levels = <450000 133>, <750000 154>; qcom,base-name = "snoc-base"; qcom,base-offset = <0x7000>; qcom,qos-off = <0x1000>; Loading @@ -166,6 +174,8 @@ Example: mm_int_bimc: mm-int-bimc { cell-id = <10003>; label = "mm-int-bimc"; qcom,util-fact = <154>; qcom,vrail-comp = <100>; qcom,ap-owned; qcom,connections = <&snoc_bimc_1_mas>; qcom,bus-dev = <&fab_snoc>; Loading drivers/platform/msm/msm_bus/msm_bus_adhoc.h +17 −6 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ struct nodebw { uint64_t last_sum_ab; uint64_t max_ib; uint64_t cur_clk_hz; uint32_t util_used; uint32_t vrail_used; }; struct msm_bus_fab_device_type { Loading @@ -60,8 +62,6 @@ struct msm_bus_fab_device_type { uint32_t base_offset; uint32_t qos_freq; uint32_t qos_off; uint32_t util_fact; uint32_t vrail_comp; struct msm_bus_noc_ops noc_ops; enum msm_bus_hw_sel bus_type; bool bypass_qos_prg; Loading @@ -83,6 +83,20 @@ struct qos_params_type { u64 bw_buffer; }; struct node_util_levels_type { uint64_t threshold; uint32_t util_fact; }; struct node_agg_params_type { uint32_t agg_scheme; uint32_t num_aggports; unsigned int buswidth; uint32_t vrail_comp; uint32_t num_util_levels; struct node_util_levels_type *util_levels; }; struct msm_bus_node_info_type { const char *name; unsigned int id; Loading @@ -103,13 +117,10 @@ struct msm_bus_node_info_type { struct device **black_connections; unsigned int bus_device_id; struct device *bus_device; unsigned int buswidth; struct rule_update_path_info rule; uint64_t lim_bw; uint32_t util_fact; uint32_t vrail_comp; uint32_t num_aggports; bool defer_qos; struct node_agg_params_type agg_params; }; struct msm_bus_node_device_type { Loading drivers/platform/msm/msm_bus/msm_bus_arb_adhoc.c +166 −35 Original line number Diff line number Diff line Loading @@ -395,68 +395,197 @@ exit_getpath: return first_hop; } static uint64_t arbitrate_bus_req(struct msm_bus_node_device_type *bus_dev, int ctx) static uint64_t scheme1_agg_scheme(struct msm_bus_node_device_type *bus_dev, struct msm_bus_node_device_type *fab_dev, int ctx) { int i; uint64_t max_ib = 0; uint64_t sum_ab = 0; uint64_t max_ib; uint64_t sum_ab; uint64_t bw_max_hz; struct msm_bus_node_device_type *fab_dev = NULL; uint32_t util_fact = 0; uint32_t vrail_comp = 0; struct node_util_levels_type *utils; int i; int num_util_levels; /* Find max ib */ for (i = 0; i < bus_dev->num_lnodes; i++) { max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]); sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; /* * Account for Util factor and vrail comp. * Util factor is picked according to the current sum(AB) for this * node and for this context. * Vrail comp is fixed for the entire performance range. * They default to 100 if absent. * * The aggregated clock is computed as: * Freq_hz = max((sum(ab) * util_fact)/num_chan, max(ib)/vrail_comp) * / bus-width */ if (bus_dev->node_info->agg_params.num_util_levels) { utils = bus_dev->node_info->agg_params.util_levels; num_util_levels = bus_dev->node_info->agg_params.num_util_levels; } else { utils = fab_dev->node_info->agg_params.util_levels; num_util_levels = fab_dev->node_info->agg_params.num_util_levels; } bus_dev->node_bw[ctx].sum_ab = sum_ab; bus_dev->node_bw[ctx].max_ib = max_ib; sum_ab = bus_dev->node_bw[ctx].sum_ab; max_ib = bus_dev->node_bw[ctx].max_ib; for (i = 0; i < num_util_levels; i++) { if (sum_ab < utils[i].threshold) { util_fact = utils[i].util_fact; break; } } if (i == num_util_levels) util_fact = utils[(num_util_levels - 1)].util_fact; vrail_comp = bus_dev->node_info->agg_params.vrail_comp ? bus_dev->node_info->agg_params.vrail_comp : fab_dev->node_info->agg_params.vrail_comp; bus_dev->node_bw[ctx].vrail_used = vrail_comp; bus_dev->node_bw[ctx].util_used = util_fact; if (util_fact && (util_fact != 100)) { sum_ab *= util_fact; sum_ab = msm_bus_div64(100, sum_ab); } if (vrail_comp && (vrail_comp != 100)) { max_ib *= 100; max_ib = msm_bus_div64(vrail_comp, max_ib); } /* Account for multiple channels if any */ if (bus_dev->node_info->agg_params.num_aggports > 1) sum_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, sum_ab); if (!bus_dev->node_info->agg_params.buswidth) { MSM_BUS_WARN("No bus width found for %d. Using default\n", bus_dev->node_info->id); bus_dev->node_info->agg_params.buswidth = 8; } bw_max_hz = max(max_ib, sum_ab); bw_max_hz = msm_bus_div64(bus_dev->node_info->agg_params.buswidth, bw_max_hz); return bw_max_hz; } static uint64_t legacy_agg_scheme(struct msm_bus_node_device_type *bus_dev, struct msm_bus_node_device_type *fab_dev, int ctx) { uint64_t max_ib; uint64_t sum_ab; uint64_t bw_max_hz; uint32_t util_fact = 0; uint32_t vrail_comp = 0; /* * Account for Util factor and vrail comp. The new aggregation * formula is: * Util_fact and vrail comp are obtained from fabric/Node's dts * properties and are fixed for the entire performance range. * They default to 100 if absent. * * The clock frequency is computed as: * Freq_hz = max((sum(ab) * util_fact)/num_chan, max(ib)/vrail_comp) * / bus-width * util_fact and vrail comp are obtained from fabric/Node's dts * properties. * They default to 100 if absent. */ fab_dev = bus_dev->node_info->bus_device->platform_data; /* Don't do this for virtual fabrics */ if (fab_dev && fab_dev->fabdev) { util_fact = bus_dev->node_info->util_fact ? bus_dev->node_info->util_fact : fab_dev->fabdev->util_fact; vrail_comp = bus_dev->node_info->vrail_comp ? bus_dev->node_info->vrail_comp : fab_dev->fabdev->vrail_comp; util_fact = fab_dev->node_info->agg_params.util_levels[0].util_fact; vrail_comp = fab_dev->node_info->agg_params.vrail_comp; if (bus_dev->node_info->agg_params.num_util_levels) util_fact = bus_dev->node_info->agg_params.util_levels[0].util_fact ? bus_dev->node_info->agg_params.util_levels[0].util_fact : util_fact; vrail_comp = bus_dev->node_info->agg_params.vrail_comp ? bus_dev->node_info->agg_params.vrail_comp : vrail_comp; bus_dev->node_bw[ctx].vrail_used = vrail_comp; bus_dev->node_bw[ctx].util_used = util_fact; sum_ab = bus_dev->node_bw[ctx].sum_ab; max_ib = bus_dev->node_bw[ctx].max_ib; if (util_fact && (util_fact != 100)) { sum_ab *= util_fact; sum_ab = msm_bus_div64(100, sum_ab); } if (vrail_comp && (vrail_comp != 100)) { max_ib *= 100; max_ib = msm_bus_div64(vrail_comp, max_ib); } /* Account for multiple channels if any */ if (bus_dev->node_info->num_aggports > 1) sum_ab = msm_bus_div64(bus_dev->node_info->num_aggports, if (bus_dev->node_info->agg_params.num_aggports > 1) sum_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, sum_ab); if (!bus_dev->node_info->buswidth) { if (!bus_dev->node_info->agg_params.buswidth) { MSM_BUS_WARN("No bus width found for %d. Using default\n", bus_dev->node_info->id); bus_dev->node_info->buswidth = 8; bus_dev->node_info->agg_params.buswidth = 8; } bw_max_hz = max(max_ib, sum_ab); bw_max_hz = msm_bus_div64(bus_dev->node_info->buswidth, bw_max_hz = msm_bus_div64(bus_dev->node_info->agg_params.buswidth, bw_max_hz); return bw_max_hz; } static uint64_t aggregate_bus_req(struct msm_bus_node_device_type *bus_dev, int ctx) { uint64_t bw_hz = 0; int i; struct msm_bus_node_device_type *fab_dev = NULL; uint32_t agg_scheme; uint64_t max_ib = 0; uint64_t sum_ab = 0; if (!bus_dev || !bus_dev->node_info->bus_device->platform_data) { MSM_BUS_ERR("Bus node pointer is Invalid"); goto exit_agg_bus_req; } fab_dev = bus_dev->node_info->bus_device->platform_data; for (i = 0; i < bus_dev->num_lnodes; i++) { max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]); sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; } bus_dev->node_bw[ctx].sum_ab = sum_ab; bus_dev->node_bw[ctx].max_ib = max_ib; if (bus_dev->node_info->agg_params.agg_scheme != AGG_SCHEME_NONE) agg_scheme = bus_dev->node_info->agg_params.agg_scheme; else agg_scheme = fab_dev->node_info->agg_params.agg_scheme; switch (agg_scheme) { case AGG_SCHEME_1: bw_hz = scheme1_agg_scheme(bus_dev, fab_dev, ctx); break; case AGG_SCHEME_LEG: bw_hz = legacy_agg_scheme(bus_dev, fab_dev, ctx); break; default: panic("Invalid Bus aggregation scheme"); } exit_agg_bus_req: return bw_hz; } static void del_inp_list(struct list_head *list) { struct rule_update_path_info *rule_node; Loading Loading @@ -519,8 +648,10 @@ static uint64_t get_node_aggab(struct msm_bus_node_device_type *bus_dev) for (i = 0; i < bus_dev->num_lnodes; i++) agg_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; if (bus_dev->node_info->num_aggports > 1) agg_ab = msm_bus_div64(bus_dev->node_info->num_aggports, if (bus_dev->node_info->agg_params.num_aggports > 1) agg_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, agg_ab); max_agg_ab = max(max_agg_ab, agg_ab); Loading Loading @@ -606,7 +737,7 @@ static int update_path(int src, int dest, uint64_t act_req_ib, for (i = 0; i < NUM_CTX; i++) dev_info->node_bw[i].cur_clk_hz = arbitrate_bus_req(dev_info, i); aggregate_bus_req(dev_info, i); /* Start updating the clocks at the first hop. * Its ok to figure out the aggregated Loading drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +2 −2 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is Mree software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -198,7 +198,7 @@ static int msm_bus_floor_init_dev(struct device *fab_dev, bus_node->node_info = node_info; bus_node->ap_owned = true; bus_node->node_info->bus_device = fab_dev; bus_node->node_info->buswidth = 8; bus_node->node_info->agg_params.buswidth = 8; dev->platform_data = bus_node; dev->bus = &msm_bus_type; Loading drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c +39 −47 Original line number Diff line number Diff line Loading @@ -25,41 +25,6 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data); ssize_t vrail_show(struct device *dev, struct device_attribute *attr, char *buf) { struct msm_bus_node_info_type *node_info = NULL; struct msm_bus_node_device_type *bus_node = NULL; bus_node = dev->platform_data; if (!bus_node) return -EINVAL; node_info = bus_node->node_info; return snprintf(buf, PAGE_SIZE, "%u", node_info->vrail_comp); } ssize_t vrail_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct msm_bus_node_info_type *node_info = NULL; struct msm_bus_node_device_type *bus_node = NULL; int ret = 0; bus_node = dev->platform_data; if (!bus_node) return -EINVAL; node_info = bus_node->node_info; ret = sscanf(buf, "%u", &node_info->vrail_comp); if (ret != 1) return -EINVAL; return count; } DEVICE_ATTR(vrail, 0600, vrail_show, vrail_store); ssize_t bw_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -92,17 +57,29 @@ ssize_t bw_show(struct device *dev, struct device_attribute *attr, bus_node->lnode_list[i].lnode_ab[DUAL_CTX]); } off += scnprintf((buf + off), PAGE_SIZE, "Max_Act_IB %llu Sum_Act_AB %llu\nMax_Slp_IB %llu Sum_Slp_AB %llu\n", "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", bus_node->node_bw[ACTIVE_CTX].max_ib, bus_node->node_bw[ACTIVE_CTX].sum_ab, bus_node->node_bw[ACTIVE_CTX].util_used, bus_node->node_bw[ACTIVE_CTX].vrail_used); off += scnprintf((buf + off), PAGE_SIZE, "Max_Slp_IB %llu Sum_Slp_AB %llu Slp_Util_fact %d Slp_Vrail_comp %d\n", bus_node->node_bw[DUAL_CTX].max_ib, bus_node->node_bw[DUAL_CTX].sum_ab); bus_node->node_bw[DUAL_CTX].sum_ab, bus_node->node_bw[DUAL_CTX].util_used, bus_node->node_bw[DUAL_CTX].vrail_used); trace_printk( "Max_Act_IB %llu Sum_Act_AB %llu\nMax_Slp_IB %llu Sum_Slp_AB %llu\n", "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", bus_node->node_bw[ACTIVE_CTX].max_ib, bus_node->node_bw[ACTIVE_CTX].sum_ab, bus_node->node_bw[ACTIVE_CTX].util_used, bus_node->node_bw[ACTIVE_CTX].vrail_used); trace_printk( "Max_Slp_IB %llu Sum_Slp_AB %lluSlp_Util_fact %d Slp_Vrail_comp %d\n", bus_node->node_bw[DUAL_CTX].max_ib, bus_node->node_bw[DUAL_CTX].sum_ab); bus_node->node_bw[DUAL_CTX].sum_ab, bus_node->node_bw[DUAL_CTX].util_used, bus_node->node_bw[DUAL_CTX].vrail_used); return off; } Loading Loading @@ -909,8 +886,6 @@ static int msm_bus_fabric_init(struct device *dev, fabdev->qos_freq = pdata->fabdev->qos_freq; fabdev->bus_type = pdata->fabdev->bus_type; fabdev->bypass_qos_prg = pdata->fabdev->bypass_qos_prg; fabdev->util_fact = pdata->fabdev->util_fact; fabdev->vrail_comp = pdata->fabdev->vrail_comp; msm_bus_fab_init_noc_ops(node_dev); fabdev->qos_base = devm_ioremap(dev, Loading Loading @@ -1020,8 +995,6 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->num_connections = pdata_node_info->num_connections; node_info->num_blist = pdata_node_info->num_blist; node_info->num_qports = pdata_node_info->num_qports; node_info->num_aggports = pdata_node_info->num_aggports; node_info->buswidth = pdata_node_info->buswidth; node_info->virt_dev = pdata_node_info->virt_dev; node_info->is_fab_dev = pdata_node_info->is_fab_dev; node_info->qos_params.mode = pdata_node_info->qos_params.mode; Loading @@ -1036,8 +1009,28 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->qos_params.thmp = pdata_node_info->qos_params.thmp; node_info->qos_params.ws = pdata_node_info->qos_params.ws; node_info->qos_params.bw_buffer = pdata_node_info->qos_params.bw_buffer; node_info->util_fact = pdata_node_info->util_fact; node_info->vrail_comp = pdata_node_info->vrail_comp; node_info->agg_params.buswidth = pdata_node_info->agg_params.buswidth; node_info->agg_params.agg_scheme = pdata_node_info->agg_params.agg_scheme; node_info->agg_params.vrail_comp = pdata_node_info->agg_params.vrail_comp; node_info->agg_params.num_aggports = pdata_node_info->agg_params.num_aggports; node_info->agg_params.num_util_levels = pdata_node_info->agg_params.num_util_levels; node_info->agg_params.util_levels = devm_kzalloc(bus_dev, sizeof(struct node_util_levels_type) * node_info->agg_params.num_util_levels, GFP_KERNEL); if (!node_info->agg_params.util_levels) { MSM_BUS_ERR("%s: Agg util level alloc failed\n", __func__); ret = -ENOMEM; goto exit_copy_node_info; } memcpy(node_info->agg_params.util_levels, pdata_node_info->agg_params.util_levels, sizeof(struct node_util_levels_type) * pdata_node_info->agg_params.num_util_levels); node_info->dev_connections = devm_kzalloc(bus_dev, sizeof(struct device *) * Loading Loading @@ -1181,7 +1174,6 @@ static struct device *msm_bus_device_init( bus_dev = NULL; goto exit_device_init; } device_create_file(bus_dev, &dev_attr_vrail); device_create_file(bus_dev, &dev_attr_bw); exit_device_init: Loading Loading @@ -1271,7 +1263,7 @@ static int msm_bus_node_debug(struct device *bus_dev, void *data) } MSM_BUS_DBG("Device = %d buswidth %u", bus_node->node_info->id, bus_node->node_info->buswidth); bus_node->node_info->agg_params.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 *) Loading Loading
Documentation/devicetree/bindings/arm/msm/msm_bus_adhoc.txt +14 −4 Original line number Diff line number Diff line Loading @@ -57,11 +57,16 @@ qcom,qos-off: Parameter that represents the delta between QoS register address space for different devices. Typically these optional properties are used for devices that represent fabric devices. qcom,util-fact: Parameter that represents the DDR utilization factor. It is represented as actual util-factor * 100. qcom,agg-scheme: Parameter that represents the aggregation scheme to be used for the node. This parameter defaults to LEGACY scheme. The valid options are LEGACY/SCHEME_1. qcom,util-fact: Parameter that represents the DDR utilization factor to be used in LEGACY scheme. It is represented as actual util-factor * 100. qcom,vrail-comp: Parameter that represents the voltage rail compensation to push the bus to the next level if needed. It is represented as actual vrail-comp * 100. the bus to the next level if needed in LEGACY and SCHEME 1 aggregation schemes. It is represented as actual vrail-comp * 100. qcom,util-levels: Array of tuples that represent a bandwidth threshold and util factor to be used uptil the given threshold. qcom,bus-type: Parameter that represents the bus type such as BIMC or NOC. Typically these optional properties are used for devices that represent fabric devices. Loading Loading @@ -148,6 +153,9 @@ Example: label = "fab-snoc"; qcom,fab-dev; qcom,bypass-qos-prg; qcom,agg-scheme = <SCHEME_1>; qcom,util-levels = <450000 133>, <750000 154>; qcom,base-name = "snoc-base"; qcom,base-offset = <0x7000>; qcom,qos-off = <0x1000>; Loading @@ -166,6 +174,8 @@ Example: mm_int_bimc: mm-int-bimc { cell-id = <10003>; label = "mm-int-bimc"; qcom,util-fact = <154>; qcom,vrail-comp = <100>; qcom,ap-owned; qcom,connections = <&snoc_bimc_1_mas>; qcom,bus-dev = <&fab_snoc>; Loading
drivers/platform/msm/msm_bus/msm_bus_adhoc.h +17 −6 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ struct nodebw { uint64_t last_sum_ab; uint64_t max_ib; uint64_t cur_clk_hz; uint32_t util_used; uint32_t vrail_used; }; struct msm_bus_fab_device_type { Loading @@ -60,8 +62,6 @@ struct msm_bus_fab_device_type { uint32_t base_offset; uint32_t qos_freq; uint32_t qos_off; uint32_t util_fact; uint32_t vrail_comp; struct msm_bus_noc_ops noc_ops; enum msm_bus_hw_sel bus_type; bool bypass_qos_prg; Loading @@ -83,6 +83,20 @@ struct qos_params_type { u64 bw_buffer; }; struct node_util_levels_type { uint64_t threshold; uint32_t util_fact; }; struct node_agg_params_type { uint32_t agg_scheme; uint32_t num_aggports; unsigned int buswidth; uint32_t vrail_comp; uint32_t num_util_levels; struct node_util_levels_type *util_levels; }; struct msm_bus_node_info_type { const char *name; unsigned int id; Loading @@ -103,13 +117,10 @@ struct msm_bus_node_info_type { struct device **black_connections; unsigned int bus_device_id; struct device *bus_device; unsigned int buswidth; struct rule_update_path_info rule; uint64_t lim_bw; uint32_t util_fact; uint32_t vrail_comp; uint32_t num_aggports; bool defer_qos; struct node_agg_params_type agg_params; }; struct msm_bus_node_device_type { Loading
drivers/platform/msm/msm_bus/msm_bus_arb_adhoc.c +166 −35 Original line number Diff line number Diff line Loading @@ -395,68 +395,197 @@ exit_getpath: return first_hop; } static uint64_t arbitrate_bus_req(struct msm_bus_node_device_type *bus_dev, int ctx) static uint64_t scheme1_agg_scheme(struct msm_bus_node_device_type *bus_dev, struct msm_bus_node_device_type *fab_dev, int ctx) { int i; uint64_t max_ib = 0; uint64_t sum_ab = 0; uint64_t max_ib; uint64_t sum_ab; uint64_t bw_max_hz; struct msm_bus_node_device_type *fab_dev = NULL; uint32_t util_fact = 0; uint32_t vrail_comp = 0; struct node_util_levels_type *utils; int i; int num_util_levels; /* Find max ib */ for (i = 0; i < bus_dev->num_lnodes; i++) { max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]); sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; /* * Account for Util factor and vrail comp. * Util factor is picked according to the current sum(AB) for this * node and for this context. * Vrail comp is fixed for the entire performance range. * They default to 100 if absent. * * The aggregated clock is computed as: * Freq_hz = max((sum(ab) * util_fact)/num_chan, max(ib)/vrail_comp) * / bus-width */ if (bus_dev->node_info->agg_params.num_util_levels) { utils = bus_dev->node_info->agg_params.util_levels; num_util_levels = bus_dev->node_info->agg_params.num_util_levels; } else { utils = fab_dev->node_info->agg_params.util_levels; num_util_levels = fab_dev->node_info->agg_params.num_util_levels; } bus_dev->node_bw[ctx].sum_ab = sum_ab; bus_dev->node_bw[ctx].max_ib = max_ib; sum_ab = bus_dev->node_bw[ctx].sum_ab; max_ib = bus_dev->node_bw[ctx].max_ib; for (i = 0; i < num_util_levels; i++) { if (sum_ab < utils[i].threshold) { util_fact = utils[i].util_fact; break; } } if (i == num_util_levels) util_fact = utils[(num_util_levels - 1)].util_fact; vrail_comp = bus_dev->node_info->agg_params.vrail_comp ? bus_dev->node_info->agg_params.vrail_comp : fab_dev->node_info->agg_params.vrail_comp; bus_dev->node_bw[ctx].vrail_used = vrail_comp; bus_dev->node_bw[ctx].util_used = util_fact; if (util_fact && (util_fact != 100)) { sum_ab *= util_fact; sum_ab = msm_bus_div64(100, sum_ab); } if (vrail_comp && (vrail_comp != 100)) { max_ib *= 100; max_ib = msm_bus_div64(vrail_comp, max_ib); } /* Account for multiple channels if any */ if (bus_dev->node_info->agg_params.num_aggports > 1) sum_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, sum_ab); if (!bus_dev->node_info->agg_params.buswidth) { MSM_BUS_WARN("No bus width found for %d. Using default\n", bus_dev->node_info->id); bus_dev->node_info->agg_params.buswidth = 8; } bw_max_hz = max(max_ib, sum_ab); bw_max_hz = msm_bus_div64(bus_dev->node_info->agg_params.buswidth, bw_max_hz); return bw_max_hz; } static uint64_t legacy_agg_scheme(struct msm_bus_node_device_type *bus_dev, struct msm_bus_node_device_type *fab_dev, int ctx) { uint64_t max_ib; uint64_t sum_ab; uint64_t bw_max_hz; uint32_t util_fact = 0; uint32_t vrail_comp = 0; /* * Account for Util factor and vrail comp. The new aggregation * formula is: * Util_fact and vrail comp are obtained from fabric/Node's dts * properties and are fixed for the entire performance range. * They default to 100 if absent. * * The clock frequency is computed as: * Freq_hz = max((sum(ab) * util_fact)/num_chan, max(ib)/vrail_comp) * / bus-width * util_fact and vrail comp are obtained from fabric/Node's dts * properties. * They default to 100 if absent. */ fab_dev = bus_dev->node_info->bus_device->platform_data; /* Don't do this for virtual fabrics */ if (fab_dev && fab_dev->fabdev) { util_fact = bus_dev->node_info->util_fact ? bus_dev->node_info->util_fact : fab_dev->fabdev->util_fact; vrail_comp = bus_dev->node_info->vrail_comp ? bus_dev->node_info->vrail_comp : fab_dev->fabdev->vrail_comp; util_fact = fab_dev->node_info->agg_params.util_levels[0].util_fact; vrail_comp = fab_dev->node_info->agg_params.vrail_comp; if (bus_dev->node_info->agg_params.num_util_levels) util_fact = bus_dev->node_info->agg_params.util_levels[0].util_fact ? bus_dev->node_info->agg_params.util_levels[0].util_fact : util_fact; vrail_comp = bus_dev->node_info->agg_params.vrail_comp ? bus_dev->node_info->agg_params.vrail_comp : vrail_comp; bus_dev->node_bw[ctx].vrail_used = vrail_comp; bus_dev->node_bw[ctx].util_used = util_fact; sum_ab = bus_dev->node_bw[ctx].sum_ab; max_ib = bus_dev->node_bw[ctx].max_ib; if (util_fact && (util_fact != 100)) { sum_ab *= util_fact; sum_ab = msm_bus_div64(100, sum_ab); } if (vrail_comp && (vrail_comp != 100)) { max_ib *= 100; max_ib = msm_bus_div64(vrail_comp, max_ib); } /* Account for multiple channels if any */ if (bus_dev->node_info->num_aggports > 1) sum_ab = msm_bus_div64(bus_dev->node_info->num_aggports, if (bus_dev->node_info->agg_params.num_aggports > 1) sum_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, sum_ab); if (!bus_dev->node_info->buswidth) { if (!bus_dev->node_info->agg_params.buswidth) { MSM_BUS_WARN("No bus width found for %d. Using default\n", bus_dev->node_info->id); bus_dev->node_info->buswidth = 8; bus_dev->node_info->agg_params.buswidth = 8; } bw_max_hz = max(max_ib, sum_ab); bw_max_hz = msm_bus_div64(bus_dev->node_info->buswidth, bw_max_hz = msm_bus_div64(bus_dev->node_info->agg_params.buswidth, bw_max_hz); return bw_max_hz; } static uint64_t aggregate_bus_req(struct msm_bus_node_device_type *bus_dev, int ctx) { uint64_t bw_hz = 0; int i; struct msm_bus_node_device_type *fab_dev = NULL; uint32_t agg_scheme; uint64_t max_ib = 0; uint64_t sum_ab = 0; if (!bus_dev || !bus_dev->node_info->bus_device->platform_data) { MSM_BUS_ERR("Bus node pointer is Invalid"); goto exit_agg_bus_req; } fab_dev = bus_dev->node_info->bus_device->platform_data; for (i = 0; i < bus_dev->num_lnodes; i++) { max_ib = max(max_ib, bus_dev->lnode_list[i].lnode_ib[ctx]); sum_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; } bus_dev->node_bw[ctx].sum_ab = sum_ab; bus_dev->node_bw[ctx].max_ib = max_ib; if (bus_dev->node_info->agg_params.agg_scheme != AGG_SCHEME_NONE) agg_scheme = bus_dev->node_info->agg_params.agg_scheme; else agg_scheme = fab_dev->node_info->agg_params.agg_scheme; switch (agg_scheme) { case AGG_SCHEME_1: bw_hz = scheme1_agg_scheme(bus_dev, fab_dev, ctx); break; case AGG_SCHEME_LEG: bw_hz = legacy_agg_scheme(bus_dev, fab_dev, ctx); break; default: panic("Invalid Bus aggregation scheme"); } exit_agg_bus_req: return bw_hz; } static void del_inp_list(struct list_head *list) { struct rule_update_path_info *rule_node; Loading Loading @@ -519,8 +648,10 @@ static uint64_t get_node_aggab(struct msm_bus_node_device_type *bus_dev) for (i = 0; i < bus_dev->num_lnodes; i++) agg_ab += bus_dev->lnode_list[i].lnode_ab[ctx]; if (bus_dev->node_info->num_aggports > 1) agg_ab = msm_bus_div64(bus_dev->node_info->num_aggports, if (bus_dev->node_info->agg_params.num_aggports > 1) agg_ab = msm_bus_div64( bus_dev->node_info->agg_params.num_aggports, agg_ab); max_agg_ab = max(max_agg_ab, agg_ab); Loading Loading @@ -606,7 +737,7 @@ static int update_path(int src, int dest, uint64_t act_req_ib, for (i = 0; i < NUM_CTX; i++) dev_info->node_bw[i].cur_clk_hz = arbitrate_bus_req(dev_info, i); aggregate_bus_req(dev_info, i); /* Start updating the clocks at the first hop. * Its ok to figure out the aggregated Loading
drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +2 −2 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is Mree software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -198,7 +198,7 @@ static int msm_bus_floor_init_dev(struct device *fab_dev, bus_node->node_info = node_info; bus_node->ap_owned = true; bus_node->node_info->bus_device = fab_dev; bus_node->node_info->buswidth = 8; bus_node->node_info->agg_params.buswidth = 8; dev->platform_data = bus_node; dev->bus = &msm_bus_type; Loading
drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c +39 −47 Original line number Diff line number Diff line Loading @@ -25,41 +25,6 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data); ssize_t vrail_show(struct device *dev, struct device_attribute *attr, char *buf) { struct msm_bus_node_info_type *node_info = NULL; struct msm_bus_node_device_type *bus_node = NULL; bus_node = dev->platform_data; if (!bus_node) return -EINVAL; node_info = bus_node->node_info; return snprintf(buf, PAGE_SIZE, "%u", node_info->vrail_comp); } ssize_t vrail_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct msm_bus_node_info_type *node_info = NULL; struct msm_bus_node_device_type *bus_node = NULL; int ret = 0; bus_node = dev->platform_data; if (!bus_node) return -EINVAL; node_info = bus_node->node_info; ret = sscanf(buf, "%u", &node_info->vrail_comp); if (ret != 1) return -EINVAL; return count; } DEVICE_ATTR(vrail, 0600, vrail_show, vrail_store); ssize_t bw_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading Loading @@ -92,17 +57,29 @@ ssize_t bw_show(struct device *dev, struct device_attribute *attr, bus_node->lnode_list[i].lnode_ab[DUAL_CTX]); } off += scnprintf((buf + off), PAGE_SIZE, "Max_Act_IB %llu Sum_Act_AB %llu\nMax_Slp_IB %llu Sum_Slp_AB %llu\n", "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", bus_node->node_bw[ACTIVE_CTX].max_ib, bus_node->node_bw[ACTIVE_CTX].sum_ab, bus_node->node_bw[ACTIVE_CTX].util_used, bus_node->node_bw[ACTIVE_CTX].vrail_used); off += scnprintf((buf + off), PAGE_SIZE, "Max_Slp_IB %llu Sum_Slp_AB %llu Slp_Util_fact %d Slp_Vrail_comp %d\n", bus_node->node_bw[DUAL_CTX].max_ib, bus_node->node_bw[DUAL_CTX].sum_ab); bus_node->node_bw[DUAL_CTX].sum_ab, bus_node->node_bw[DUAL_CTX].util_used, bus_node->node_bw[DUAL_CTX].vrail_used); trace_printk( "Max_Act_IB %llu Sum_Act_AB %llu\nMax_Slp_IB %llu Sum_Slp_AB %llu\n", "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n", bus_node->node_bw[ACTIVE_CTX].max_ib, bus_node->node_bw[ACTIVE_CTX].sum_ab, bus_node->node_bw[ACTIVE_CTX].util_used, bus_node->node_bw[ACTIVE_CTX].vrail_used); trace_printk( "Max_Slp_IB %llu Sum_Slp_AB %lluSlp_Util_fact %d Slp_Vrail_comp %d\n", bus_node->node_bw[DUAL_CTX].max_ib, bus_node->node_bw[DUAL_CTX].sum_ab); bus_node->node_bw[DUAL_CTX].sum_ab, bus_node->node_bw[DUAL_CTX].util_used, bus_node->node_bw[DUAL_CTX].vrail_used); return off; } Loading Loading @@ -909,8 +886,6 @@ static int msm_bus_fabric_init(struct device *dev, fabdev->qos_freq = pdata->fabdev->qos_freq; fabdev->bus_type = pdata->fabdev->bus_type; fabdev->bypass_qos_prg = pdata->fabdev->bypass_qos_prg; fabdev->util_fact = pdata->fabdev->util_fact; fabdev->vrail_comp = pdata->fabdev->vrail_comp; msm_bus_fab_init_noc_ops(node_dev); fabdev->qos_base = devm_ioremap(dev, Loading Loading @@ -1020,8 +995,6 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->num_connections = pdata_node_info->num_connections; node_info->num_blist = pdata_node_info->num_blist; node_info->num_qports = pdata_node_info->num_qports; node_info->num_aggports = pdata_node_info->num_aggports; node_info->buswidth = pdata_node_info->buswidth; node_info->virt_dev = pdata_node_info->virt_dev; node_info->is_fab_dev = pdata_node_info->is_fab_dev; node_info->qos_params.mode = pdata_node_info->qos_params.mode; Loading @@ -1036,8 +1009,28 @@ static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata, node_info->qos_params.thmp = pdata_node_info->qos_params.thmp; node_info->qos_params.ws = pdata_node_info->qos_params.ws; node_info->qos_params.bw_buffer = pdata_node_info->qos_params.bw_buffer; node_info->util_fact = pdata_node_info->util_fact; node_info->vrail_comp = pdata_node_info->vrail_comp; node_info->agg_params.buswidth = pdata_node_info->agg_params.buswidth; node_info->agg_params.agg_scheme = pdata_node_info->agg_params.agg_scheme; node_info->agg_params.vrail_comp = pdata_node_info->agg_params.vrail_comp; node_info->agg_params.num_aggports = pdata_node_info->agg_params.num_aggports; node_info->agg_params.num_util_levels = pdata_node_info->agg_params.num_util_levels; node_info->agg_params.util_levels = devm_kzalloc(bus_dev, sizeof(struct node_util_levels_type) * node_info->agg_params.num_util_levels, GFP_KERNEL); if (!node_info->agg_params.util_levels) { MSM_BUS_ERR("%s: Agg util level alloc failed\n", __func__); ret = -ENOMEM; goto exit_copy_node_info; } memcpy(node_info->agg_params.util_levels, pdata_node_info->agg_params.util_levels, sizeof(struct node_util_levels_type) * pdata_node_info->agg_params.num_util_levels); node_info->dev_connections = devm_kzalloc(bus_dev, sizeof(struct device *) * Loading Loading @@ -1181,7 +1174,6 @@ static struct device *msm_bus_device_init( bus_dev = NULL; goto exit_device_init; } device_create_file(bus_dev, &dev_attr_vrail); device_create_file(bus_dev, &dev_attr_bw); exit_device_init: Loading Loading @@ -1271,7 +1263,7 @@ static int msm_bus_node_debug(struct device *bus_dev, void *data) } MSM_BUS_DBG("Device = %d buswidth %u", bus_node->node_info->id, bus_node->node_info->buswidth); bus_node->node_info->agg_params.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 *) Loading