diff options
Diffstat (limited to 'drivers/hwtracing/intel_th')
| -rw-r--r-- | drivers/hwtracing/intel_th/intel_th.h | 2 | ||||
| -rw-r--r-- | drivers/hwtracing/intel_th/msu.c | 49 | ||||
| -rw-r--r-- | drivers/hwtracing/intel_th/pci.c | 8 | 
3 files changed, 54 insertions, 5 deletions
| diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 6f4f5486fe6d..5fe694708b7a 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -47,11 +47,13 @@ struct intel_th_output {  /**   * struct intel_th_drvdata - describes hardware capabilities and quirks   * @tscu_enable:	device needs SW to enable time stamping unit + * @multi_is_broken:	device has multiblock mode is broken   * @has_mintctl:	device has interrupt control (MINTCTL) register   * @host_mode_only:	device can only operate in 'host debugger' mode   */  struct intel_th_drvdata {  	unsigned int	tscu_enable        : 1, +			multi_is_broken    : 1,  			has_mintctl        : 1,  			host_mode_only     : 1;  }; diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 255f8f41c8ff..3a77551fb4fc 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -138,6 +138,7 @@ struct msc {  	struct list_head	win_list;  	struct sg_table		single_sgt;  	struct msc_window	*cur_win; +	struct msc_window	*switch_on_unlock;  	unsigned long		nr_pages;  	unsigned long		single_sz;  	unsigned int		single_wrap : 1; @@ -154,10 +155,13 @@ struct msc {  	struct list_head	iter_list; +	bool			stop_on_full; +  	/* config */  	unsigned int		enabled : 1,  				wrap	: 1, -				do_irq	: 1; +				do_irq	: 1, +				multi_is_broken : 1;  	unsigned int		mode;  	unsigned int		burst_len;  	unsigned int		index; @@ -1665,7 +1669,7 @@ static int intel_th_msc_init(struct msc *msc)  {  	atomic_set(&msc->user_count, -1); -	msc->mode = MSC_MODE_MULTI; +	msc->mode = msc->multi_is_broken ? MSC_MODE_SINGLE : MSC_MODE_MULTI;  	mutex_init(&msc->buf_mutex);  	INIT_LIST_HEAD(&msc->win_list);  	INIT_LIST_HEAD(&msc->iter_list); @@ -1717,6 +1721,10 @@ void intel_th_msc_window_unlock(struct device *dev, struct sg_table *sgt)  		return;  	msc_win_set_lockout(win, WIN_LOCKED, WIN_READY); +	if (msc->switch_on_unlock == win) { +		msc->switch_on_unlock = NULL; +		msc_win_switch(msc); +	}  }  EXPORT_SYMBOL_GPL(intel_th_msc_window_unlock); @@ -1757,7 +1765,11 @@ static irqreturn_t intel_th_msc_interrupt(struct intel_th_device *thdev)  	/* next window: if READY, proceed, if LOCKED, stop the trace */  	if (msc_win_set_lockout(next_win, WIN_READY, WIN_INUSE)) { -		schedule_work(&msc->work); +		if (msc->stop_on_full) +			schedule_work(&msc->work); +		else +			msc->switch_on_unlock = next_win; +  		return IRQ_HANDLED;  	} @@ -1877,6 +1889,9 @@ mode_store(struct device *dev, struct device_attribute *attr, const char *buf,  	return -EINVAL;  found: +	if (i == MSC_MODE_MULTI && msc->multi_is_broken) +		return -EOPNOTSUPP; +  	mutex_lock(&msc->buf_mutex);  	ret = 0; @@ -2047,11 +2062,36 @@ win_switch_store(struct device *dev, struct device_attribute *attr,  static DEVICE_ATTR_WO(win_switch); +static ssize_t stop_on_full_show(struct device *dev, +				 struct device_attribute *attr, char *buf) +{ +	struct msc *msc = dev_get_drvdata(dev); + +	return sprintf(buf, "%d\n", msc->stop_on_full); +} + +static ssize_t stop_on_full_store(struct device *dev, +				  struct device_attribute *attr, +				  const char *buf, size_t size) +{ +	struct msc *msc = dev_get_drvdata(dev); +	int ret; + +	ret = kstrtobool(buf, &msc->stop_on_full); +	if (ret) +		return ret; + +	return size; +} + +static DEVICE_ATTR_RW(stop_on_full); +  static struct attribute *msc_output_attrs[] = {  	&dev_attr_wrap.attr,  	&dev_attr_mode.attr,  	&dev_attr_nr_pages.attr,  	&dev_attr_win_switch.attr, +	&dev_attr_stop_on_full.attr,  	NULL,  }; @@ -2083,6 +2123,9 @@ static int intel_th_msc_probe(struct intel_th_device *thdev)  	if (!res)  		msc->do_irq = 1; +	if (INTEL_TH_CAP(to_intel_th(thdev), multi_is_broken)) +		msc->multi_is_broken = 1; +  	msc->index = thdev->id;  	msc->thdev = thdev; diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index 86aa6a46bcba..7ccac74553a6 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -120,6 +120,10 @@ static void intel_th_pci_remove(struct pci_dev *pdev)  	pci_free_irq_vectors(pdev);  } +static const struct intel_th_drvdata intel_th_1x_multi_is_broken = { +	.multi_is_broken	= 1, +}; +  static const struct intel_th_drvdata intel_th_2x = {  	.tscu_enable	= 1,  	.has_mintctl	= 1, @@ -152,7 +156,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = {  	{  		/* Kaby Lake PCH-H */  		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6), -		.driver_data = (kernel_ulong_t)0, +		.driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,  	},  	{  		/* Denverton */ @@ -207,7 +211,7 @@ static const struct pci_device_id intel_th_pci_id_table[] = {  	{  		/* Comet Lake PCH-V */  		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6), -		.driver_data = (kernel_ulong_t)&intel_th_2x, +		.driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,  	},  	{  		/* Ice Lake NNPI */ |