diff mbox

[V3] AHCI: Workaround for ThunderX Errata#22536

Message ID 1455653329-4934-1-git-send-email-tchalamarla@caviumnetworks.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tirumalesh Chalamarla Feb. 16, 2016, 8:08 p.m. UTC
From: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>

Due to Errata in ThunderX, HOST_IRQ_STAT should be
cleared before leaving the interrupt handler.
The patch attempts to satisfy the need.

Changes from V2:
	- removed newfile
	- code is now under CONFIG_ARM64

Changes from V1:
	- Rebased on top of libata/for-4.6
        - Moved ThunderX intr handler to new file

Signed-off-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
---
 drivers/ata/ahci.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

Comments

Thomas Gleixner Feb. 17, 2016, 4:12 p.m. UTC | #1
On Tue, 16 Feb 2016, tchalamarla@caviumnetworks.com wrote:
> +#ifdef CONFIG_ARM64
> +/* Due to ERRATA#22536, ThunderX need to handle
> + * HOST_IRQ_STAT differently.
> + * Work around is to make sure all pending IRQs
> + * are served before leaving handler
> + */
> +static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
> +{
> +	struct ata_host *host = dev_instance;
> +	struct ahci_host_priv *hpriv;
> +	unsigned int rc = 0;
> +	void __iomem *mmio;
> +	u32 irq_stat, irq_masked;
> +	unsigned int handled = 1;
> +
> +	VPRINTK("ENTER\n");

Come on. This VPRINK stuff is really pointless. Enable irq tracepoints, they
already track the enter/exit of interrupt handlers ....

Thanks,

	tglx
Tirumalesh Chalamarla Feb. 24, 2016, midnight UTC | #2
Hi Tejun,

Any more comments on this?

Thanks,
Tirumalesh.


On 02/16/2016 12:08 PM, tchalamarla@caviumnetworks.com wrote:
> From: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
>
> Due to Errata in ThunderX, HOST_IRQ_STAT should be
> cleared before leaving the interrupt handler.
> The patch attempts to satisfy the need.
>
> Changes from V2:
> 	- removed newfile
> 	- code is now under CONFIG_ARM64
>
> Changes from V1:
> 	- Rebased on top of libata/for-4.6
>          - Moved ThunderX intr handler to new file
>
> Signed-off-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
> ---
>   drivers/ata/ahci.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 44 insertions(+)
>
> diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> index 546a369..c8496fc 100644
> --- a/drivers/ata/ahci.c
> +++ b/drivers/ata/ahci.c
> @@ -1325,6 +1325,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
>   {}
>   #endif
>
> +#ifdef CONFIG_ARM64
> +/* Due to ERRATA#22536, ThunderX need to handle
> + * HOST_IRQ_STAT differently.
> + * Work around is to make sure all pending IRQs
> + * are served before leaving handler
> + */
> +static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
> +{
> +	struct ata_host *host = dev_instance;
> +	struct ahci_host_priv *hpriv;
> +	unsigned int rc = 0;
> +	void __iomem *mmio;
> +	u32 irq_stat, irq_masked;
> +	unsigned int handled = 1;
> +
> +	VPRINTK("ENTER\n");
> +	hpriv = host->private_data;
> +	mmio = hpriv->mmio;
> +	irq_stat = readl(mmio + HOST_IRQ_STAT);
> +	if (!irq_stat)
> +		return IRQ_NONE;
> +
> +	do {
> +		irq_masked = irq_stat & hpriv->port_map;
> +		spin_lock(&host->lock);
> +		rc = ahci_handle_port_intr(host, irq_masked);
> +		if (!rc)
> +			handled = 0;
> +		writel(irq_stat, mmio + HOST_IRQ_STAT);
> +		irq_stat = readl(mmio + HOST_IRQ_STAT);
> +		spin_unlock(&host->lock);
> +	} while (irq_stat);
> +	VPRINTK("EXIT\n");
> +
> +	return IRQ_RETVAL(handled);
> +}
> +#endif
> +
>   /*
>    * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
>    * to single msi.
> @@ -1560,6 +1598,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>   	if (ahci_broken_devslp(pdev))
>   		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
>
> +#ifdef CONFIG_ARM64
> +	/* this should be done before save config*/
> +	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
> +		hpriv->irq_handler = ahci_thunderx_irq_handler;
> +#endif
> +
>   	/* save initial config */
>   	ahci_pci_save_initial_config(pdev, hpriv);
>
>
Tirumalesh Chalamarla Feb. 25, 2016, 8:31 p.m. UTC | #3
On 02/17/2016 08:12 AM, Thomas Gleixner wrote:
> On Tue, 16 Feb 2016, tchalamarla@caviumnetworks.com wrote:
>> +#ifdef CONFIG_ARM64
>> +/* Due to ERRATA#22536, ThunderX need to handle
>> + * HOST_IRQ_STAT differently.
>> + * Work around is to make sure all pending IRQs
>> + * are served before leaving handler
>> + */
>> +static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
>> +{
>> +	struct ata_host *host = dev_instance;
>> +	struct ahci_host_priv *hpriv;
>> +	unsigned int rc = 0;
>> +	void __iomem *mmio;
>> +	u32 irq_stat, irq_masked;
>> +	unsigned int handled = 1;
>> +
>> +	VPRINTK("ENTER\n");
>
> Come on. This VPRINK stuff is really pointless. Enable irq tracepoints, they
> already track the enter/exit of interrupt handlers ....
>

sure. waiting for some more comments if any.
> Thanks,
>
> 	tglx
>
>
Tejun Heo Feb. 29, 2016, 9:12 p.m. UTC | #4
Hello,

Sorry about the delay.

On Thu, Feb 25, 2016 at 12:31:53PM -0800, Tirumalesh Chalamarla wrote:
> On 02/17/2016 08:12 AM, Thomas Gleixner wrote:
> >On Tue, 16 Feb 2016, tchalamarla@caviumnetworks.com wrote:
> >>+#ifdef CONFIG_ARM64
> >>+/* Due to ERRATA#22536, ThunderX need to handle
> >>+ * HOST_IRQ_STAT differently.
> >>+ * Work around is to make sure all pending IRQs
> >>+ * are served before leaving handler
> >>+ */
> >>+static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
> >>+{
> >>+	struct ata_host *host = dev_instance;
> >>+	struct ahci_host_priv *hpriv;
> >>+	unsigned int rc = 0;
> >>+	void __iomem *mmio;
> >>+	u32 irq_stat, irq_masked;
> >>+	unsigned int handled = 1;
> >>+
> >>+	VPRINTK("ENTER\n");
> >
> >Come on. This VPRINK stuff is really pointless. Enable irq tracepoints, they
> >already track the enter/exit of interrupt handlers ....
> 
> sure. waiting for some more comments if any.

Yeah, VPRINTK way predates tracepoints and is kinda silly at this
point.  That said, it's used relatively consistently across libata and
some people still use it for debugging.  We can replace them with
proper tracepoints but that's a work for another patchset.  For now,
let's leave it in for consistency with counterparts.

Thanks.
Tejun Heo Feb. 29, 2016, 9:17 p.m. UTC | #5
On Tue, Feb 16, 2016 at 12:08:49PM -0800, tchalamarla@caviumnetworks.com wrote:
> From: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
> 
> Due to Errata in ThunderX, HOST_IRQ_STAT should be
> cleared before leaving the interrupt handler.
> The patch attempts to satisfy the need.
> 
> Changes from V2:
> 	- removed newfile
> 	- code is now under CONFIG_ARM64
> 
> Changes from V1:
> 	- Rebased on top of libata/for-4.6
>         - Moved ThunderX intr handler to new file
> 
> Signed-off-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>

Applied to libata/for-4.5-fixes w/ minor adjustments to comments.

Thanks.
Tirumalesh Chalamarla Feb. 29, 2016, 10 p.m. UTC | #6
Thanks.


On 02/29/2016 01:17 PM, Tejun Heo wrote:
> On Tue, Feb 16, 2016 at 12:08:49PM -0800, tchalamarla@caviumnetworks.com wrote:
>> From: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
>>
>> Due to Errata in ThunderX, HOST_IRQ_STAT should be
>> cleared before leaving the interrupt handler.
>> The patch attempts to satisfy the need.
>>
>> Changes from V2:
>> 	- removed newfile
>> 	- code is now under CONFIG_ARM64
>>
>> Changes from V1:
>> 	- Rebased on top of libata/for-4.6
>>          - Moved ThunderX intr handler to new file
>>
>> Signed-off-by: Tirumalesh Chalamarla <tchalamarla@caviumnetworks.com>
>
> Applied to libata/for-4.5-fixes w/ minor adjustments to comments.
>
> Thanks.
>
diff mbox

Patch

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 546a369..c8496fc 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1325,6 +1325,44 @@  static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
+#ifdef CONFIG_ARM64
+/* Due to ERRATA#22536, ThunderX need to handle
+ * HOST_IRQ_STAT differently.
+ * Work around is to make sure all pending IRQs
+ * are served before leaving handler
+ */
+static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
+{
+	struct ata_host *host = dev_instance;
+	struct ahci_host_priv *hpriv;
+	unsigned int rc = 0;
+	void __iomem *mmio;
+	u32 irq_stat, irq_masked;
+	unsigned int handled = 1;
+
+	VPRINTK("ENTER\n");
+	hpriv = host->private_data;
+	mmio = hpriv->mmio;
+	irq_stat = readl(mmio + HOST_IRQ_STAT);
+	if (!irq_stat)
+		return IRQ_NONE;
+
+	do {
+		irq_masked = irq_stat & hpriv->port_map;
+		spin_lock(&host->lock);
+		rc = ahci_handle_port_intr(host, irq_masked);
+		if (!rc)
+			handled = 0;
+		writel(irq_stat, mmio + HOST_IRQ_STAT);
+		irq_stat = readl(mmio + HOST_IRQ_STAT);
+		spin_unlock(&host->lock);
+	} while (irq_stat);
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(handled);
+}
+#endif
+
 /*
  * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
  * to single msi.
@@ -1560,6 +1598,12 @@  static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (ahci_broken_devslp(pdev))
 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
 
+#ifdef CONFIG_ARM64
+	/* this should be done before save config*/
+	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
+		hpriv->irq_handler = ahci_thunderx_irq_handler;
+#endif
+
 	/* save initial config */
 	ahci_pci_save_initial_config(pdev, hpriv);