mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 07:37:31 -04:00
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: Junjie Wu <junjiew@codeaurora.org> [avajid@codeaurora.org: made minor styling changes] Signed-off-by: Amir Vajid <avajid@codeaurora.org>
This commit is contained in:
parent
b29a2f00d3
commit
939d572b12
2 changed files with 25 additions and 32 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue