dmaengine.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v3] dmaengine: idxd: fix wq cleanup of WQCFG registers
       [not found] <161782510285.106717.15904886797025412090.stgit@djiang5-desk3.ch.intel.com>
@ 2021-04-07 19:54 ` Dave Jiang
  0 siblings, 0 replies; only message in thread
From: Dave Jiang @ 2021-04-07 19:54 UTC (permalink / raw)
  To: vkoul; +Cc: Shreenivaas Devarajan, dmaengine


On 4/7/2021 12:52 PM, Dave Jiang wrote:
> A pre-release silicon erratum workaround where wq reset does not clear
> WQCFG registers was leaked into upstream code. Use wq reset command
> instead of blasting the MMIO region. This also address an issue where
> we clobber registers in future devices.
>
> Fixes: da32b28c95a7 ("dmaengine: idxd: cleanup workqueue config after disabling")
> Reported-by: Shreenivaas Devarajan <shreenivaas.devarajan@intel.com>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
> v3:
> - Remove unused vars
> v2:
> - Set IDXD_WQ_DISABLED for internal state after reset.

Forgot to set cc to dmaengine@vger



>
>   drivers/dma/idxd/device.c |   36 +++++++++++++++++++++++++-----------
>   drivers/dma/idxd/idxd.h   |    1 +
>   drivers/dma/idxd/sysfs.c  |    9 ++-------
>   3 files changed, 28 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
> index b8939e7eccfb..eb313e0e0e9b 100644
> --- a/drivers/dma/idxd/device.c
> +++ b/drivers/dma/idxd/device.c
> @@ -276,6 +276,23 @@ void idxd_wq_drain(struct idxd_wq *wq)
>   	idxd_cmd_exec(idxd, IDXD_CMD_DRAIN_WQ, operand, NULL);
>   }
>   
> +void idxd_wq_reset(struct idxd_wq *wq)
> +{
> +	struct idxd_device *idxd = wq->idxd;
> +	struct device *dev = &idxd->pdev->dev;
> +	u32 operand;
> +
> +	if (wq->state != IDXD_WQ_ENABLED) {
> +		dev_dbg(dev, "WQ %d in wrong state: %d\n", wq->id, wq->state);
> +		return;
> +	}
> +
> +	dev_dbg(dev, "Resetting WQ %d\n", wq->id);
> +	operand = BIT(wq->id % 16) | ((wq->id / 16) << 16);
> +	idxd_cmd_exec(idxd, IDXD_CMD_RESET_WQ, operand, NULL);
> +	wq->state = IDXD_WQ_DISABLED;
> +}
> +
>   int idxd_wq_map_portal(struct idxd_wq *wq)
>   {
>   	struct idxd_device *idxd = wq->idxd;
> @@ -357,8 +374,6 @@ int idxd_wq_disable_pasid(struct idxd_wq *wq)
>   void idxd_wq_disable_cleanup(struct idxd_wq *wq)
>   {
>   	struct idxd_device *idxd = wq->idxd;
> -	struct device *dev = &idxd->pdev->dev;
> -	int i, wq_offset;
>   
>   	lockdep_assert_held(&idxd->dev_lock);
>   	memset(wq->wqcfg, 0, idxd->wqcfg_size);
> @@ -370,14 +385,6 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
>   	wq->ats_dis = 0;
>   	clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
>   	memset(wq->name, 0, WQ_NAME_SIZE);
> -
> -	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
> -		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
> -		iowrite32(0, idxd->reg_base + wq_offset);
> -		dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
> -			wq->id, i, wq_offset,
> -			ioread32(idxd->reg_base + wq_offset));
> -	}
>   }
>   
>   /* Device control bits */
> @@ -636,7 +643,14 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
>   	if (!wq->group)
>   		return 0;
>   
> -	memset(wq->wqcfg, 0, idxd->wqcfg_size);
> +	/*
> +	 * Instead of memset the entire shadow copy of WQCFG, copy from the hardware after
> +	 * wq reset. This will copy back the sticky values that are present on some devices.
> +	 */
> +	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
> +		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
> +		wq->wqcfg->bits[i] = ioread32(idxd->reg_base + wq_offset);
> +	}
>   
>   	/* byte 0-3 */
>   	wq->wqcfg->wq_size = wq->size;
> diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
> index eee94121991e..21aa6e2017c8 100644
> --- a/drivers/dma/idxd/idxd.h
> +++ b/drivers/dma/idxd/idxd.h
> @@ -387,6 +387,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq);
>   int idxd_wq_enable(struct idxd_wq *wq);
>   int idxd_wq_disable(struct idxd_wq *wq);
>   void idxd_wq_drain(struct idxd_wq *wq);
> +void idxd_wq_reset(struct idxd_wq *wq);
>   int idxd_wq_map_portal(struct idxd_wq *wq);
>   void idxd_wq_unmap_portal(struct idxd_wq *wq);
>   void idxd_wq_disable_cleanup(struct idxd_wq *wq);
> diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
> index 6d38bf9034e6..0155c1b4f2ef 100644
> --- a/drivers/dma/idxd/sysfs.c
> +++ b/drivers/dma/idxd/sysfs.c
> @@ -212,7 +212,6 @@ static void disable_wq(struct idxd_wq *wq)
>   {
>   	struct idxd_device *idxd = wq->idxd;
>   	struct device *dev = &idxd->pdev->dev;
> -	int rc;
>   
>   	mutex_lock(&wq->wq_lock);
>   	dev_dbg(dev, "%s removing WQ %s\n", __func__, dev_name(&wq->conf_dev));
> @@ -233,17 +232,13 @@ static void disable_wq(struct idxd_wq *wq)
>   	idxd_wq_unmap_portal(wq);
>   
>   	idxd_wq_drain(wq);
> -	rc = idxd_wq_disable(wq);
> +	idxd_wq_reset(wq);
>   
>   	idxd_wq_free_resources(wq);
>   	wq->client_count = 0;
>   	mutex_unlock(&wq->wq_lock);
>   
> -	if (rc < 0)
> -		dev_warn(dev, "Failed to disable %s: %d\n",
> -			 dev_name(&wq->conf_dev), rc);
> -	else
> -		dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev));
> +	dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev));
>   }
>   
>   static int idxd_config_bus_remove(struct device *dev)
>
>

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-07 19:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <161782510285.106717.15904886797025412090.stgit@djiang5-desk3.ch.intel.com>
2021-04-07 19:54 ` [PATCH v3] dmaengine: idxd: fix wq cleanup of WQCFG registers Dave Jiang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).