diff options
author | Tejun Heo <htejun@gmail.com> | 2006-11-28 21:33:14 -0500 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-11-29 00:57:44 -0500 |
commit | 41669553353554211310cdb23079d58af1fda41e (patch) | |
tree | 2aace00509badc17ad432fa5e2b83f56b6d7453e | |
parent | 08475a1920aa7acc535324d6991b830fa7625bd8 (diff) |
[PATCH] ahci: ignore PORT_IRQ_IF_ERR on JMB controllers
JMicron AHCI controllers set PORT_IRQ_IF_ERR on device errors. The
IRQ status bit indicates interface error or protocol mismatch and ahci
driver interprets it into AC_ERR_ATA_BUS. So, whenever an ATAPI
device raises check condition, ahci interprets it as ATA bus error and
thus resets it which, in turn, raises check condition thus creating a
reset loop and rendering the device unuseable.
This patch makes JMB controllers ignore PORT_IRQ_IF_ERR when
interpreting error condition.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Justin Tsai <justin@jmicron.com>
-rw-r--r-- | drivers/ata/ahci.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f510e1196dc6..bddb14e91d3c 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -78,6 +78,7 @@ enum { | |||
78 | 78 | ||
79 | board_ahci = 0, | 79 | board_ahci = 0, |
80 | board_ahci_vt8251 = 1, | 80 | board_ahci_vt8251 = 1, |
81 | board_ahci_ign_iferr = 2, | ||
81 | 82 | ||
82 | /* global controller registers */ | 83 | /* global controller registers */ |
83 | HOST_CAP = 0x00, /* host capabilities */ | 84 | HOST_CAP = 0x00, /* host capabilities */ |
@@ -168,6 +169,7 @@ enum { | |||
168 | /* ap->flags bits */ | 169 | /* ap->flags bits */ |
169 | AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), | 170 | AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), |
170 | AHCI_FLAG_NO_NCQ = (1 << 25), | 171 | AHCI_FLAG_NO_NCQ = (1 << 25), |
172 | AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */ | ||
171 | }; | 173 | }; |
172 | 174 | ||
173 | struct ahci_cmd_hdr { | 175 | struct ahci_cmd_hdr { |
@@ -295,6 +297,17 @@ static const struct ata_port_info ahci_port_info[] = { | |||
295 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 297 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
296 | .port_ops = &ahci_ops, | 298 | .port_ops = &ahci_ops, |
297 | }, | 299 | }, |
300 | /* board_ahci_ign_iferr */ | ||
301 | { | ||
302 | .sht = &ahci_sht, | ||
303 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | ||
304 | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | | ||
305 | ATA_FLAG_SKIP_D2H_BSY | | ||
306 | AHCI_FLAG_IGN_IRQ_IF_ERR, | ||
307 | .pio_mask = 0x1f, /* pio0-4 */ | ||
308 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | ||
309 | .port_ops = &ahci_ops, | ||
310 | }, | ||
298 | }; | 311 | }; |
299 | 312 | ||
300 | static const struct pci_device_id ahci_pci_tbl[] = { | 313 | static const struct pci_device_id ahci_pci_tbl[] = { |
@@ -327,11 +340,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
327 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ | 340 | { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ |
328 | 341 | ||
329 | /* JMicron */ | 342 | /* JMicron */ |
330 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */ | 343 | { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ |
331 | { PCI_VDEVICE(JMICRON, 0x2361), board_ahci }, /* JMicron JMB361 */ | 344 | { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */ |
332 | { PCI_VDEVICE(JMICRON, 0x2363), board_ahci }, /* JMicron JMB363 */ | 345 | { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */ |
333 | { PCI_VDEVICE(JMICRON, 0x2365), board_ahci }, /* JMicron JMB365 */ | 346 | { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */ |
334 | { PCI_VDEVICE(JMICRON, 0x2366), board_ahci }, /* JMicron JMB366 */ | 347 | { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */ |
335 | 348 | ||
336 | /* ATI */ | 349 | /* ATI */ |
337 | { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ | 350 | { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ |
@@ -980,6 +993,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | |||
980 | /* analyze @irq_stat */ | 993 | /* analyze @irq_stat */ |
981 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); | 994 | ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); |
982 | 995 | ||
996 | /* some controllers set IRQ_IF_ERR on device errors, ignore it */ | ||
997 | if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) | ||
998 | irq_stat &= ~PORT_IRQ_IF_ERR; | ||
999 | |||
983 | if (irq_stat & PORT_IRQ_TF_ERR) | 1000 | if (irq_stat & PORT_IRQ_TF_ERR) |
984 | err_mask |= AC_ERR_DEV; | 1001 | err_mask |= AC_ERR_DEV; |
985 | 1002 | ||