drivers/interconnect/qcom/icc-rpm.c

Source file repositories/reference/linux-study-clean/drivers/interconnect/qcom/icc-rpm.c

File Facts

System
Linux kernel
Corpus path
drivers/interconnect/qcom/icc-rpm.c
Extension
.c
Size
16819 bytes
Lines
643
Domain
Driver Families
Bucket
drivers/interconnect
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (qn->mas_rpm_id != -1) {
			ret = qcom_icc_rpm_smd_send(rpm_ctx,
						    RPM_BUS_MASTER_REQ,
						    qn->mas_rpm_id,
						    bw_bps);
			if (ret) {
				pr_err("qcom_icc_rpm_smd_send mas %d error %d\n",
				       qn->mas_rpm_id, ret);
				if (ret != -ENXIO || !ignore_enxio)
					return ret;
			}
		}

		if (qn->slv_rpm_id != -1) {
			ret = qcom_icc_rpm_smd_send(rpm_ctx,
						    RPM_BUS_SLAVE_REQ,
						    qn->slv_rpm_id,
						    bw_bps);
			if (ret) {
				pr_err("qcom_icc_rpm_smd_send slv %d error %d\n",
				       qn->slv_rpm_id, ret);
				if (ret != -ENXIO || !ignore_enxio)
					return ret;
			}
		}
	}

	return 0;
}

/**
 * qcom_icc_pre_bw_aggregate - cleans up values before re-aggregate requests
 * @node: icc node to operate on
 */
static void qcom_icc_pre_bw_aggregate(struct icc_node *node)
{
	struct qcom_icc_node *qn;
	size_t i;

	qn = node->data;
	for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
		qn->sum_avg[i] = 0;
		qn->max_peak[i] = 0;
	}
}

/**
 * qcom_icc_bw_aggregate - aggregate bw for buckets indicated by tag
 * @node: node to aggregate
 * @tag: tag to indicate which buckets to aggregate
 * @avg_bw: new bw to sum aggregate
 * @peak_bw: new bw to max aggregate
 * @agg_avg: existing aggregate avg bw val
 * @agg_peak: existing aggregate peak bw val
 */
static int qcom_icc_bw_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
				 u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
	size_t i;
	struct qcom_icc_node *qn;

	qn = node->data;

	if (!tag)
		tag = RPM_ALWAYS_TAG;

	for (i = 0; i < QCOM_SMD_RPM_STATE_NUM; i++) {
		if (tag & BIT(i)) {
			qn->sum_avg[i] += avg_bw;
			qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
		}
	}

	*agg_avg += avg_bw;
	*agg_peak = max_t(u32, *agg_peak, peak_bw);
	return 0;
}

static u64 qcom_icc_calc_rate(struct qcom_icc_provider *qp, struct qcom_icc_node *qn, int ctx)
{
	u64 agg_avg_rate, agg_peak_rate, agg_rate;

	if (qn->channels)
		agg_avg_rate = div_u64(qn->sum_avg[ctx], qn->channels);
	else
		agg_avg_rate = qn->sum_avg[ctx];

	if (qn->ab_coeff) {
		agg_avg_rate = agg_avg_rate * qn->ab_coeff;
		agg_avg_rate = div_u64(agg_avg_rate, 100);

Annotation

Implementation Notes