libata: check for trusted computing in IDENTIFY DEVICE data
authorChristoph Hellwig <hch@lst.de>
Tue, 29 Aug 2017 12:42:06 +0000 (14:42 +0200)
committerTejun Heo <tj@kernel.org>
Tue, 29 Aug 2017 15:33:24 +0000 (08:33 -0700)
ATA-8 and later mirrors the TRUSTED COMPUTING SUPPORTED bit in word 48 of
the IDENTIFY DEVICE data.  Check this before issuing a READ LOG PAGE
command to avoid issues with buggy devices.  The only downside is that
we can't support Security Send / Receive for a device with an older
revision due to the conflicting use of this field in earlier
specifications.

tj: The reason we need this is because some devices which don't
    support READ LOG PAGE lock up after getting issued that command.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Tested-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
drivers/ata/libata-core.c
include/linux/ata.h

index 697f5f896b190cfacf771a71cf29311454db6175..ca57b03ab9505ec03375e72cffc1b55aa3af4416 100644 (file)
@@ -2413,6 +2413,9 @@ static void ata_dev_config_trusted(struct ata_device *dev)
        u64 trusted_cap;
        unsigned int err;
 
+       if (!ata_id_has_trusted(dev->id))
+               return;
+
        if (!ata_identify_page_supported(dev, ATA_LOG_SECURITY)) {
                ata_dev_warn(dev,
                             "Security Log not supported\n");
index e65ae4b2ed485a67a26d7c45d542a76d70ab9d97..c7a353825450a950a2f53f93774ef4c5bce934a0 100644 (file)
@@ -60,7 +60,8 @@ enum {
        ATA_ID_FW_REV           = 23,
        ATA_ID_PROD             = 27,
        ATA_ID_MAX_MULTSECT     = 47,
-       ATA_ID_DWORD_IO         = 48,
+       ATA_ID_DWORD_IO         = 48,   /* before ATA-8 */
+       ATA_ID_TRUSTED          = 48,   /* ATA-8 and later */
        ATA_ID_CAPABILITY       = 49,
        ATA_ID_OLD_PIO_MODES    = 51,
        ATA_ID_OLD_DMA_MODES    = 52,
@@ -889,6 +890,13 @@ static inline bool ata_id_has_dword_io(const u16 *id)
        return id[ATA_ID_DWORD_IO] & (1 << 0);
 }
 
+static inline bool ata_id_has_trusted(const u16 *id)
+{
+       if (ata_id_major_version(id) <= 7)
+               return false;
+       return id[ATA_ID_TRUSTED] & (1 << 0);
+}
+
 static inline bool ata_id_has_unload(const u16 *id)
 {
        if (ata_id_major_version(id) >= 7 &&