[PATCH v2 1/8] drivers/perf: hisi: Refactor code for more uncore PMUs

Shaokun Zhang zhangshaokun at hisilicon.com
Wed Feb 3 22:38:38 EST 2021


Hi Mark,

在 2021/2/3 20:53, Mark Rutland 写道:
> On Wed, Feb 03, 2021 at 03:51:01PM +0800, Shaokun Zhang wrote:
>> On HiSilicon uncore PMU drivers, interrupt handling function and interrupt
>> registration function are very similar in differents PMU modules. Let's
>> refactor the frame, use a callback function for the HW accessors.
> 
> It would be helpful if the commit message could briefly elaborate on
> the refactoring, e.g.
> 
> It would be helpful if the commit message could briefly explain the
> refactoring, e.g.

Agree,

> 
> | Two new callbacks are added:
> |
> | * hisi_uncore_ops::get_int_status returns a bitmap of events which
> |   have overflowed and raised an interrupt
> |
> | * hisi_uncore_ops::clear_int_status clears the overflow status for a
> |   specific event
> |
> | ... and are used by a common IRQ handler, hisi_uncore_pmu_isr().
> 

Ok, I will update these in next version,

> The refactoring itself looks good to me.

Thanks,

> 
> I also see that sanity-checks are removed from the read_counter() and
> write_counter() functions, but the commit message doesn't mention that
> at all. It looks like that should be a separate change.

Oh, I will do one separate patch before this refactor code, the later
new drivers need this.

Cheers,
Shaokun

