[PATCH #upstream-fixes 2/2] libata: implement ATAPI_HORKAGE_NOPIO and apply it to GGW-H10N

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

 



LG blueray drive GGW-H10N can't do ATAPI PIO.  Implement
ATAPI_HORKAGE_NOPIO and apply it to the drive.  If the horkage is
active, atapi_check_dma() always returns 0 and warns if the controller
needs ATAPI PIO for certain commands.

Reported by Luke Ross in bz 10091.

Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
Cc: Luke Ross <luke@xxxxxxxxxxxxx>
---
 drivers/ata/libata-core.c |   30 +++++++++++++++++++++++++-----
 drivers/ata/libata-eh.c   |    1 +
 include/linux/libata.h    |    2 ++
 3 files changed, 28 insertions(+), 5 deletions(-)

Index: work/drivers/ata/libata-core.c
===================================================================
--- work.orig/drivers/ata/libata-core.c
+++ work/drivers/ata/libata-core.c
@@ -2266,6 +2266,7 @@ int ata_dev_configure(struct ata_device 
 		const char *cdb_intr_string = "";
 		const char *atapi_an_string = "";
 		const char *dma_dir_string = "";
+		const char *nopio_string = "";
 		u32 sntf;
 
 		rc = atapi_cdb_len(id);
@@ -2311,14 +2312,17 @@ int ata_dev_configure(struct ata_device 
 			dma_dir_string = ", DMADIR";
 		}
 
+		if (dev->horkage & ATAPI_HORKAGE_NOPIO)
+			nopio_string = ", no PIO";
+
 		/* print device info to dmesg */
 		if (ata_msg_drv(ap) && print_info)
 			ata_dev_printk(dev, KERN_INFO,
-				       "ATAPI: %s, %s, max %s%s%s%s\n",
+				       "ATAPI: %s, %s, max %s%s%s%s%s\n",
 				       modelbuf, fwrevbuf,
 				       ata_mode_string(xfer_mask),
 				       cdb_intr_string, atapi_an_string,
-				       dma_dir_string);
+				       dma_dir_string, nopio_string);
 	}
 
 	/* determine max_sectors */
@@ -3946,6 +3950,9 @@ static const struct ata_blacklist_entry 
 	{ "TSSTcorp CDDVDW SH-S202N", "SB00",	  ATA_HORKAGE_IVB, },
 	{ "TSSTcorp CDDVDW SH-S202N", "SB01",	  ATA_HORKAGE_IVB, },
 
+	/* AAAARGH... this one can't do ATAPI PIO */
+	{ "HL-DT-ST BD-RE  GGW-H10N", NULL,	ATAPI_HORKAGE_NOPIO },
+
 	/* End Marker */
 	{ }
 };
@@ -4313,17 +4320,30 @@ void ata_sg_clean(struct ata_queued_cmd 
 int atapi_check_dma(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
+	struct ata_device *dev = qc->dev;
+	bool nopio = dev->horkage & ATAPI_HORKAGE_NOPIO;
+	int rc = 0;
 
 	/* Don't allow DMA if it isn't multiple of 16 bytes.  Quite a
 	 * few ATAPI devices choke on such DMA requests.
 	 */
-	if (unlikely(qc->nbytes & 15))
+	if (unlikely(qc->nbytes & 15) && !nopio)
 		return 1;
 
 	if (ap->ops->check_atapi_dma)
-		return ap->ops->check_atapi_dma(qc);
+		rc = ap->ops->check_atapi_dma(qc);
 
-	return 0;
+	if (unlikely(rc) && nopio) {
+		if (!(dev->flags & ATAPI_DFLAG_WARNED_NOPIO)) {
+			ata_dev_printk(dev, KERN_ERR,
+			       "device can't handle ATAPI PIO but "
+			       "controller needs it, expect problem\n");
+			dev->flags |= ATAPI_DFLAG_WARNED_NOPIO;
+		}
+		rc = 0;	/* we're screwed, be optimistic while being screwed */
+	}
+
+	return rc;
 }
 
 /**
Index: work/drivers/ata/libata-eh.c
===================================================================
--- work.orig/drivers/ata/libata-eh.c
+++ work/drivers/ata/libata-eh.c
@@ -1693,6 +1693,7 @@ static unsigned int ata_eh_speed_down(st
 	 */
 	if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
 	    (link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
+	    !(dev->horkage & ATAPI_HORKAGE_NOPIO) &&
 	    (dev->xfer_shift != ATA_SHIFT_PIO)) {
 		if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
 			dev->spdn_cnt = 0;
Index: work/include/linux/libata.h
===================================================================
--- work.orig/include/linux/libata.h
+++ work/include/linux/libata.h
@@ -145,6 +145,7 @@ enum {
 	ATA_DFLAG_SPUNDOWN	= (1 << 14), /* XXX: for spindown_compat */
 	ATA_DFLAG_SLEEPING	= (1 << 15), /* device is sleeping */
 	ATA_DFLAG_DUBIOUS_XFER	= (1 << 16), /* data transfer not verified */
+	ATAPI_DFLAG_WARNED_NOPIO = (1 << 17), /* warned about ATAPI NOPIO */
 	ATA_DFLAG_INIT_MASK	= (1 << 24) - 1,
 
 	ATA_DFLAG_DETACH	= (1 << 24),
@@ -353,6 +354,7 @@ enum {
 	ATA_HORKAGE_IPM		= (1 << 7),	/* Link PM problems */
 	ATA_HORKAGE_IVB		= (1 << 8),	/* cbl det validity bit bugs */
 	ATA_HORKAGE_STUCK_ERR	= (1 << 9),	/* stuck ERR on next PACKET */
+	ATAPI_HORKAGE_NOPIO	= (1 << 10),	/* don't use ATAPI PIO */
 
 	 /* DMA mask for user DMA control: User visible values; DO NOT
 	    renumber */
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[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