Re: [PATCH #upstream-fixes 1/4] libata: fix device iteration bugs

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

 



Michael Guntsche wrote:
> On Wed, 12 Nov 2008 11:34:19 +0900, Tejun Heo <tj@xxxxxxxxxx> wrote:
> 
>> Looks like we screwed up phantom device detection somewhere.  Michael,
>> can you please apply the attached patch and report kernel boot log?
> 
> Here the relevant dmesg output
> 
> ata_piix 0000:00:07.1: version 2.12
> scsi0 : ata_piix
> scsi1 : ata_piix
> ata1: PATA max MWDMA2 cmd 0x1f0 ctl 0x3f6 bmdma 0xe800 irq 14
> ata2: PATA max MWDMA2 cmd 0x170 ctl 0x376 bmdma 0xe808 irq 15
> ata1: XXX devmask=3
> ata1.00: XXX sff_dev_classify present=1 hdiag=0 tf=01:00:00 class=1
> ata1.01: XXX sff_dev_classify present=2 hdiag=0 tf=01:00:00 class=1
> ata1.00: ATA-5: IC35L040AVER07-0, ER4OA45A, max UDMA/100
> ata1.00: 66055248 sectors, multi 16: LBA
> ata1.00: configured for MWDMA2
> ata2: XXX devmask=1
> ata2.00: XXX sff_dev_classify present=1 hdiag=0 tf=01:14:eb class=3
> ata2.01: XXX sff_dev_classify present=0 hdiag=1 tf=ff:00:00 class=1
> ata2.01: XXX status=0x1 hdiag=1
> ata2.01: NODEV after polling detection
> ata2.00: ATAPI: SAMSUNG CD-R/RW SW-408B, M300, max MWDMA2
> ata2.00: configured for MWDMA2

Can you please test the attached patch?

Thanks.

-- 
tejun
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 4b47394..9859705 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1083,7 +1083,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 
 /**
  *	ata_sff_hsm_move - move the HSM to the next state.
- *	@ap: the target ata_port
  *	@qc: qc on going
  *	@status: current device status
  *	@in_wq: 1 if called from workqueue, 0 otherwise
@@ -1091,9 +1090,11 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
  *	RETURNS:
  *	1 when poll next status needed, 0 otherwise.
  */
-int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
-		     u8 status, int in_wq)
+int ata_sff_hsm_move(struct ata_queued_cmd *qc, u8 status, int in_wq)
 {
+	struct ata_port *ap = qc->ap;
+	struct ata_device *dev = qc->dev;
+	struct ata_eh_context *ehc = &ap->link.eh_context;
 	struct ata_eh_info *ehi = &ap->link.eh_info;
 	unsigned long flags = 0;
 	int poll_next;
@@ -1227,10 +1228,15 @@ fsm_start:
 			/* ATA PIO protocol */
 			if (unlikely((status & ATA_DRQ) == 0)) {
 				/* handle BSY=0, DRQ=0 as error */
-				if (likely(status & (ATA_ERR | ATA_DF)))
+				if (likely(status & (ATA_ERR | ATA_DF))) {
 					/* device stops HSM for abort/error */
 					qc->err_mask |= AC_ERR_DEV;
-				else {
+
+					if (!(ehc->sff_devmask &
+					      (1 << dev->devno)))
+						qc->err_mask |=
+							AC_ERR_NODEV_HINT;
+				} else {
 					/* HSM violation. Let EH handle this.
 					 * Phantom devices also trigger this
 					 * condition.  Mark hint.
@@ -1359,7 +1365,7 @@ fsm_start:
 	}
 
 	/* move the HSM */
-	poll_next = ata_sff_hsm_move(ap, qc, status, 1);
+	poll_next = ata_sff_hsm_move(qc, status, 1);
 
 	/* another command or interrupt handler
 	 * may be running at this point.
@@ -1593,7 +1599,7 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap,
 	/* ack bmdma irq events */
 	ap->ops->sff_irq_clear(ap);
 
-	ata_sff_hsm_move(ap, qc, status, 0);
+	ata_sff_hsm_move(qc, status, 0);
 
 	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
 				       qc->tf.protocol == ATAPI_PROT_DMA))
@@ -1969,25 +1975,26 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
 		      unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
+	struct ata_eh_context *ehc = &link->eh_context;
 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
-	unsigned int devmask = 0;
 	int rc;
 	u8 err;
 
 	DPRINTK("ENTER\n");
 
 	/* determine if device 0/1 are present */
+	ehc->sff_devmask = 0;
 	if (ata_devchk(ap, 0))
-		devmask |= (1 << 0);
+		ehc->sff_devmask |= (1 << 0);
 	if (slave_possible && ata_devchk(ap, 1))
-		devmask |= (1 << 1);
+		ehc->sff_devmask |= (1 << 1);
 
 	/* select device 0 again */
 	ap->ops->sff_dev_select(ap, 0);
 
 	/* issue bus reset */
-	DPRINTK("about to softreset, devmask=%x\n", devmask);
-	rc = ata_bus_softreset(ap, devmask, deadline);
+	DPRINTK("about to softreset, devmask=%x\n", ehc->sff_devmask);
+	rc = ata_bus_softreset(ap, ehc->sff_devmask, deadline);
 	/* if link is occupied, -ENODEV too is an error */
 	if (rc && (rc != -ENODEV || sata_scr_valid(link))) {
 		ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
@@ -1996,10 +2003,10 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
 
 	/* determine by signature whether we have ATA or ATAPI devices */
 	classes[0] = ata_sff_dev_classify(&link->device[0],
-					  devmask & (1 << 0), &err);
+					  ehc->sff_devmask & (1 << 0), &err);
 	if (slave_possible && err != 0x81)
 		classes[1] = ata_sff_dev_classify(&link->device[1],
-						  devmask & (1 << 1), &err);
+					ehc->sff_devmask & (1 << 1), &err);
 
 	DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
 	return 0;
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 1266924..1458ce8 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1406,7 +1406,7 @@ static unsigned int bfin_ata_host_intr(struct ata_port *ap,
 	/* ack bmdma irq events */
 	ap->ops->sff_irq_clear(ap);
 
-	ata_sff_hsm_move(ap, qc, status, 0);
+	ata_sff_hsm_move(qc, status, 0);
 
 	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
 				       qc->tf.protocol == ATAPI_PROT_DMA))
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 031d7b7..061f471 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -413,7 +413,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
 	ata_sff_irq_clear(ap);
 
 	/* kick HSM in the ass */
-	ata_sff_hsm_move(ap, qc, status, 0);
+	ata_sff_hsm_move(qc, status, 0);
 
 	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
 		ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 59b0f1c..0a14022 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -639,6 +639,9 @@ struct ata_eh_context {
 	u8			saved_xfer_mode[ATA_MAX_DEVICES];
 	/* timestamp for the last reset attempt or success */
 	unsigned long		last_reset;
+#ifdef CONFIG_ATA_SFF
+	unsigned int		sff_devmask;
+#endif
 };
 
 struct ata_acpi_drive
@@ -1511,8 +1514,7 @@ extern unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev,
 			unsigned char *buf, unsigned int buflen, int rw);
 extern u8 ata_sff_irq_on(struct ata_port *ap);
 extern void ata_sff_irq_clear(struct ata_port *ap);
-extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
-			    u8 status, int in_wq);
+extern int ata_sff_hsm_move(struct ata_queued_cmd *qc, u8 status, int in_wq);
 extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
 extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
 extern unsigned int ata_sff_host_intr(struct ata_port *ap,

[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