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

Commit 6b963ad5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "PM / devfreq: bw_hwmon: Move IRQ handling to device specific drivers"

parents 98c1e6b4 d8b46e28
Loading
Loading
Loading
Loading
+38 −43
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct hwmon_node {
	unsigned long prev_ab;
	unsigned long *dev_ab;
	ktime_t prev_ts;
	bool mon_started;
	struct list_head list;
	void *orig_data;
	struct bw_hwmon *hw;
@@ -140,19 +141,45 @@ static void compute_bw(struct hwmon_node *node, int mbps,
	*freq = (new_bw * 100) / node->io_percent;
}

static struct hwmon_node *find_hwmon_node(struct devfreq *df)
{
	struct hwmon_node *node, *found = NULL;

	mutex_lock(&list_lock);
	list_for_each_entry(node, &hwmon_list, list)
		if (node->hw->dev == df->dev.parent ||
		    node->hw->of_node == df->dev.parent->of_node ||
		    node->gov == df->governor) {
			found = node;
			break;
		}
	mutex_unlock(&list_lock);

	return found;
}

#define TOO_SOON_US	(1 * USEC_PER_MSEC)
static irqreturn_t mon_intr_handler(int irq, void *dev)
int update_bw_hwmon(struct bw_hwmon *hwmon)
{
	struct hwmon_node *node = dev;
	struct devfreq *df = node->hw->df;
	struct devfreq *df;
	struct hwmon_node *node;
	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 = find_hwmon_node(df);
	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);

	/*
@@ -172,30 +199,13 @@ static irqreturn_t mon_intr_handler(int irq, void *dev)
		ret = update_devfreq(df);
		if (ret)
			dev_err(df->dev.parent,
				"Unable to update freq on IRQ!\n");
				"Unable to update freq on request!\n");
		mutex_unlock(&df->lock);
	}

	devfreq_monitor_start(df);

	return IRQ_HANDLED;
}

static struct hwmon_node *find_hwmon_node(struct devfreq *df)
{
	struct hwmon_node *node, *found = NULL;

	mutex_lock(&list_lock);
	list_for_each_entry(node, &hwmon_list, list)
		if (node->hw->dev == df->dev.parent ||
		    node->hw->of_node == df->dev.parent->of_node ||
		    node->gov == df->governor) {
			found = node;
			break;
		}
	mutex_unlock(&list_lock);

	return found;
	return 0;
}

static int start_monitoring(struct devfreq *df)
@@ -236,15 +246,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,
				  "bw_hwmon", node);
	if (ret) {
		dev_err(dev, "Unable to register interrupt handler!\n");
		goto err_req_irq;
	}
	node->mon_started = true;

	ret = sysfs_create_group(&df->dev.kobj, node->attr_grp);
	if (ret)
@@ -253,11 +255,7 @@ static int start_monitoring(struct devfreq *df)
	return 0;

err_sysfs:
	if (hw->irq) {
		disable_irq(hw->irq);
		free_irq(hw->irq, node);
	}
err_req_irq:
	node->mon_started = false;
	devfreq_monitor_stop(df);
	hw->stop_hwmon(hw);
err_start:
@@ -274,10 +272,7 @@ static void stop_monitoring(struct devfreq *df)
	struct bw_hwmon *hw = node->hw;

	sysfs_remove_group(&df->dev.kobj, node->attr_grp);
	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 −2
Original line number Diff line number Diff line
@@ -47,10 +47,8 @@
struct bw_hwmon {
	int (*start_hwmon)(struct bw_hwmon *hw, unsigned long mbps);
	void (*stop_hwmon)(struct bw_hwmon *hw);
	bool (*is_valid_irq)(struct bw_hwmon *hw);
	unsigned long (*meas_bw_and_set_irq)(struct bw_hwmon *hw,
					unsigned int tol, unsigned int us);
	int irq;
	struct device *dev;
	struct device_node *of_node;
	struct devfreq_governor *gov;
@@ -60,12 +58,17 @@ struct bw_hwmon {

#ifdef CONFIG_DEVFREQ_GOV_MSM_BW_HWMON
int register_bw_hwmon(struct device *dev, struct bw_hwmon *hwmon);
int update_bw_hwmon(struct bw_hwmon *hwmon);
#else
static inline int register_bw_hwmon(struct device *dev,
					struct bw_hwmon *hwmon)
{
	return 0;
}
int update_bw_hwmon(struct bw_hwmon *hwmon)
{
	return 0;
}
#endif

#endif /* _GOVERNOR_BW_HWMON_H */
+23 −7
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ static long mon_get_count(int n, u32 start_val)
static u32 bytes_per_beat;
static u32 prev_r_start_val;
static u32 prev_w_start_val;
static int bw_irq;

static void mon_bw_init(void)
{
@@ -200,14 +201,28 @@ static unsigned long meas_bw_and_set_irq(struct bw_hwmon *hw,
	return r_mbps + w_mbps;
}

static bool is_valid_bw_irq(struct bw_hwmon *hw)
static irqreturn_t bwmon_intr_handler(int irq, void *dev)
{
	return mon_overflow(RD_MON) || mon_overflow(WR_MON);
	if (mon_overflow(RD_MON) || mon_overflow(WR_MON)) {
		update_bw_hwmon(dev);
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}

static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)
{
	u32 limit;
	int ret;

	ret = request_threaded_irq(bw_irq, NULL, bwmon_intr_handler,
				  IRQF_ONESHOT | IRQF_SHARED,
				  "bw_hwmon", hw);
	if (ret) {
		pr_err("Unable to register interrupt handler!\n");
		return ret;
	}

	mon_bw_init();
	mon_disable(RD_MON);
@@ -229,6 +244,8 @@ static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)

static void stop_bw_hwmon(struct bw_hwmon *hw)
{
	disable_irq(bw_irq);
	free_irq(bw_irq, hw);
	global_mon_enable(false);
	mon_disable(RD_MON);
	mon_disable(WR_MON);
@@ -243,7 +260,6 @@ static struct devfreq_governor devfreq_gov_cpubw_hwmon = {
static struct bw_hwmon cpubw_hwmon = {
	.start_hwmon = &start_bw_hwmon,
	.stop_hwmon = &stop_bw_hwmon,
	.is_valid_irq = &is_valid_bw_irq,
	.meas_bw_and_set_irq = &meas_bw_and_set_irq,
	.gov = &devfreq_gov_cpubw_hwmon,
};
@@ -372,12 +388,12 @@ static int krait_l2pm_driver_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	int ret, ret2;

	cpubw_hwmon.irq = platform_get_irq(pdev, 0);
	if (cpubw_hwmon.irq < 0) {
	bw_irq = platform_get_irq(pdev, 0);
	if (bw_irq < 0) {
		pr_err("Unable to get IRQ number\n");
		return cpubw_hwmon.irq;
		return bw_irq;
	}
	mrps_hwmon.irq = cpubw_hwmon.irq;
	mrps_hwmon.irq = bw_irq;

	ret = of_property_read_u32(dev->of_node, "qcom,bytes-per-beat",
					&bytes_per_beat);