libata: Add atapi_dmadir force flag
authorVincent Pelletier <plr.vincent@gmail.com>
Tue, 21 May 2013 20:30:58 +0000 (22:30 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2014 20:24:23 +0000 (12:24 -0800)
commit 966fbe193f47c68e70a80ec9991098e88e7959cb upstream.

Some device require DMADIR to be enabled, but are not detected as such
by atapi_id_dmadir.  One such example is "Asus Serillel 2"
SATA-host-to-PATA-device bridge: the bridge itself requires DMADIR,
even if the bridged device does not.

As atapi_dmadir module parameter can cause problems with some devices
(as per Tejun Heo's memory), enabling it globally may not be possible
depending on the hardware.

This patch adds atapi_dmadir in the form of a "force" horkage value,
allowing global, per-bus and per-device control.

Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/kernel-parameters.txt
drivers/ata/libata-core.c
include/linux/libata.h

index 2fe6e767b3d6013f3d1023c2e518b0466fa27e2f..96401631523d26787c9e03ef8938bd08bd8c8d9f 100644 (file)
@@ -1456,6 +1456,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                        * dump_id: dump IDENTIFY data.
 
+                       * atapi_dmadir: Enable ATAPI DMADIR bridge support
+
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
 
index 011d12cdc102d786d9878d981033c739925a4ec2..d18ab9015e3ecf0d0b7a322ebcd63849be68ab57 100644 (file)
@@ -2401,7 +2401,7 @@ int ata_dev_configure(struct ata_device *dev)
                        cdb_intr_string = ", CDB intr";
                }
 
-               if (atapi_dmadir || atapi_id_dmadir(dev->id)) {
+               if (atapi_dmadir || (dev->horkage & ATA_HORKAGE_ATAPI_DMADIR) || atapi_id_dmadir(dev->id)) {
                        dev->flags |= ATA_DFLAG_DMADIR;
                        dma_dir_string = ", DMADIR";
                }
@@ -6506,6 +6506,7 @@ static int __init ata_parse_force_one(char **cur,
                { "nosrst",     .lflags         = ATA_LFLAG_NO_SRST },
                { "norst",      .lflags         = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
                { "rstonce",    .lflags         = ATA_LFLAG_RST_ONCE },
+               { "atapi_dmadir", .horkage_on   = ATA_HORKAGE_ATAPI_DMADIR },
        };
        char *start = *cur, *p = *cur;
        char *id, *val, *endp;
index eae7a053dc5141d062a80bb4055449520bac61cf..9a4c194ebc8a0b8e4fbe38be28e80b6ad6860838 100644 (file)
@@ -399,6 +399,7 @@ enum {
        ATA_HORKAGE_BROKEN_FPDMA_AA     = (1 << 15),    /* skip AA */
        ATA_HORKAGE_DUMP_ID     = (1 << 16),    /* dump IDENTIFY data */
        ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17),  /* Set max sects to 65535 */
+       ATA_HORKAGE_ATAPI_DMADIR = (1 << 18),   /* device requires dmadir */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */