Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4820a359 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: qcom: rpmh: Avoid race when setting solver mode"

parents febc2a86 479682d4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ struct rpmh_ctrlr {
 * @base:       start address of the RSC's DRV registers
 * @tcs_base:   start address of the TCS registers in this controller
 * @id:         instance id in the controller (Direct Resource Voter)
 * @in_solver_mode: Controller is in solver mode
 * @num_tcs:    number of TCSes in this DRV
 * @tcs:        TCS groups
 * @tcs_in_use: s/w state of the TCS
@@ -100,6 +101,7 @@ struct rsc_drv {
	void __iomem *base;
	void __iomem *tcs_base;
	int id;
	bool in_solver_mode;
	int num_tcs;
	struct tcs_group tcs[TCS_TYPE_NR];
	DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
@@ -116,6 +118,7 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
int rpmh_rsc_invalidate(struct rsc_drv *drv);
bool rpmh_rsc_ctrlr_is_idle(struct rsc_drv *drv);
int rpmh_rsc_write_pdc_data(struct rsc_drv *drv, const struct tcs_request *msg);
void rpmh_rsc_mode_solver_set(struct rsc_drv *drv, bool enable);

void rpmh_tx_done(const struct tcs_request *msg, int r);

+29 −0
Original line number Diff line number Diff line
@@ -388,6 +388,10 @@ static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
		return PTR_ERR(tcs);

	spin_lock(&drv->lock);
	if (msg->state == RPMH_ACTIVE_ONLY_STATE && drv->in_solver_mode) {
		ret = -EINVAL;
		goto done_write;
	}
	/*
	 * The h/w does not like if we send a request to the same address,
	 * when one is already in-flight or being processed.
@@ -526,6 +530,30 @@ static int tcs_ctrl_write(struct rsc_drv *drv, const struct tcs_request *msg)
	return ret;
}

/**
 *  rpmh_rsc_mode_solver_set: Enable/disable solver mode
 *
 *  @drv: The controller
 *
 *  enable: boolean state to be set - true/false
 */
void rpmh_rsc_mode_solver_set(struct rsc_drv *drv, bool enable)
{
	int m;
	struct tcs_group *tcs = get_tcs_of_type(drv, ACTIVE_TCS);

again:
	spin_lock(&drv->lock);
	for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) {
		if (!tcs_is_free(drv, m)) {
			spin_unlock(&drv->lock);
			goto again;
		}
	}
	drv->in_solver_mode = enable;
	spin_unlock(&drv->lock);
}

/**
 *  rpmh_rsc_ctrlr_is_idle: Check if any of the AMCs are busy.
 *
@@ -818,6 +846,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
		return ret;

	spin_lock_init(&drv->lock);
	drv->in_solver_mode = false;
	bitmap_zero(drv->tcs_in_use, MAX_TCS_NR);

	irq = platform_get_irq(pdev, drv->id);
+6 −14
Original line number Diff line number Diff line
@@ -78,14 +78,13 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)

static int check_ctrlr_state(struct rpmh_ctrlr *ctrlr, enum rpmh_state state)
{
	unsigned long flags;
	int ret = 0;

	/* Do not allow setting active votes when in solver mode */
	spin_lock_irqsave(&ctrlr->cache_lock, flags);
	spin_lock(&ctrlr->cache_lock);
	if (ctrlr->in_solver_mode && state == RPMH_ACTIVE_ONLY_STATE)
		ret = -EBUSY;
	spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
	spin_unlock(&ctrlr->cache_lock);

	return ret;
}
@@ -103,18 +102,11 @@ static int check_ctrlr_state(struct rpmh_ctrlr *ctrlr, enum rpmh_state state)
int rpmh_mode_solver_set(const struct device *dev, bool enable)
{
	struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
	unsigned long flags;

	for (;;) {
		spin_lock_irqsave(&ctrlr->cache_lock, flags);
		if (rpmh_rsc_ctrlr_is_idle(ctrlr_to_drv(ctrlr))) {
	spin_lock(&ctrlr->cache_lock);
	rpmh_rsc_mode_solver_set(ctrlr_to_drv(ctrlr), enable);
	ctrlr->in_solver_mode = enable;
			spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
			break;
		}
		spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
		udelay(10);
	}
	spin_unlock(&ctrlr->cache_lock);

	return 0;
}