Skip to content

Commit 803739d

Browse files
Shane HuangJeff Garzik
authored andcommitted
[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 <[email protected]> Signed-off-by: Shane Huang <[email protected]> Cc: [email protected] Signed-off-by: Jeff Garzik <[email protected]>
1 parent 7f9c9f8 commit 803739d

File tree

4 files changed

+23
-17
lines changed

4 files changed

+23
-17
lines changed

drivers/ata/libahci.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
19511951
/* Use the nominal value 10 ms if the read MDAT is zero,
19521952
* the nominal value of DETO is 20 ms.
19531953
*/
1954-
if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
1954+
if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
19551955
ATA_LOG_DEVSLP_VALID_MASK) {
1956-
mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
1956+
mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
19571957
ATA_LOG_DEVSLP_MDAT_MASK;
19581958
if (!mdat)
19591959
mdat = 10;
1960-
deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
1960+
deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
19611961
if (!deto)
19621962
deto = 20;
19631963
} else {

drivers/ata/libata-core.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev)
23252325
}
23262326
}
23272327

2328-
/* check and mark DevSlp capability */
2329-
if (ata_id_has_devslp(dev->id))
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()
2328+
/* Check and mark DevSlp capability. Get DevSlp timing variables
2329+
* from SATA Settings page of Identify Device Data Log.
23352330
*/
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;
23372336
err_mask = ata_read_log_page(dev,
23382337
ATA_LOG_SATA_ID_DEV_DATA,
23392338
ATA_LOG_SATA_SETTINGS,
2340-
dev->sata_settings,
2339+
sata_setting,
23412340
1);
23422341
if (err_mask)
23432342
ata_dev_dbg(dev,
23442343
"failed to get Identify Device Data, Emask 0x%x\n",
23452344
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+
}
23462350
}
23472351

23482352
dev->cdb_len = 16;

include/linux/ata.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,12 @@ enum {
297297
ATA_LOG_SATA_NCQ = 0x10,
298298
ATA_LOG_SATA_ID_DEV_DATA = 0x30,
299299
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,
301303
ATA_LOG_DEVSLP_MDAT_MASK = 0x1F,
302-
ATA_LOG_DEVSLP_DETO = 0x31,
303-
ATA_LOG_DEVSLP_VALID = 0x37,
304+
ATA_LOG_DEVSLP_DETO = 0x01,
305+
ATA_LOG_DEVSLP_VALID = 0x07,
304306
ATA_LOG_DEVSLP_VALID_MASK = 0x80,
305307

306308
/* READ/WRITE LONG (obsolete) */

include/linux/libata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,8 @@ struct ata_device {
652652
u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
653653
};
654654

655-
/* Identify Device Data Log (30h), SATA Settings (page 08h) */
656-
u8 sata_settings[ATA_SECT_SIZE];
655+
/* DEVSLP Timing Variables from Identify Device Data Log */
656+
u8 devslp_timing[ATA_LOG_DEVSLP_SIZE];
657657

658658
/* error history */
659659
int spdn_cnt;

0 commit comments

Comments
 (0)