Patch "ata: libahci: clear pending interrupt status" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ata: libahci: clear pending interrupt status

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ata-libahci-clear-pending-interrupt-status.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit de70500d95c937f534fb005a2378ca680e99f871
Author: Szuying Chen <chensiying21@xxxxxxxxx>
Date:   Thu Sep 7 16:17:10 2023 +0800

    ata: libahci: clear pending interrupt status
    
    [ Upstream commit 737dd811a3dbfd7edd4ad2ba5152e93d99074f83 ]
    
    When a CRC error occurs, the HBA asserts an interrupt to indicate an
    interface fatal error (PxIS.IFS). The ISR clears PxIE and PxIS, then
    does error recovery. If the adapter receives another SDB FIS
    with an error (PxIS.TFES) from the device before the start of the EH
    recovery process, the interrupt signaling the new SDB cannot be
    serviced as PxIE was cleared already. This in turn results in the HBA
    inability to issue any command during the error recovery process after
    setting PxCMD.ST to 1 because PxIS.TFES is still set.
    
    According to AHCI 1.3.1 specifications section 6.2.2, fatal errors
    notified by setting PxIS.HBFS, PxIS.HBDS, PxIS.IFS or PxIS.TFES will
    cause the HBA to enter the ERR:Fatal state. In this state, the HBA
    shall not issue any new commands.
    
    To avoid this situation, introduce the function
    ahci_port_clear_pending_irq() to clear pending interrupts before
    executing a COMRESET. This follows the AHCI 1.3.1 - section 6.2.2.2
    specification.
    
    Signed-off-by: Szuying Chen <Chloe_Chen@xxxxxxxxxxxxxx>
    Fixes: e0bfd149973d ("[PATCH] ahci: stop engine during hard reset")
    Cc: stable@xxxxxxxxxxxxxxx
    Reviewed-by: Niklas Cassel <niklas.cassel@xxxxxxx>
    Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index b591a05768744..e22d45fb8ebdc 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1200,6 +1200,26 @@ static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
 	return sprintf(buf, "%d\n", emp->blink_policy);
 }
 
+static void ahci_port_clear_pending_irq(struct ata_port *ap)
+{
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+	void __iomem *port_mmio = ahci_port_base(ap);
+	u32 tmp;
+
+	/* clear SError */
+	tmp = readl(port_mmio + PORT_SCR_ERR);
+	dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp);
+	writel(tmp, port_mmio + PORT_SCR_ERR);
+
+	/* clear port IRQ */
+	tmp = readl(port_mmio + PORT_IRQ_STAT);
+	dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
+	if (tmp)
+		writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+	writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT);
+}
+
 static void ahci_port_init(struct device *dev, struct ata_port *ap,
 			   int port_no, void __iomem *mmio,
 			   void __iomem *port_mmio)
@@ -1214,18 +1234,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
 	if (rc)
 		dev_warn(dev, "%s (%d)\n", emsg, rc);
 
-	/* clear SError */
-	tmp = readl(port_mmio + PORT_SCR_ERR);
-	dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp);
-	writel(tmp, port_mmio + PORT_SCR_ERR);
-
-	/* clear port IRQ */
-	tmp = readl(port_mmio + PORT_IRQ_STAT);
-	dev_dbg(dev, "PORT_IRQ_STAT 0x%x\n", tmp);
-	if (tmp)
-		writel(tmp, port_mmio + PORT_IRQ_STAT);
-
-	writel(1 << port_no, mmio + HOST_IRQ_STAT);
+	ahci_port_clear_pending_irq(ap);
 
 	/* mark esata ports */
 	tmp = readl(port_mmio + PORT_CMD);
@@ -1555,6 +1564,8 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
 	tf.status = ATA_BUSY;
 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
+	ahci_port_clear_pending_irq(ap);
+
 	rc = sata_link_hardreset(link, timing, deadline, online,
 				 ahci_check_ready);
 



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux