Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

interconnect: qcom: icc-rpm: Support multiple buckets

The current interconnect rpm driver uses a single aggregate bandwidth to
calculate the clock rates for both active and sleep clocks; therefore,
it has no chance to separate bandwidth requests for these two kinds of
clocks.

This patch studies the implementation from interconnect rpmh driver to
support multiple buckets. The rpmh driver provides three buckets for
AMC, WAKE, and SLEEP; this driver only needs to use WAKE and SLEEP
buckets, but we keep the same way with rpmh driver, this can allow us to
reuse the DT binding and avoid to define duplicated data structures.

This patch introduces two callbacks: qcom_icc_pre_bw_aggregate() is used
to clean up bucket values before aggregate bandwidth requests, and
qcom_icc_bw_aggregate() is to aggregate bandwidth for buckets.

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Link: https://lore.kernel.org/r/20220712015929.2789881-5-leo.yan@linaro.org
Signed-off-by: Georgi Djakov <djakov@kernel.org>

authored by

Leo Yan and committed by
Georgi Djakov
dcbce7b0 ad510e4e

+56 -1
+50 -1
drivers/interconnect/qcom/icc-rpm.c
··· 254 254 return 0; 255 255 } 256 256 257 + /** 258 + * qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests 259 + * @node: icc node to operate on 260 + */ 261 + static void qcom_icc_pre_bw_aggregate(struct icc_node *node) 262 + { 263 + struct qcom_icc_node *qn; 264 + size_t i; 265 + 266 + qn = node->data; 267 + for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { 268 + qn->sum_avg[i] = 0; 269 + qn->max_peak[i] = 0; 270 + } 271 + } 272 + 273 + /** 274 + * qcom_icc_bw_aggregate - aggregate bw for buckets indicated by tag 275 + * @node: node to aggregate 276 + * @tag: tag to indicate which buckets to aggregate 277 + * @avg_bw: new bw to sum aggregate 278 + * @peak_bw: new bw to max aggregate 279 + * @agg_avg: existing aggregate avg bw val 280 + * @agg_peak: existing aggregate peak bw val 281 + */ 282 + static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, 283 + u32 peak_bw, u32 *agg_avg, u32 *agg_peak) 284 + { 285 + size_t i; 286 + struct qcom_icc_node *qn; 287 + 288 + qn = node->data; 289 + 290 + if (!tag) 291 + tag = QCOM_ICC_TAG_ALWAYS; 292 + 293 + for (i = 0; i < QCOM_ICC_NUM_BUCKETS; i++) { 294 + if (tag & BIT(i)) { 295 + qn->sum_avg[i] += avg_bw; 296 + qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw); 297 + } 298 + } 299 + 300 + *agg_avg += avg_bw; 301 + *agg_peak = max_t(u32, *agg_peak, peak_bw); 302 + return 0; 303 + } 304 + 257 305 static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) 258 306 { 259 307 struct qcom_icc_provider *qp; ··· 462 414 INIT_LIST_HEAD(&provider->nodes); 463 415 provider->dev = dev; 464 416 provider->set = qcom_icc_set; 465 - provider->aggregate = icc_std_aggregate; 417 + provider->pre_aggregate = qcom_icc_pre_bw_aggregate; 418 + provider->aggregate = qcom_icc_bw_aggregate; 466 419 provider->xlate_extended = qcom_icc_xlate_extended; 467 420 provider->data = data; 468 421
+6
drivers/interconnect/qcom/icc-rpm.h
··· 6 6 #ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H 7 7 #define __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H 8 8 9 + #include <dt-bindings/interconnect/qcom,icc.h> 10 + 9 11 #define RPM_BUS_MASTER_REQ 0x73616d62 10 12 #define RPM_BUS_SLAVE_REQ 0x766c7362 11 13 ··· 67 65 * @links: an array of nodes where we can go next while traversing 68 66 * @num_links: the total number of @links 69 67 * @buswidth: width of the interconnect between a node and the bus (bytes) 68 + * @sum_avg: current sum aggregate value of all avg bw requests 69 + * @max_peak: current max aggregate value of all peak bw requests 70 70 * @mas_rpm_id: RPM id for devices that are bus masters 71 71 * @slv_rpm_id: RPM id for devices that are bus slaves 72 72 * @qos: NoC QoS setting parameters ··· 79 75 const u16 *links; 80 76 u16 num_links; 81 77 u16 buswidth; 78 + u64 sum_avg[QCOM_ICC_NUM_BUCKETS]; 79 + u64 max_peak[QCOM_ICC_NUM_BUCKETS]; 82 80 int mas_rpm_id; 83 81 int slv_rpm_id; 84 82 struct qcom_icc_qos qos;