Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9116300634c5c76cfcd0d2af689846e04d172256
Commit:     9116300634c5c76cfcd0d2af689846e04d172256
Parent:     559bbe6cbd0d8c68d40076a5f7dc98e3bf5864b2
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Thu Feb 21 13:25:50 2008 +0900
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sun Feb 24 00:27:33 2008 -0500

    libata: automatically use DMADIR if drive/bridge requires it
    
    Back in 2.6.17-rc2, a libata module parameter was added for atapi_dmadir.
    
    That's nice, but most SATA devices which need it will tell us about it
    in their IDENTIFY PACKET response, as bit-15 of word-62 of the
    returned data (as per ATA7, ATA8 specifications).
    
    So for those which specify it, we should automatically use the DMADIR bit.
    Otherwise, disc writing will fail by default on many SATA-ATAPI drives.
    
    This patch adds ATA_DFLAG_DMADIR and make ata_dev_configure() set it
    if atapi_dmadir is set or identify data indicates DMADIR is necessary.
    atapi_xlat() is converted to check ATA_DFLAG_DMADIR before setting
    DMADIR.
    
    Original patch is from Mark Lord.
    
    Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
    Cc: Mark Lord <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/libata-core.c |   11 +++++++++--
 drivers/ata/libata-scsi.c |    3 ++-
 include/linux/ata.h       |    5 +++++
 include/linux/libata.h    |    1 +
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9812bbf..1845119 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2396,6 +2396,7 @@ int ata_dev_configure(struct ata_device *dev)
        else if (dev->class == ATA_DEV_ATAPI) {
                const char *cdb_intr_string = "";
                const char *atapi_an_string = "";
+               const char *dma_dir_string = "";
                u32 sntf;
 
                rc = atapi_cdb_len(id);
@@ -2436,13 +2437,19 @@ int ata_dev_configure(struct ata_device *dev)
                        cdb_intr_string = ", CDB intr";
                }
 
+               if (atapi_dmadir || atapi_id_dmadir(dev->id)) {
+                       dev->flags |= ATA_DFLAG_DMADIR;
+                       dma_dir_string = ", DMADIR";
+               }
+
                /* 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\n",
+                                      "ATAPI: %s, %s, max %s%s%s%s\n",
                                       modelbuf, fwrevbuf,
                                       ata_mode_string(xfer_mask),
-                                      cdb_intr_string, atapi_an_string);
+                                      cdb_intr_string, atapi_an_string,
+                                      dma_dir_string);
        }
 
        /* determine max_sectors */
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index f888bab..0562b0a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2582,7 +2582,8 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
                qc->tf.protocol = ATAPI_PROT_DMA;
                qc->tf.feature |= ATAPI_PKT_DMA;
 
-               if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
+               if ((dev->flags & ATA_DFLAG_DMADIR) &&
+                   (scmd->sc_data_direction != DMA_TO_DEVICE))
                        /* some SATA bridges need us to indicate data xfer 
direction */
                        qc->tf.feature |= ATAPI_DMADIR;
        }
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 78bbaca..1c622e2 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -659,6 +659,11 @@ static inline int atapi_command_packet_set(const u16 
*dev_id)
        return (dev_id[0] >> 8) & 0x1f;
 }
 
+static inline int atapi_id_dmadir(const u16 *dev_id)
+{
+       return ata_id_major_version(dev_id) >= 7 && (dev_id[62] & 0x8000);
+}
+
 static inline int is_multi_taskfile(struct ata_taskfile *tf)
 {
        return (tf->command == ATA_CMD_READ_MULTI) ||
diff --git a/include/linux/libata.h b/include/linux/libata.h
index ce7603a..a05f600 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -138,6 +138,7 @@ enum {
        ATA_DFLAG_AN            = (1 << 7), /* AN configured */
        ATA_DFLAG_HIPM          = (1 << 8), /* device supports HIPM */
        ATA_DFLAG_DIPM          = (1 << 9), /* device supports DIPM */
+       ATA_DFLAG_DMADIR        = (1 << 10), /* device requires DMADIR */
        ATA_DFLAG_CFG_MASK      = (1 << 12) - 1,
 
        ATA_DFLAG_PIO           = (1 << 12), /* device limited to PIO mode */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to