> 
> Thanks,
> Mark.
> 
>>
>> Cc: Mark Rutland <mark.rutland at arm.com>
>> Cc: Will Deacon <will at kernel.org>
>> Cc: John Garry <john.garry at huawei.com>
>> Cc: Jonathan Cameron <Jonathan.Cameron at huawei.com>
>> Reviewed-by: John Garry <john.garry at huawei.com>
>> Co-developed-by: Qi Liu <liuqi115 at huawei.com>
>> Signed-off-by: Qi Liu <liuqi115 at huawei.com>
>> Signed-off-by: Shaokun Zhang <zhangshaokun at hisilicon.com>
>> ---
>>  drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 79 ++++-----------------------
>>  drivers/perf/hisilicon/hisi_uncore_hha_pmu.c  | 77 +++-----------------------
>>  drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c  | 77 +++-----------------------
>>  drivers/perf/hisilicon/hisi_uncore_pmu.c      | 68 ++++++++++++++++++++++-
>>  drivers/perf/hisilicon/hisi_uncore_pmu.h      |  6 +-
>>  5 files changed, 100 insertions(+), 207 deletions(-)
>>
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
>> index ac1a8c120a00..7f7827cd54d7 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
>> +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
>> @@ -14,7 +14,6 @@
>>  #include <linux/interrupt.h>
>>  #include <linux/irq.h>
>>  #include <linux/list.h>
>> -#include <linux/platform_device.h>
>>  #include <linux/smp.h>
>>  
>>  #include "hisi_uncore_pmu.h"
>> @@ -65,29 +64,15 @@ static u32 hisi_ddrc_pmu_get_counter_offset(int cntr_idx)
>>  static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu,
>>  				      struct hw_perf_event *hwc)
>>  {
>> -	/* Use event code as counter index */
>> -	u32 idx = GET_DDRC_EVENTID(hwc);
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) {
>> -		dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return 0;
>> -	}
>> -
>> -	return readl(ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx));
>> +	return readl(ddrc_pmu->base +
>> +		     hisi_ddrc_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu,
>>  					struct hw_perf_event *hwc, u64 val)
>>  {
>> -	u32 idx = GET_DDRC_EVENTID(hwc);
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) {
>> -		dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return;
>> -	}
>> -
>>  	writel((u32)val,
>> -	       ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx));
>> +	       ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  /*
>> @@ -179,60 +164,14 @@ static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu,
>>  	writel(val, ddrc_pmu->base + DDRC_INT_MASK);
>>  }
>>  
>> -static irqreturn_t hisi_ddrc_pmu_isr(int irq, void *dev_id)
>> +static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu)
>>  {
>> -	struct hisi_pmu *ddrc_pmu = dev_id;
>> -	struct perf_event *event;
>> -	unsigned long overflown;
>> -	int idx;
>> -
>> -	/* Read the DDRC_INT_STATUS register */
>> -	overflown = readl(ddrc_pmu->base + DDRC_INT_STATUS);
>> -	if (!overflown)
>> -		return IRQ_NONE;
>> -
>> -	/*
>> -	 * Find the counter index which overflowed if the bit was set
>> -	 * and handle it
>> -	 */
>> -	for_each_set_bit(idx, &overflown, DDRC_NR_COUNTERS) {
>> -		/* Write 1 to clear the IRQ status flag */
>> -		writel((1 << idx), ddrc_pmu->base + DDRC_INT_CLEAR);
>> -
>> -		/* Get the corresponding event struct */
>> -		event = ddrc_pmu->pmu_events.hw_events[idx];
>> -		if (!event)
>> -			continue;
>> -
>> -		hisi_uncore_pmu_event_update(event);
>> -		hisi_uncore_pmu_set_event_period(event);
>> -	}
>> -
>> -	return IRQ_HANDLED;
>> +	return readl(ddrc_pmu->base + DDRC_INT_STATUS);
>>  }
>>  
>> -static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu,
>> -				  struct platform_device *pdev)
>> +static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, int idx)
>>  {
>> -	int irq, ret;
>> -
>> -	/* Read and init IRQ */
>> -	irq = platform_get_irq(pdev, 0);
>> -	if (irq < 0)
>> -		return irq;
>> -
>> -	ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr,
>> -			       IRQF_NOBALANCING | IRQF_NO_THREAD,
>> -			       dev_name(&pdev->dev), ddrc_pmu);
>> -	if (ret < 0) {
>> -		dev_err(&pdev->dev,
>> -			"Fail to request IRQ:%d ret:%d\n", irq, ret);
>> -		return ret;
>> -	}
>> -
>> -	ddrc_pmu->irq = irq;
>> -
>> -	return 0;
>> +	writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR);
>>  }
>>  
>>  static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = {
>> @@ -342,6 +281,8 @@ static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = {
>>  	.disable_counter_int	= hisi_ddrc_pmu_disable_counter_int,
>>  	.write_counter		= hisi_ddrc_pmu_write_counter,
>>  	.read_counter		= hisi_ddrc_pmu_read_counter,
>> +	.get_int_status		= hisi_ddrc_pmu_get_int_status,
>> +	.clear_int_status	= hisi_ddrc_pmu_clear_int_status,
>>  };
>>  
>>  static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
>> @@ -353,7 +294,7 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = hisi_ddrc_pmu_init_irq(ddrc_pmu, pdev);
>> +	ret = hisi_uncore_pmu_init_irq(ddrc_pmu, pdev);
>>  	if (ret)
>>  		return ret;
>>  
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
>> index 3402f1a395a8..667eebddcc82 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
>> +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
>> @@ -14,7 +14,6 @@
>>  #include <linux/interrupt.h>
>>  #include <linux/irq.h>
>>  #include <linux/list.h>
>> -#include <linux/platform_device.h>
>>  #include <linux/smp.h>
>>  
>>  #include "hisi_uncore_pmu.h"
>> @@ -51,29 +50,15 @@ static u32 hisi_hha_pmu_get_counter_offset(int cntr_idx)
>>  static u64 hisi_hha_pmu_read_counter(struct hisi_pmu *hha_pmu,
>>  				     struct hw_perf_event *hwc)
>>  {
>> -	u32 idx = hwc->idx;
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) {
>> -		dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return 0;
>> -	}
>> -
>>  	/* Read 64 bits and like L3C, top 16 bits are RAZ */
>> -	return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx));
>> +	return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  static void hisi_hha_pmu_write_counter(struct hisi_pmu *hha_pmu,
>>  				       struct hw_perf_event *hwc, u64 val)
>>  {
>> -	u32 idx = hwc->idx;
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) {
>> -		dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return;
>> -	}
>> -
>>  	/* Write 64 bits and like L3C, top 16 bits are WI */
>> -	writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx));
>> +	writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  static void hisi_hha_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx,
>> @@ -169,60 +154,14 @@ static void hisi_hha_pmu_disable_counter_int(struct hisi_pmu *hha_pmu,
>>  	writel(val, hha_pmu->base + HHA_INT_MASK);
>>  }
>>  
>> -static irqreturn_t hisi_hha_pmu_isr(int irq, void *dev_id)
>> +static u32 hisi_hha_pmu_get_int_status(struct hisi_pmu *hha_pmu)
>>  {
>> -	struct hisi_pmu *hha_pmu = dev_id;
>> -	struct perf_event *event;
>> -	unsigned long overflown;
>> -	int idx;
>> -
>> -	/* Read HHA_INT_STATUS register */
>> -	overflown = readl(hha_pmu->base + HHA_INT_STATUS);
>> -	if (!overflown)
>> -		return IRQ_NONE;
>> -
>> -	/*
>> -	 * Find the counter index which overflowed if the bit was set
>> -	 * and handle it
>> -	 */
>> -	for_each_set_bit(idx, &overflown, HHA_NR_COUNTERS) {
>> -		/* Write 1 to clear the IRQ status flag */
>> -		writel((1 << idx), hha_pmu->base + HHA_INT_CLEAR);
>> -
>> -		/* Get the corresponding event struct */
>> -		event = hha_pmu->pmu_events.hw_events[idx];
>> -		if (!event)
>> -			continue;
>> -
>> -		hisi_uncore_pmu_event_update(event);
>> -		hisi_uncore_pmu_set_event_period(event);
>> -	}
>> -
>> -	return IRQ_HANDLED;
>> +	return readl(hha_pmu->base + HHA_INT_STATUS);
>>  }
>>  
>> -static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu,
>> -				 struct platform_device *pdev)
>> +static void hisi_hha_pmu_clear_int_status(struct hisi_pmu *hha_pmu, int idx)
>>  {
>> -	int irq, ret;
>> -
>> -	/* Read and init IRQ */
>> -	irq = platform_get_irq(pdev, 0);
>> -	if (irq < 0)
>> -		return irq;
>> -
>> -	ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr,
>> -			      IRQF_NOBALANCING | IRQF_NO_THREAD,
>> -			      dev_name(&pdev->dev), hha_pmu);
>> -	if (ret < 0) {
>> -		dev_err(&pdev->dev,
>> -			"Fail to request IRQ:%d ret:%d\n", irq, ret);
>> -		return ret;
>> -	}
>> -
>> -	hha_pmu->irq = irq;
>> -
>> -	return 0;
>> +	writel(1 << idx, hha_pmu->base + HHA_INT_CLEAR);
>>  }
>>  
>>  static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = {
>> @@ -354,6 +293,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = {
>>  	.disable_counter_int	= hisi_hha_pmu_disable_counter_int,
>>  	.write_counter		= hisi_hha_pmu_write_counter,
>>  	.read_counter		= hisi_hha_pmu_read_counter,
>> +	.get_int_status		= hisi_hha_pmu_get_int_status,
>> +	.clear_int_status	= hisi_hha_pmu_clear_int_status,
>>  };
>>  
>>  static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
>> @@ -365,7 +306,7 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = hisi_hha_pmu_init_irq(hha_pmu, pdev);
>> +	ret = hisi_uncore_pmu_init_irq(hha_pmu, pdev);
>>  	if (ret)
>>  		return ret;
>>  
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
>> index 7d792435c2aa..831622e0c445 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
>> +++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
>> @@ -14,7 +14,6 @@
>>  #include <linux/interrupt.h>
>>  #include <linux/irq.h>
>>  #include <linux/list.h>
>> -#include <linux/platform_device.h>
>>  #include <linux/smp.h>
>>  
>>  #include "hisi_uncore_pmu.h"
>> @@ -50,29 +49,15 @@ static u32 hisi_l3c_pmu_get_counter_offset(int cntr_idx)
>>  static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu,
>>  				     struct hw_perf_event *hwc)
>>  {
>> -	u32 idx = hwc->idx;
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) {
>> -		dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return 0;
>> -	}
>> -
>>  	/* Read 64-bits and the upper 16 bits are RAZ */
>> -	return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx));
>> +	return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu,
>>  				       struct hw_perf_event *hwc, u64 val)
>>  {
>> -	u32 idx = hwc->idx;
>> -
>> -	if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) {
>> -		dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx);
>> -		return;
>> -	}
>> -
>>  	/* Write 64-bits and the upper 16 bits are WI */
>> -	writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx));
>> +	writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx));
>>  }
>>  
>>  static void hisi_l3c_pmu_write_evtype(struct hisi_pmu *l3c_pmu, int idx,
>> @@ -168,60 +153,14 @@ static void hisi_l3c_pmu_disable_counter_int(struct hisi_pmu *l3c_pmu,
>>  	writel(val, l3c_pmu->base + L3C_INT_MASK);
>>  }
>>  
>> -static irqreturn_t hisi_l3c_pmu_isr(int irq, void *dev_id)
>> +static u32 hisi_l3c_pmu_get_int_status(struct hisi_pmu *l3c_pmu)
>>  {
>> -	struct hisi_pmu *l3c_pmu = dev_id;
>> -	struct perf_event *event;
>> -	unsigned long overflown;
>> -	int idx;
>> -
>> -	/* Read L3C_INT_STATUS register */
>> -	overflown = readl(l3c_pmu->base + L3C_INT_STATUS);
>> -	if (!overflown)
>> -		return IRQ_NONE;
>> -
>> -	/*
>> -	 * Find the counter index which overflowed if the bit was set
>> -	 * and handle it.
>> -	 */
>> -	for_each_set_bit(idx, &overflown, L3C_NR_COUNTERS) {
>> -		/* Write 1 to clear the IRQ status flag */
>> -		writel((1 << idx), l3c_pmu->base + L3C_INT_CLEAR);
>> -
>> -		/* Get the corresponding event struct */
>> -		event = l3c_pmu->pmu_events.hw_events[idx];
>> -		if (!event)
>> -			continue;
>> -
>> -		hisi_uncore_pmu_event_update(event);
>> -		hisi_uncore_pmu_set_event_period(event);
>> -	}
>> -
>> -	return IRQ_HANDLED;
>> +	return readl(l3c_pmu->base + L3C_INT_STATUS);
>>  }
>>  
>> -static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu,
>> -				 struct platform_device *pdev)
>> +static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx)
>>  {
>> -	int irq, ret;
>> -
>> -	/* Read and init IRQ */
>> -	irq = platform_get_irq(pdev, 0);
>> -	if (irq < 0)
>> -		return irq;
>> -
>> -	ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr,
>> -			       IRQF_NOBALANCING | IRQF_NO_THREAD,
>> -			       dev_name(&pdev->dev), l3c_pmu);
>> -	if (ret < 0) {
>> -		dev_err(&pdev->dev,
>> -			"Fail to request IRQ:%d ret:%d\n", irq, ret);
>> -		return ret;
>> -	}
>> -
>> -	l3c_pmu->irq = irq;
>> -
>> -	return 0;
>> +	writel(1 << idx, l3c_pmu->base + L3C_INT_CLEAR);
>>  }
>>  
>>  static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = {
>> @@ -344,6 +283,8 @@ static const struct hisi_uncore_ops hisi_uncore_l3c_ops = {
>>  	.disable_counter_int	= hisi_l3c_pmu_disable_counter_int,
>>  	.write_counter		= hisi_l3c_pmu_write_counter,
>>  	.read_counter		= hisi_l3c_pmu_read_counter,
>> +	.get_int_status		= hisi_l3c_pmu_get_int_status,
>> +	.clear_int_status	= hisi_l3c_pmu_clear_int_status,
>>  };
>>  
>>  static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
>> @@ -355,7 +296,7 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = hisi_l3c_pmu_init_irq(l3c_pmu, pdev);
>> +	ret = hisi_uncore_pmu_init_irq(l3c_pmu, pdev);
>>  	if (ret)
>>  		return ret;
>>  
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
>> index 9dbdc3fc3bb4..82a4ff2bc3ae 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
>> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
>> @@ -132,13 +132,67 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_identifier_attr_show);
>>  static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx)
>>  {
>>  	if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) {
>> -		dev_err(hisi_pmu->dev, "Unsupported event index:%d!\n", idx);
>> +		dev_err(hisi_pmu->dev, "Unsupported event index: %d\n", idx);
>>  		return;
>>  	}
>>  
>>  	clear_bit(idx, hisi_pmu->pmu_events.used_mask);
>>  }
>>  
>> +static irqreturn_t hisi_uncore_pmu_isr(int irq, void *data)
>> +{
>> +	struct hisi_pmu *hisi_pmu = data;
>> +	struct perf_event *event;
>> +	unsigned long overflown;
>> +	int idx;
>> +
>> +	overflown = hisi_pmu->ops->get_int_status(hisi_pmu);
>> +	if (!overflown)
>> +		return IRQ_NONE;
>> +
>> +	/*
>> +	 * Find the counter index which overflowed if the bit was set
>> +	 * and handle it.
>> +	 */
>> +	for_each_set_bit(idx, &overflown, hisi_pmu->num_counters) {
>> +		/* Write 1 to clear the IRQ status flag */
>> +		hisi_pmu->ops->clear_int_status(hisi_pmu, idx);
>> +		/* Get the corresponding event struct */
>> +		event = hisi_pmu->pmu_events.hw_events[idx];
>> +		if (!event)
>> +			continue;
>> +
>> +		hisi_uncore_pmu_event_update(event);
>> +		hisi_uncore_pmu_set_event_period(event);
>> +	}
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
>> +			     struct platform_device *pdev)
>> +{
>> +	int irq, ret;
>> +
>> +	irq = platform_get_irq(pdev, 0);
>> +	if (irq < 0)
>> +		return irq;
>> +
>> +	ret = devm_request_irq(&pdev->dev, irq, hisi_uncore_pmu_isr,
>> +			       IRQF_NOBALANCING | IRQF_NO_THREAD,
>> +			       dev_name(&pdev->dev), hisi_pmu);
>> +	if (ret < 0) {
>> +		dev_err(&pdev->dev,
>> +			"Fail to request IRQ:%d ret:%d\n", irq, ret);
>> +		return ret;
>> +	}
>> +
>> +	hisi_pmu->irq = irq;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(hisi_uncore_pmu_init_irq);
>> +
>>  int hisi_uncore_pmu_event_init(struct perf_event *event)
>>  {
>>  	struct hw_perf_event *hwc = &event->hw;
>> @@ -243,6 +297,12 @@ void hisi_uncore_pmu_event_update(struct perf_event *event)
>>  	struct hisi_pmu *hisi_pmu = to_hisi_pmu(event->pmu);
>>  	struct hw_perf_event *hwc = &event->hw;
>>  	u64 delta, prev_raw_count, new_raw_count;
>> +	u32 idx = hwc->idx;
>> +
>> +	if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) {
>> +		dev_err(hisi_pmu->dev, "Unsupported counter index: %d\n", idx);
>> +		return;
>> +	}
>>  
>>  	do {
>>  		/* Read the count from the counter register */
>> @@ -263,10 +323,16 @@ void hisi_uncore_pmu_start(struct perf_event *event, int flags)
>>  {
>>  	struct hisi_pmu *hisi_pmu = to_hisi_pmu(event->pmu);
>>  	struct hw_perf_event *hwc = &event->hw;
>> +	u32 idx = hwc->idx;
>>  
>>  	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
>>  		return;
>>  
>> +	if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) {
>> +		dev_err(hisi_pmu->dev, "Unsupported counter index: %d.\n", idx);
>> +		return;
>> +	}
>> +
>>  	WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
>>  	hwc->state = 0;
>>  	hisi_uncore_pmu_set_event_period(event);
>> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> index 25b7cbe1f818..aaaf637cc9ea 100644
>> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
>> @@ -16,6 +16,7 @@
>>  #include <linux/kernel.h>
>>  #include <linux/module.h>
>>  #include <linux/perf_event.h>
>> +#include <linux/platform_device.h>
>>  #include <linux/types.h>
>>  
>>  #undef pr_fmt
>> @@ -47,6 +48,8 @@ struct hisi_uncore_ops {
>>  	void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
>>  	void (*start_counters)(struct hisi_pmu *);
>>  	void (*stop_counters)(struct hisi_pmu *);
>> +	u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
>> +	void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
>>  };
>>  
>>  struct hisi_pmu_hwevents {
>> @@ -102,6 +105,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
>>  ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
>>  					     struct device_attribute *attr,
>>  					     char *page);
>> -
>> +int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
>> +			     struct platform_device *pdev);
>>  
>>  #endif /* __HISI_UNCORE_PMU_H__ */
>> -- 
>> 2.7.4
>>
> .
> 



More information about the linux-arm-kernel mailing list