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

Commit 939d572b authored by Junjie Wu's avatar Junjie Wu Committed by Amir Vajid
Browse files

PM / devfreq: cache_hwmon: Move IRQ handling to device drivers



The cache monitoring devices might have more than one IRQ to handle
or might have notifications from other drivers instead of using actual
IRQs. So, refactor the governor to move the IRQ handling to the cache
monitoring device specific drivers and just provide an API that can be
used to request a re-evaluation.

The device specific driver can call this API to request an immediate
re-evaluation whenever the cache request has exceeded the previously
set limit instead of waiting for the periodic update.

Change-Id: Ib2e9f53f95749d659f440739a1b074b5a0d94fd8
Signed-off-by: default avatarJunjie Wu <junjiew@codeaurora.org>
[avajid@codeaurora.org: made minor styling changes]
Signed-off-by: default avatarAmir Vajid <avajid@codeaurora.org>
parent b29a2f00
Loading
Loading
Loading
Loading
+20 −27
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ struct cache_hwmon_node {
	unsigned int		decay_rate;
	unsigned long		prev_mhz;
	ktime_t			prev_ts;
	bool			mon_started;
	struct list_head	list;
	void			*orig_data;
	struct cache_hwmon	*hw;
@@ -154,18 +155,26 @@ static void compute_cache_freq(struct cache_hwmon_node *node,
}

#define TOO_SOON_US	(1 * USEC_PER_MSEC)
static irqreturn_t mon_intr_handler(int irq, void *dev)
int update_cache_hwmon(struct cache_hwmon *hwmon)
{
	struct cache_hwmon_node *node = dev;
	struct devfreq *df = node->hw->df;
	struct cache_hwmon_node *node;
	struct devfreq *df;
	ktime_t ts;
	unsigned int us;
	int ret;

	if (!node->hw->is_valid_irq(node->hw))
		return IRQ_NONE;
	if (!hwmon)
		return -EINVAL;
	df = hwmon->df;
	if (!df)
		return -ENODEV;
	node = df->data;
	if (!node)
		return -ENODEV;
	if (!node->mon_started)
		return -EBUSY;

	dev_dbg(df->dev.parent, "Got interrupt\n");
	dev_dbg(df->dev.parent, "Got update request\n");
	devfreq_monitor_stop(df);

	/*
@@ -187,13 +196,13 @@ static irqreturn_t mon_intr_handler(int irq, void *dev)
		ret = update_devfreq(df);
		if (ret < 0)
			dev_err(df->dev.parent,
				"Unable to update freq on IRQ! (%d)\n", ret);
				"Unable to update freq on req! (%d)\n", ret);
		mutex_unlock(&df->lock);
	}

	devfreq_monitor_start(df);

	return IRQ_HANDLED;
	return 0;
}

static int devfreq_cache_hwmon_get_freq(struct devfreq *df,
@@ -282,16 +291,7 @@ static int start_monitoring(struct devfreq *df)
	}

	devfreq_monitor_start(df);

	if (hw->irq)
		ret = request_threaded_irq(hw->irq, NULL, mon_intr_handler,
			  IRQF_ONESHOT | IRQF_SHARED,
			  "cache_hwmon", node);
	if (ret < 0) {
		dev_err(dev, "Unable to register interrupt handler! (%d)\n",
				ret);
		goto req_irq_fail;
	}
	node->mon_started = true;

	ret = sysfs_create_group(&df->dev.kobj, &dev_attr_group);
	if (ret < 0) {
@@ -302,11 +302,7 @@ static int start_monitoring(struct devfreq *df)
	return 0;

sysfs_fail:
	if (hw->irq) {
		disable_irq(hw->irq);
		free_irq(hw->irq, node);
	}
req_irq_fail:
	node->mon_started = false;
	devfreq_monitor_stop(df);
	hw->stop_hwmon(hw);
err_start:
@@ -322,10 +318,7 @@ static void stop_monitoring(struct devfreq *df)
	struct cache_hwmon *hw = node->hw;

	sysfs_remove_group(&df->dev.kobj, &dev_attr_group);
	if (hw->irq) {
		disable_irq(hw->irq);
		free_irq(hw->irq, node);
	}
	node->mon_started = false;
	devfreq_monitor_stop(df);
	hw->stop_hwmon(hw);
	df->data = node->orig_data;
+5 −5
Original line number Diff line number Diff line
@@ -20,12 +20,9 @@ struct mrps_stats {
 * struct cache_hwmon - devfreq Cache HW monitor info
 * @start_hwmon:	Start the HW monitoring
 * @stop_hwmon:		Stop the HW monitoring
 * @is_valid_irq:	Check whether the IRQ was triggered by the counter
 *			used to monitor cache activity.
 * @meas_mrps_and_set_irq:	Return the measured count and set up the
 *				IRQ to fire if usage exceeds current
 *				measurement by @tol percent.
 * @irq:		IRQ number that corresponds to this HW monitor.
 * @dev:		device that this HW monitor can monitor.
 * @of_node:		OF node of device that this HW monitor can monitor.
 * @df:			Devfreq node that this HW montior is being used
@@ -36,11 +33,9 @@ struct cache_hwmon {
	int			(*start_hwmon)(struct cache_hwmon *hw,
					struct mrps_stats *mrps);
	void			(*stop_hwmon)(struct cache_hwmon *hw);
	bool			(*is_valid_irq)(struct cache_hwmon *hw);
	unsigned long		(*meas_mrps_and_set_irq)(struct cache_hwmon *hw,
					unsigned int tol, unsigned int us,
					struct mrps_stats *mrps);
	int			irq;
	struct device		*dev;
	struct device_node	*of_node;
	struct devfreq		*df;
@@ -48,12 +43,17 @@ struct cache_hwmon {

#ifdef CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON
int register_cache_hwmon(struct device *dev, struct cache_hwmon *hwmon);
int update_cache_hwmon(struct cache_hwmon *hwmon);
#else
static inline int register_cache_hwmon(struct device *dev,
				       struct cache_hwmon *hwmon)
{
	return 0;
}
int update_cache_hwmon(struct cache_hwmon *hwmon)
{
	return 0;
}
#endif

#endif /* _GOVERNOR_CACHE_HWMON_H */