diff mbox

[1/2,SRU,P/Q/R] ioatdma: channel reset scheme fixup on Intel Atom S1200 platforms

Message ID 1395319870-3929-1-git-send-email-tim.gardner@canonical.com
State New
Headers show

Commit Message

Tim Gardner March 20, 2014, 12:51 p.m. UTC
From: Dave Jiang <dave.jiang@intel.com>

BugLink: http://bugs.launchpad.net/bugs/1291113

The Intel Atom S1200 family ioatdma changed the channel reset behavior.
It does a reset similar to PCI FLR by resetting all the MSIX
registers. We have to re-init msix interrupts because of this. This
workaround is only specific to this platform and is not expected to carry
over to the later generations.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Acked-by: Dan Williams <djbw@fb.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
(back ported from commit 8a52b9ff1154a68b6a2a8da9a31a87e52f5f6418)

Back port notes: I implemented enough of this patch to support
device->irq_mode storage, upon which da87ca4d4ca101f177fffd84f1f0a5e4c0343557
(ioat: fix tasklet tear down) is dependent.

Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
 drivers/dma/ioat/dma.c |    8 +++++++-
 drivers/dma/ioat/dma.h |   10 ++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

Comments

Brad Figg March 21, 2014, 2:49 p.m. UTC | #1
On 03/20/2014 05:51 AM, tim.gardner@canonical.com wrote:
> From: Dave Jiang <dave.jiang@intel.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1291113
> 
> The Intel Atom S1200 family ioatdma changed the channel reset behavior.
> It does a reset similar to PCI FLR by resetting all the MSIX
> registers. We have to re-init msix interrupts because of this. This
> workaround is only specific to this platform and is not expected to carry
> over to the later generations.
> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> Acked-by: Dan Williams <djbw@fb.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> (back ported from commit 8a52b9ff1154a68b6a2a8da9a31a87e52f5f6418)
> 
> Back port notes: I implemented enough of this patch to support
> device->irq_mode storage, upon which da87ca4d4ca101f177fffd84f1f0a5e4c0343557
> (ioat: fix tasklet tear down) is dependent.
> 
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> ---
>  drivers/dma/ioat/dma.c |    8 +++++++-
>  drivers/dma/ioat/dma.h |   10 ++++++++++
>  2 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
> index 6595180..fe5152a 100644
> --- a/drivers/dma/ioat/dma.c
> +++ b/drivers/dma/ioat/dma.c
> @@ -890,7 +890,7 @@ MODULE_PARM_DESC(ioat_interrupt_style,
>   * ioat_dma_setup_interrupts - setup interrupt handler
>   * @device: ioat device
>   */
> -static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
> +int ioat_dma_setup_interrupts(struct ioatdma_device *device)
>  {
>  	struct ioat_chan_common *chan;
>  	struct pci_dev *pdev = device->pdev;
> @@ -939,6 +939,7 @@ msix:
>  		}
>  	}
>  	intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
> +	device->irq_mode = IOAT_MSIX;
>  	goto done;
>  
>  msix_single_vector:
> @@ -954,6 +955,7 @@ msix_single_vector:
>  		pci_disable_msix(pdev);
>  		goto msi;
>  	}
> +	device->irq_mode = IOAT_MSIX_SINGLE;
>  	goto done;
>  
>  msi:
> @@ -967,6 +969,7 @@ msi:
>  		pci_disable_msi(pdev);
>  		goto intx;
>  	}
> +	device->irq_mode = IOAT_MSIX;
>  	goto done;
>  
>  intx:
> @@ -975,6 +978,7 @@ intx:
>  	if (err)
>  		goto err_no_irq;
>  
> +	device->irq_mode = IOAT_INTX;
>  done:
>  	if (device->intr_quirk)
>  		device->intr_quirk(device);
> @@ -985,9 +989,11 @@ done:
>  err_no_irq:
>  	/* Disable all interrupt generation */
>  	writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
> +	device->irq_mode = IOAT_NOIRQ;
>  	dev_err(dev, "no usable interrupts\n");
>  	return err;
>  }
> +EXPORT_SYMBOL(ioat_dma_setup_interrupts);
>  
>  static void ioat_disable_interrupts(struct ioatdma_device *device)
>  {
> diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
> index 8bebddd..148883e 100644
> --- a/drivers/dma/ioat/dma.h
> +++ b/drivers/dma/ioat/dma.h
> @@ -48,6 +48,14 @@
>   */
>  #define NULL_DESC_BUFFER_SIZE 1
>  
> +enum ioat_irq_mode {
> +	IOAT_NOIRQ = 0,
> +	IOAT_MSIX,
> +	IOAT_MSIX_SINGLE,
> +	IOAT_MSI,
> +	IOAT_INTX
> +};
> +
>  /**
>   * struct ioatdma_device - internal representation of a IOAT device
>   * @pdev: PCI-Express device
> @@ -77,6 +85,7 @@ struct ioatdma_device {
>  	struct msix_entry msix_entries[4];
>  	struct ioat_chan_common *idx[4];
>  	struct dca_provider *dca;
> +	enum ioat_irq_mode irq_mode;
>  	void (*intr_quirk)(struct ioatdma_device *device);
>  	int (*enumerate_channels)(struct ioatdma_device *device);
>  	int (*reset_hw)(struct ioat_chan_common *chan);
> @@ -344,6 +353,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
>  			   dma_addr_t *phys_complete);
>  void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
>  void ioat_kobject_del(struct ioatdma_device *device);
> +int ioat_dma_setup_interrupts(struct ioatdma_device *device);
>  extern const struct sysfs_ops ioat_sysfs_ops;
>  extern struct ioat_sysfs_entry ioat_version_attr;
>  extern struct ioat_sysfs_entry ioat_cap_attr;
> 

Looks like a faithful backport of the upstream commit and you got positive testing
results.
Brad Figg March 21, 2014, 2:49 p.m. UTC | #2
On 03/20/2014 05:51 AM, tim.gardner@canonical.com wrote:
> From: Dave Jiang <dave.jiang@intel.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1291113
> 
> The Intel Atom S1200 family ioatdma changed the channel reset behavior.
> It does a reset similar to PCI FLR by resetting all the MSIX
> registers. We have to re-init msix interrupts because of this. This
> workaround is only specific to this platform and is not expected to carry
> over to the later generations.
> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> Acked-by: Dan Williams <djbw@fb.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> (back ported from commit 8a52b9ff1154a68b6a2a8da9a31a87e52f5f6418)
> 
> Back port notes: I implemented enough of this patch to support
> device->irq_mode storage, upon which da87ca4d4ca101f177fffd84f1f0a5e4c0343557
> (ioat: fix tasklet tear down) is dependent.
> 
> Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
> ---
>  drivers/dma/ioat/dma.c |    8 +++++++-
>  drivers/dma/ioat/dma.h |   10 ++++++++++
>  2 files changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
> index 6595180..fe5152a 100644
> --- a/drivers/dma/ioat/dma.c
> +++ b/drivers/dma/ioat/dma.c
> @@ -890,7 +890,7 @@ MODULE_PARM_DESC(ioat_interrupt_style,
>   * ioat_dma_setup_interrupts - setup interrupt handler
>   * @device: ioat device
>   */
> -static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
> +int ioat_dma_setup_interrupts(struct ioatdma_device *device)
>  {
>  	struct ioat_chan_common *chan;
>  	struct pci_dev *pdev = device->pdev;
> @@ -939,6 +939,7 @@ msix:
>  		}
>  	}
>  	intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
> +	device->irq_mode = IOAT_MSIX;
>  	goto done;
>  
>  msix_single_vector:
> @@ -954,6 +955,7 @@ msix_single_vector:
>  		pci_disable_msix(pdev);
>  		goto msi;
>  	}
> +	device->irq_mode = IOAT_MSIX_SINGLE;
>  	goto done;
>  
>  msi:
> @@ -967,6 +969,7 @@ msi:
>  		pci_disable_msi(pdev);
>  		goto intx;
>  	}
> +	device->irq_mode = IOAT_MSIX;
>  	goto done;
>  
>  intx:
> @@ -975,6 +978,7 @@ intx:
>  	if (err)
>  		goto err_no_irq;
>  
> +	device->irq_mode = IOAT_INTX;
>  done:
>  	if (device->intr_quirk)
>  		device->intr_quirk(device);
> @@ -985,9 +989,11 @@ done:
>  err_no_irq:
>  	/* Disable all interrupt generation */
>  	writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
> +	device->irq_mode = IOAT_NOIRQ;
>  	dev_err(dev, "no usable interrupts\n");
>  	return err;
>  }
> +EXPORT_SYMBOL(ioat_dma_setup_interrupts);
>  
>  static void ioat_disable_interrupts(struct ioatdma_device *device)
>  {
> diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
> index 8bebddd..148883e 100644
> --- a/drivers/dma/ioat/dma.h
> +++ b/drivers/dma/ioat/dma.h
> @@ -48,6 +48,14 @@
>   */
>  #define NULL_DESC_BUFFER_SIZE 1
>  
> +enum ioat_irq_mode {
> +	IOAT_NOIRQ = 0,
> +	IOAT_MSIX,
> +	IOAT_MSIX_SINGLE,
> +	IOAT_MSI,
> +	IOAT_INTX
> +};
> +
>  /**
>   * struct ioatdma_device - internal representation of a IOAT device
>   * @pdev: PCI-Express device
> @@ -77,6 +85,7 @@ struct ioatdma_device {
>  	struct msix_entry msix_entries[4];
>  	struct ioat_chan_common *idx[4];
>  	struct dca_provider *dca;
> +	enum ioat_irq_mode irq_mode;
>  	void (*intr_quirk)(struct ioatdma_device *device);
>  	int (*enumerate_channels)(struct ioatdma_device *device);
>  	int (*reset_hw)(struct ioat_chan_common *chan);
> @@ -344,6 +353,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
>  			   dma_addr_t *phys_complete);
>  void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
>  void ioat_kobject_del(struct ioatdma_device *device);
> +int ioat_dma_setup_interrupts(struct ioatdma_device *device);
>  extern const struct sysfs_ops ioat_sysfs_ops;
>  extern struct ioat_sysfs_entry ioat_version_attr;
>  extern struct ioat_sysfs_entry ioat_cap_attr;
>
Tim Gardner March 21, 2014, 3:17 p.m. UTC | #3

diff mbox

Patch

diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 6595180..fe5152a 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -890,7 +890,7 @@  MODULE_PARM_DESC(ioat_interrupt_style,
  * ioat_dma_setup_interrupts - setup interrupt handler
  * @device: ioat device
  */
-static int ioat_dma_setup_interrupts(struct ioatdma_device *device)
+int ioat_dma_setup_interrupts(struct ioatdma_device *device)
 {
 	struct ioat_chan_common *chan;
 	struct pci_dev *pdev = device->pdev;
@@ -939,6 +939,7 @@  msix:
 		}
 	}
 	intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
