提交 6919a0a6 编写于 作者: A Alan Cox 提交者: Jeff Garzik

[PATCH] libata: Revamp blacklist support to allow multiple kinds of blacklisting flaws

Signed-off-by: NAlan Cox <alan@redhat.com>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Tejun Heo <htejun@gmail.com>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 fbbb262d
...@@ -1345,7 +1345,10 @@ static void ata_dev_config_ncq(struct ata_device *dev, ...@@ -1345,7 +1345,10 @@ static void ata_dev_config_ncq(struct ata_device *dev,
desc[0] = '\0'; desc[0] = '\0';
return; return;
} }
if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
snprintf(desc, desc_sz, "NCQ (not used)");
return;
}
if (ap->flags & ATA_FLAG_NCQ) { if (ap->flags & ATA_FLAG_NCQ) {
hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1); hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
dev->flags |= ATA_DFLAG_NCQ; dev->flags |= ATA_DFLAG_NCQ;
...@@ -3014,37 +3017,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset) ...@@ -3014,37 +3017,55 @@ int ata_dev_revalidate(struct ata_device *dev, int post_reset)
return rc; return rc;
} }
static const char * const ata_dma_blacklist [] = { struct ata_blacklist_entry {
"WDC AC11000H", NULL, const char *model_num;
"WDC AC22100H", NULL, const char *model_rev;
"WDC AC32500H", NULL, unsigned long horkage;
"WDC AC33100H", NULL, };
"WDC AC31600H", NULL,
"WDC AC32100H", "24.09P07", static const struct ata_blacklist_entry ata_device_blacklist [] = {
"WDC AC23200L", "21.10N21", /* Devices with DMA related problems under Linux */
"Compaq CRD-8241B", NULL, { "WDC AC11000H", NULL, ATA_HORKAGE_NODMA },
"CRD-8400B", NULL, { "WDC AC22100H", NULL, ATA_HORKAGE_NODMA },
"CRD-8480B", NULL, { "WDC AC32500H", NULL, ATA_HORKAGE_NODMA },
"CRD-8482B", NULL, { "WDC AC33100H", NULL, ATA_HORKAGE_NODMA },
"CRD-84", NULL, { "WDC AC31600H", NULL, ATA_HORKAGE_NODMA },
"SanDisk SDP3B", NULL, { "WDC AC32100H", "24.09P07", ATA_HORKAGE_NODMA },
"SanDisk SDP3B-64", NULL, { "WDC AC23200L", "21.10N21", ATA_HORKAGE_NODMA },
"SANYO CD-ROM CRD", NULL, { "Compaq CRD-8241B", NULL, ATA_HORKAGE_NODMA },
"HITACHI CDR-8", NULL, { "CRD-8400B", NULL, ATA_HORKAGE_NODMA },
"HITACHI CDR-8335", NULL, { "CRD-8480B", NULL, ATA_HORKAGE_NODMA },
"HITACHI CDR-8435", NULL, { "CRD-8482B", NULL, ATA_HORKAGE_NODMA },
"Toshiba CD-ROM XM-6202B", NULL, { "CRD-84", NULL, ATA_HORKAGE_NODMA },
"TOSHIBA CD-ROM XM-1702BC", NULL, { "SanDisk SDP3B", NULL, ATA_HORKAGE_NODMA },
"CD-532E-A", NULL, { "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA },
"E-IDE CD-ROM CR-840", NULL, { "SANYO CD-ROM CRD", NULL, ATA_HORKAGE_NODMA },
"CD-ROM Drive/F5A", NULL, { "HITACHI CDR-8", NULL, ATA_HORKAGE_NODMA },
"WPI CDD-820", NULL, { "HITACHI CDR-8335", NULL, ATA_HORKAGE_NODMA },
"SAMSUNG CD-ROM SC-148C", NULL, { "HITACHI CDR-8435", NULL, ATA_HORKAGE_NODMA },
"SAMSUNG CD-ROM SC", NULL, { "Toshiba CD-ROM XM-6202B", NULL, ATA_HORKAGE_NODMA },
"SanDisk SDP3B-64", NULL, { "TOSHIBA CD-ROM XM-1702BC", NULL, ATA_HORKAGE_NODMA },
"ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, { "CD-532E-A", NULL, ATA_HORKAGE_NODMA },
"_NEC DV5800A", NULL, { "E-IDE CD-ROM CR-840",NULL, ATA_HORKAGE_NODMA },
"SAMSUNG CD-ROM SN-124", "N001" { "CD-ROM Drive/F5A", NULL, ATA_HORKAGE_NODMA },
{ "WPI CDD-820", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SC-148C", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SC", NULL, ATA_HORKAGE_NODMA },
{ "SanDisk SDP3B-64", NULL, ATA_HORKAGE_NODMA },
{ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL,ATA_HORKAGE_NODMA },
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
/* Devices we expect to fail diagnostics */
/* Devices where NCQ should be avoided */
/* NCQ is slow */
{ "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
/* Devices with NCQ limits */
/* End Marker */
{ }
}; };
static int ata_strim(char *s, size_t len) static int ata_strim(char *s, size_t len)
...@@ -3059,20 +3080,12 @@ static int ata_strim(char *s, size_t len) ...@@ -3059,20 +3080,12 @@ static int ata_strim(char *s, size_t len)
return len; return len;
} }
static int ata_dma_blacklisted(const struct ata_device *dev) unsigned long ata_device_blacklisted(const struct ata_device *dev)
{ {
unsigned char model_num[40]; unsigned char model_num[40];
unsigned char model_rev[16]; unsigned char model_rev[16];
unsigned int nlen, rlen; unsigned int nlen, rlen;
int i; const struct ata_blacklist_entry *ad = ata_device_blacklist;
/* We don't support polling DMA.
* DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
* if the LLDD handles only interrupts in the HSM_ST_LAST state.
*/
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
(dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
sizeof(model_num)); sizeof(model_num));
...@@ -3081,17 +3094,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev) ...@@ -3081,17 +3094,30 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
nlen = ata_strim(model_num, sizeof(model_num)); nlen = ata_strim(model_num, sizeof(model_num));
rlen = ata_strim(model_rev, sizeof(model_rev)); rlen = ata_strim(model_rev, sizeof(model_rev));
for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { while (ad->model_num) {
if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { if (!strncmp(ad->model_num, model_num, nlen)) {
if (ata_dma_blacklist[i+1] == NULL) if (ad->model_rev == NULL)
return 1; return ad->horkage;
if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) if (!strncmp(ad->model_rev, model_rev, rlen))
return 1; return ad->horkage;
} }
ad++;
} }
return 0; return 0;
} }
static int ata_dma_blacklisted(const struct ata_device *dev)
{
/* We don't support polling DMA.
* DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
* if the LLDD handles only interrupts in the HSM_ST_LAST state.
*/
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
(dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
}
/** /**
* ata_dev_xfermask - Compute supported xfermask of the given device * ata_dev_xfermask - Compute supported xfermask of the given device
* @dev: Device to compute xfermask for * @dev: Device to compute xfermask for
...@@ -6153,6 +6179,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend); ...@@ -6153,6 +6179,7 @@ EXPORT_SYMBOL_GPL(ata_host_suspend);
EXPORT_SYMBOL_GPL(ata_host_resume); EXPORT_SYMBOL_GPL(ata_host_resume);
EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_device_blacklisted);
EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
......
...@@ -307,6 +307,8 @@ enum { ...@@ -307,6 +307,8 @@ enum {
(some horkage may be drive/controller pair dependant */ (some horkage may be drive/controller pair dependant */
ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */ ATA_HORKAGE_DIAGNOSTIC = (1 << 0), /* Failed boot diag */
ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
}; };
enum hsm_task_states { enum hsm_task_states {
...@@ -787,6 +789,7 @@ extern void ata_id_string(const u16 *id, unsigned char *s, ...@@ -787,6 +789,7 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern void ata_id_c_string(const u16 *id, unsigned char *s, extern void ata_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册