aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Huang <shane.huang@amd.com>2012-12-17 10:18:59 -0500
committerJeff Garzik <jgarzik@redhat.com>2013-01-14 13:29:15 -0500
commit803739d25c2343da6d2f95eebdcbc08bf67097d4 (patch)
tree59f3fd6a8285925c79419132b469602f4c36a0bf
parent7f9c9f8e24590e7dcd26ca408458c43df5b83e61 (diff)
[libata] replace sata_settings with devslp_timing
NCQ capability was used to check availability of SATA Settings page from Identify Device Data Log, which contains DevSlp timing variables. It does not work on some HDDs and leads to error messages. IDENTIFY word 78 bit 5(Hardware Feature Control) can't work either because it is only the sufficient condition of Identify Device data log, not the necessary condition. This patch replaced ata_device->sata_settings with ->devslp_timing to only save DevSlp timing variables(8 bytes), instead of the whole SATA Settings page(512 bytes). Addresses https://bugzilla.kernel.org/show_bug.cgi?id=51881 Reported-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Shane Huang <shane.huang@amd.com> Cc: stable@vger.kernel.org Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/libahci.c6
-rw-r--r--drivers/ata/libata-core.c22
-rw-r--r--include/linux/ata.h8
-rw-r--r--include/linux/libata.h4
4 files changed, 23 insertions, 17 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 320712a7b9ea..6cd7805e47ca 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
1951 /* Use the nominal value 10 ms if the read MDAT is zero, 1951 /* Use the nominal value 10 ms if the read MDAT is zero,
1952 * the nominal value of DETO is 20 ms. 1952 * the nominal value of DETO is 20 ms.
1953 */ 1953 */
1954 if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & 1954 if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
1955 ATA_LOG_DEVSLP_VALID_MASK) { 1955 ATA_LOG_DEVSLP_VALID_MASK) {
1956 mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & 1956 mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
1957 ATA_LOG_DEVSLP_MDAT_MASK; 1957 ATA_LOG_DEVSLP_MDAT_MASK;
1958 if (!mdat) 1958 if (!mdat)
1959 mdat = 10; 1959 mdat = 10;
1960 deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; 1960 deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
1961 if (!deto) 1961 if (!deto)
1962 deto = 20; 1962 deto = 20;
1963 } else { 1963 } else {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9e8b99af400d..46cd3f4c6aaa 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev)
2325 } 2325 }
2326 } 2326 }
2327 2327
2328 /* check and mark DevSlp capability */ 2328 /* Check and mark DevSlp capability. Get DevSlp timing variables
2329 if (ata_id_has_devslp(dev->id)) 2329 * from SATA Settings page of Identify Device Data Log.
2330 dev->flags |= ATA_DFLAG_DEVSLP;
2331
2332 /* Obtain SATA Settings page from Identify Device Data Log,
2333 * which contains DevSlp timing variables etc.
2334 * Exclude old devices with ata_id_has_ncq()
2335 */ 2330 */
2336 if (ata_id_has_ncq(dev->id)) { 2331 if (ata_id_has_devslp(dev->id)) {
2332 u8 sata_setting[ATA_SECT_SIZE];
2333 int i, j;
2334
2335 dev->flags |= ATA_DFLAG_DEVSLP;
2337 err_mask = ata_read_log_page(dev, 2336 err_mask = ata_read_log_page(dev,
2338 ATA_LOG_SATA_ID_DEV_DATA, 2337 ATA_LOG_SATA_ID_DEV_DATA,
2339 ATA_LOG_SATA_SETTINGS, 2338 ATA_LOG_SATA_SETTINGS,
2340 dev->sata_settings, 2339 sata_setting,
2341 1); 2340 1);
2342 if (err_mask) 2341 if (err_mask)
2343 ata_dev_dbg(dev, 2342 ata_dev_dbg(dev,
2344 "failed to get Identify Device Data, Emask 0x%x\n", 2343 "failed to get Identify Device Data, Emask 0x%x\n",
2345 err_mask); 2344 err_mask);
2345 else
2346 for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) {
2347 j = ATA_LOG_DEVSLP_OFFSET + i;
2348 dev->devslp_timing[i] = sata_setting[j];
2349 }
2346 } 2350 }
2347 2351
2348 dev->cdb_len = 16; 2352 dev->cdb_len = 16;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 408da9502177..8f7a3d68371a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -297,10 +297,12 @@ enum {
297 ATA_LOG_SATA_NCQ = 0x10, 297 ATA_LOG_SATA_NCQ = 0x10,
298 ATA_LOG_SATA_ID_DEV_DATA = 0x30, 298 ATA_LOG_SATA_ID_DEV_DATA = 0x30,
299 ATA_LOG_SATA_SETTINGS = 0x08, 299 ATA_LOG_SATA_SETTINGS = 0x08,
300 ATA_LOG_DEVSLP_MDAT = 0x30, 300 ATA_LOG_DEVSLP_OFFSET = 0x30,
301 ATA_LOG_DEVSLP_SIZE = 0x08,
302 ATA_LOG_DEVSLP_MDAT = 0x00,
301 ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, 303 ATA_LOG_DEVSLP_MDAT_MASK = 0x1F,
302 ATA_LOG_DEVSLP_DETO = 0x31, 304 ATA_LOG_DEVSLP_DETO = 0x01,
303 ATA_LOG_DEVSLP_VALID = 0x37, 305 ATA_LOG_DEVSLP_VALID = 0x07,
304 ATA_LOG_DEVSLP_VALID_MASK = 0x80, 306 ATA_LOG_DEVSLP_VALID_MASK = 0x80,
305 307
306 /* READ/WRITE LONG (obsolete) */ 308 /* READ/WRITE LONG (obsolete) */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 83ba0ab2c915..649e5f86b5f0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -652,8 +652,8 @@ struct ata_device {
652 u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ 652 u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
653 }; 653 };
654 654
655 /* Identify Device Data Log (30h), SATA Settings (page 08h) */ 655 /* DEVSLP Timing Variables from Identify Device Data Log */
656 u8 sata_settings[ATA_SECT_SIZE]; 656 u8 devslp_timing[ATA_LOG_DEVSLP_SIZE];
657 657
658 /* error history */ 658 /* error history */
659 int spdn_cnt; 659 int spdn_cnt;