+	device->irq_mode = IOAT_MSIX;
 	goto done;
 
 msix_single_vector:
@@ -954,6 +955,7 @@  msix_single_vector:
 		pci_disable_msix(pdev);
 		goto msi;
 	}
+	device->irq_mode = IOAT_MSIX_SINGLE;
 	goto done;
 
 msi:
@@ -967,6 +969,7 @@  msi:
 		pci_disable_msi(pdev);
 		goto intx;
 	}
+	device->irq_mode = IOAT_MSIX;
 	goto done;
 
 intx:
@@ -975,6 +978,7 @@  intx:
 	if (err)
 		goto err_no_irq;
 
+	device->irq_mode = IOAT_INTX;
 done:
 	if (device->intr_quirk)
 		device->intr_quirk(device);
@@ -985,9 +989,11 @@  done:
 err_no_irq:
 	/* Disable all interrupt generation */
 	writeb(0, device->reg_base + IOAT_INTRCTRL_OFFSET);
+	device->irq_mode = IOAT_NOIRQ;
 	dev_err(dev, "no usable interrupts\n");
 	return err;
 }
+EXPORT_SYMBOL(ioat_dma_setup_interrupts);
 
 static void ioat_disable_interrupts(struct ioatdma_device *device)
 {
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 8bebddd..148883e 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -48,6 +48,14 @@ 
  */
 #define NULL_DESC_BUFFER_SIZE 1
 
+enum ioat_irq_mode {
+	IOAT_NOIRQ = 0,
+	IOAT_MSIX,
+	IOAT_MSIX_SINGLE,
+	IOAT_MSI,
+	IOAT_INTX
+};
+
 /**
  * struct ioatdma_device - internal representation of a IOAT device
  * @pdev: PCI-Express device
@@ -77,6 +85,7 @@  struct ioatdma_device {
 	struct msix_entry msix_entries[4];
 	struct ioat_chan_common *idx[4];
 	struct dca_provider *dca;
+	enum ioat_irq_mode irq_mode;
 	void (*intr_quirk)(struct ioatdma_device *device);
 	int (*enumerate_channels)(struct ioatdma_device *device);
 	int (*reset_hw)(struct ioat_chan_common *chan);
@@ -344,6 +353,7 @@  bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
 			   dma_addr_t *phys_complete);
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
+int ioat_dma_setup_interrupts(struct ioatdma_device *device);
 extern const struct sysfs_ops ioat_sysfs_ops;
 extern struct ioat_sysfs_entry ioat_version_attr;
 extern struct ioat_sysfs_entry ioat_cap_attr;