Re: AHCI: connection status changed + hard resetting link with 2.6.30+

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

 



Zdenek Kaspar wrote:
> Tejun Heo napsal(a):
>> Zdenek Kaspar wrote:
>>> Hello Tejun, thanks for your reply. Attaching logs from my testing machine..
>>>
>>> I see this behavior on ICH7R with i3000 chipset too:
>>> 00:1f.2 RAID bus controller [0104]: Intel Corporation 82801GR/GH (ICH7
>>> Family) SATA RAID Controller [8086:27c3] (rev 01)
>> Can you please apply the attached patch and report the resulting boot
>> log?  Thanks.

Can you please try the attached patch?

Thanks.

-- 
tejun
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 336eb1e..54c9c6d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1667,6 +1667,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	DPRINTK("ENTER\n");
 
 	/* prepare for SRST (AHCI-1.1 10.4.1) */
+	ata_link_printk(link, KERN_INFO, "XXX softresetting link, kicking engine\n");
 	rc = ahci_kick_engine(ap, 1);
 	if (rc && rc != -EOPNOTSUPP)
 		ata_link_printk(link, KERN_WARNING,
@@ -1680,6 +1681,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	if (time_after(now, deadline))
 		msecs = jiffies_to_msecs(deadline - now);
 
+	ata_link_printk(link, KERN_INFO, "XXX setting SRST\n");
 	tf.ctl |= ATA_SRST;
 	if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
 				 AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
@@ -1692,10 +1694,12 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	msleep(1);
 
 	/* issue the second D2H Register FIS */
+	ata_link_printk(link, KERN_INFO, "XXX clearing SRST\n");
 	tf.ctl &= ~ATA_SRST;
 	ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
 
 	/* wait for link to become ready */
+	ata_link_printk(link, KERN_INFO, "XXX waiting for DRDY\n");
 	rc = ata_wait_after_reset(link, deadline, check_ready);
 	/* link occupied, -ENODEV too is an error */
 	if (rc) {
@@ -1704,6 +1708,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 	}
 	*class = ahci_dev_classify(ap);
 
+	ata_link_printk(link, KERN_INFO, "XXX rc=%d, class=%u\n", rc, *class);
 	DPRINTK("EXIT, class=%u\n", *class);
 	return 0;
 
@@ -1791,6 +1796,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 
 	DPRINTK("ENTER\n");
 
+	ata_link_printk(link, KERN_INFO, "XXX hardresetting link, stopping engine\n");
 	ahci_stop_engine(ap);
 
 	/* clear D2H reception area to properly wait for D2H FIS */
@@ -1798,14 +1804,17 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 	tf.command = 0x80;
 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
+	ata_link_printk(link, KERN_INFO, "XXX flipping SControl\n");
 	rc = sata_link_hardreset(link, timing, deadline, &online,
 				 ahci_check_ready);
 
+	ata_link_printk(link, KERN_INFO, "XXX starting engine\n");
 	ahci_start_engine(ap);
 
 	if (online)
 		*class = ahci_dev_classify(ap);
 
+	ata_link_printk(link, KERN_INFO, "XXX rc=%d, class=%u\n", rc, *class);
 	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
 	return rc;
 }
@@ -2035,6 +2044,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 	}
 
 	if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
+		ata_port_printk(ap, KERN_INFO, "XXX irq_stat=%x CONN|PHY\n", irq_stat);
 		ata_ehi_hotplugged(host_ehi);
 		ata_ehi_push_desc(host_ehi, "%s",
 			irq_stat & PORT_IRQ_CONNECT ?
@@ -2217,6 +2227,7 @@ static void ahci_freeze(struct ata_port *ap)
 {
 	void __iomem *port_mmio = ahci_port_base(ap);
 
+	ata_port_printk(ap, KERN_INFO, "XXX port freeze\n");
 	/* turn IRQ off */
 	writel(0, port_mmio + PORT_IRQ_MASK);
 }
@@ -2229,12 +2240,14 @@ static void ahci_thaw(struct ata_port *ap)
 	struct ahci_port_priv *pp = ap->private_data;
 
 	/* clear IRQ */
+	ata_port_printk(ap, KERN_INFO, "XXX clearing IRQs for thawing\n");
 	tmp = readl(port_mmio + PORT_IRQ_STAT);
 	writel(tmp, port_mmio + PORT_IRQ_STAT);
 	writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
 
 	/* turn IRQ back on */
 	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+	ata_port_printk(ap, KERN_INFO, "XXX port thawed\n");
 }
 
 static void ahci_error_handler(struct ata_port *ap)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 1a07c06..655442c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2625,8 +2625,17 @@ int ata_eh_reset(struct ata_link *link, int classify,
 	if (slave)
 		sehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
 
+	/*
+	 * Reset complete.  Ignore all exceptions happened before and
+	 * during reset and clear RESETTING flag.  There is a race
+	 * window between the actual reset and here but such window is
+	 * inevitable anyway as the window between reset and thawing
+	 * always exists.  Following identification or revalidation is
+	 * enough to protect against problems arising from this.
+	 */
 	spin_lock_irqsave(ap->lock, flags);
-	ap->pflags &= ~ATA_PFLAG_RESETTING;
+	memset(&link->eh_info, 0, sizeof(link->eh_info));
+	ap->pflags &= ~(ATA_PFLAG_RESETTING | ATA_PFLAG_EH_PENDING);
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	return rc;

[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux