Skip to content

Commit 7a8526a

Browse files
Kate Hsuanaxboe
authored andcommitted
libata: Add ATA_HORKAGE_NO_NCQ_ON_ATI for Samsung 860 and 870 SSD.
Many users are reporting that the Samsung 860 and 870 SSD are having various issues when combined with AMD/ATI (vendor ID 0x1002) SATA controllers and only completely disabling NCQ helps to avoid these issues. Always disabling NCQ for Samsung 860/870 SSDs regardless of the host SATA adapter vendor will cause I/O performance degradation with well behaved adapters. To limit the performance impact to ATI adapters, introduce the ATA_HORKAGE_NO_NCQ_ON_ATI flag to force disable NCQ only for these adapters. Also, two libata.force parameters (noncqati and ncqati) are introduced to disable and enable the NCQ for the system which equipped with ATI SATA adapter and Samsung 860 and 870 SSDs. The user can determine NCQ function to be enabled or disabled according to the demand. After verifying the chipset from the user reports, the issue appears on AMD/ATI SB7x0/SB8x0/SB9x0 SATA Controllers and does not appear on recent AMD SATA adapters. The vendor ID of ATI should be 0x1002. Therefore, ATA_HORKAGE_NO_NCQ_ON_AMD was modified to ATA_HORKAGE_NO_NCQ_ON_ATI. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=201693 Signed-off-by: Kate Hsuan <[email protected]> Reviewed-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Martin K. Petersen <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 8a6430a commit 7a8526a

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

drivers/ata/libata-core.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,25 @@ static void ata_dev_config_ncq_prio(struct ata_device *dev)
21862186
dev->flags &= ~ATA_DFLAG_NCQ_PRIO;
21872187
}
21882188

2189+
static bool ata_dev_check_adapter(struct ata_device *dev,
2190+
unsigned short vendor_id)
2191+
{
2192+
struct pci_dev *pcidev = NULL;
2193+
struct device *parent_dev = NULL;
2194+
2195+
for (parent_dev = dev->tdev.parent; parent_dev != NULL;
2196+
parent_dev = parent_dev->parent) {
2197+
if (dev_is_pci(parent_dev)) {
2198+
pcidev = to_pci_dev(parent_dev);
2199+
if (pcidev->vendor == vendor_id)
2200+
return true;
2201+
break;
2202+
}
2203+
}
2204+
2205+
return false;
2206+
}
2207+
21892208
static int ata_dev_config_ncq(struct ata_device *dev,
21902209
char *desc, size_t desc_sz)
21912210
{
@@ -2204,6 +2223,13 @@ static int ata_dev_config_ncq(struct ata_device *dev,
22042223
snprintf(desc, desc_sz, "NCQ (not used)");
22052224
return 0;
22062225
}
2226+
2227+
if (dev->horkage & ATA_HORKAGE_NO_NCQ_ON_ATI &&
2228+
ata_dev_check_adapter(dev, PCI_VENDOR_ID_ATI)) {
2229+
snprintf(desc, desc_sz, "NCQ (not used)");
2230+
return 0;
2231+
}
2232+
22072233
if (ap->flags & ATA_FLAG_NCQ) {
22082234
hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE);
22092235
dev->flags |= ATA_DFLAG_NCQ;
@@ -3971,9 +3997,11 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
39713997
{ "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
39723998
ATA_HORKAGE_ZERO_AFTER_TRIM, },
39733999
{ "Samsung SSD 860*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
3974-
ATA_HORKAGE_ZERO_AFTER_TRIM, },
4000+
ATA_HORKAGE_ZERO_AFTER_TRIM |
4001+
ATA_HORKAGE_NO_NCQ_ON_ATI, },
39754002
{ "Samsung SSD 870*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
3976-
ATA_HORKAGE_ZERO_AFTER_TRIM, },
4003+
ATA_HORKAGE_ZERO_AFTER_TRIM |
4004+
ATA_HORKAGE_NO_NCQ_ON_ATI, },
39774005
{ "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
39784006
ATA_HORKAGE_ZERO_AFTER_TRIM, },
39794007

@@ -6128,6 +6156,8 @@ static int __init ata_parse_force_one(char **cur,
61286156
{ "ncq", .horkage_off = ATA_HORKAGE_NONCQ },
61296157
{ "noncqtrim", .horkage_on = ATA_HORKAGE_NO_NCQ_TRIM },
61306158
{ "ncqtrim", .horkage_off = ATA_HORKAGE_NO_NCQ_TRIM },
6159+
{ "noncqati", .horkage_on = ATA_HORKAGE_NO_NCQ_ON_ATI },
6160+
{ "ncqati", .horkage_off = ATA_HORKAGE_NO_NCQ_ON_ATI },
61316161
{ "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID },
61326162
{ "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) },
61336163
{ "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) },

include/linux/libata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ enum {
426426
ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */
427427
ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */
428428
ATA_HORKAGE_MAX_TRIM_128M = (1 << 26), /* Limit max trim size to 128M */
429+
ATA_HORKAGE_NO_NCQ_ON_ATI = (1 << 27), /* Disable NCQ on ATI chipset */
429430

430431
/* DMA mask for user DMA control: User visible values; DO NOT
431432
renumber */

0 commit comments

Comments
 (0)