static int __set_power_limit_uw()

in dtpm.c [241:302]


static int __set_power_limit_uw(struct dtpm *dtpm, int cid, u64 power_limit)
{
	struct dtpm *child;
	int ret = 0;
	u64 power;

	/*
	 * A max power limitation means we remove the power limit,
	 * otherwise we set a constraint and flag the dtpm node.
	 */
	if (power_limit == dtpm->power_max) {
		clear_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags);
	} else {
		set_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags);
	}

	pr_debug("Setting power limit for '%s': %llu uW\n",
		 dtpm->zone.name, power_limit);

	/*
	 * Only leaves of the dtpm tree has ops to get/set the power
	 */
	if (dtpm->ops) {
		dtpm->power_limit = dtpm->ops->set_power_uw(dtpm, power_limit);
	} else {
		dtpm->power_limit = 0;

		list_for_each_entry(child, &dtpm->children, sibling) {

			/*
			 * Integer division rounding will inevitably
			 * lead to a different min or max value when
			 * set several times. In order to restore the
			 * initial value, we force the child's min or
			 * max power every time if the constraint is
			 * at the boundaries.
			 */
			if (power_limit == dtpm->power_max) {
				power = child->power_max;
			} else if (power_limit == dtpm->power_min) {
				power = child->power_min;
			} else {
				power = DIV_ROUND_CLOSEST_ULL(
					power_limit * child->weight, 1024);
			}

			pr_debug("Setting power limit for '%s': %llu uW\n",
				 child->zone.name, power);

			ret = __set_power_limit_uw(child, cid, power);
			if (!ret)
				ret = __get_power_limit_uw(child, cid, &power);

			if (ret)
				break;

			dtpm->power_limit += power;
		}
	}

	return ret;
}