diff --git a/drivers/devfreq/governor_cache_hwmon.c b/drivers/devfreq/governor_cache_hwmon.c index 53fe8f4a75bf..e670ee9e7548 100644 --- a/drivers/devfreq/governor_cache_hwmon.c +++ b/drivers/devfreq/governor_cache_hwmon.c @@ -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; diff --git a/drivers/devfreq/governor_cache_hwmon.h b/drivers/devfreq/governor_cache_hwmon.h index 8c492c58ee41..f78a1d7cd028 100644 --- a/drivers/devfreq/governor_cache_hwmon.h +++ b/drivers/devfreq/governor_cache_hwmon.h @@ -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 */