aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-28 21:33:14 -0500
committerTejun Heo <htejun@gmail.com>2006-11-29 00:57:44 -0500
commit41669553353554211310cdb23079d58af1fda41e (patch)
tree2aace00509badc17ad432fa5e2b83f56b6d7453e /drivers
parent08475a1920aa7acc535324d6991b830fa7625bd8 (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c27
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
173struct ahci_cmd_hdr { 175struct 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
300static const struct pci_device_id ahci_pci_tbl[] = { 313static 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