diff --git a/drivers/interconnect/qcom/bcm-voter.c b/drivers/interconnect/qcom/bcm-voter.c index 8300b8df4560..8b176a6b134f 100644 --- a/drivers/interconnect/qcom/bcm-voter.c +++ b/drivers/interconnect/qcom/bcm-voter.c @@ -55,34 +55,44 @@ static int cmp_vcd(void *priv, struct list_head *a, struct list_head *b) return 1; } +static u64 bcm_div(u64 num, u64 base) +{ + /* Ensure that small votes aren't lost. */ + if (num && num < base) + return 1; + + return num / base; +} + static void bcm_aggregate(struct qcom_icc_bcm *bcm, bool init) { + struct qcom_icc_node *node; size_t i, bucket; u64 agg_avg[QCOM_ICC_NUM_BUCKETS] = {0}; u64 agg_peak[QCOM_ICC_NUM_BUCKETS] = {0}; u64 temp; + u32 bcm_width, bcm_unit; + + bcm_width = le16_to_cpu(bcm->aux_data.width); + bcm_unit = le32_to_cpu(bcm->aux_data.unit); for (bucket = 0; bucket < QCOM_ICC_NUM_BUCKETS; bucket++) { for (i = 0; i < bcm->num_nodes; i++) { - temp = bcm->nodes[i]->sum_avg[bucket] * - le16_to_cpu(bcm->aux_data.width); - do_div(temp, bcm->nodes[i]->buswidth * - bcm->nodes[i]->channels); + node = bcm->nodes[i]; + temp = bcm_div(node->sum_avg[bucket] * bcm_width, + node->buswidth * node->channels); agg_avg[bucket] = max(agg_avg[bucket], temp); - temp = bcm->nodes[i]->max_peak[bucket] * - le16_to_cpu(bcm->aux_data.width); - do_div(temp, bcm->nodes[i]->buswidth); + temp = bcm_div(node->max_peak[bucket] * bcm_width, + node->buswidth); agg_peak[bucket] = max(agg_peak[bucket], temp); } temp = agg_avg[bucket] * bcm->vote_scale; - do_div(temp, le32_to_cpu(bcm->aux_data.unit)); - bcm->vote_x[bucket] = temp; + bcm->vote_x[bucket] = bcm_div(temp, bcm_unit); temp = agg_peak[bucket] * bcm->vote_scale; - do_div(temp, le32_to_cpu(bcm->aux_data.unit)); - bcm->vote_y[bucket] = temp; + bcm->vote_y[bucket] = bcm_div(temp, bcm_unit); } if (bcm->keepalive) {