diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 101 |
1 files changed, 63 insertions, 38 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index b517d2493551..48616c6fee9d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -75,6 +75,7 @@ enum { | |||
75 | AHCI_CMD_CLR_BUSY = (1 << 10), | 75 | AHCI_CMD_CLR_BUSY = (1 << 10), |
76 | 76 | ||
77 | RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ | 77 | RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ |
78 | RX_FIS_SDB = 0x58, /* offset of SDB FIS data */ | ||
78 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ | 79 | RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ |
79 | 80 | ||
80 | board_ahci = 0, | 81 | board_ahci = 0, |
@@ -202,6 +203,10 @@ struct ahci_port_priv { | |||
202 | dma_addr_t cmd_tbl_dma; | 203 | dma_addr_t cmd_tbl_dma; |
203 | void *rx_fis; | 204 | void *rx_fis; |
204 | dma_addr_t rx_fis_dma; | 205 | dma_addr_t rx_fis_dma; |
206 | /* for NCQ spurious interrupt analysis */ | ||
207 | int ncq_saw_spurious_sdb_cnt; | ||
208 | unsigned int ncq_saw_d2h:1; | ||
209 | unsigned int ncq_saw_dmas:1; | ||
205 | }; | 210 | }; |
206 | 211 | ||
207 | static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); | 212 | static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); |
@@ -361,7 +366,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
361 | { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ | 366 | { PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */ |
362 | { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ | 367 | { PCI_VDEVICE(INTEL, 0x27c5), board_ahci }, /* ICH7M */ |
363 | { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ | 368 | { PCI_VDEVICE(INTEL, 0x27c3), board_ahci }, /* ICH7R */ |
364 | { PCI_VDEVICE(AL, 0x5288), board_ahci }, /* ULi M5288 */ | 369 | { PCI_VDEVICE(AL, 0x5288), board_ahci_ign_iferr }, /* ULi M5288 */ |
365 | { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ | 370 | { PCI_VDEVICE(INTEL, 0x2681), board_ahci }, /* ESB2 */ |
366 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ | 371 | { PCI_VDEVICE(INTEL, 0x2682), board_ahci }, /* ESB2 */ |
367 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ | 372 | { PCI_VDEVICE(INTEL, 0x2683), board_ahci }, /* ESB2 */ |
@@ -586,35 +591,18 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap) | |||
586 | { | 591 | { |
587 | u32 cmd, scontrol; | 592 | u32 cmd, scontrol; |
588 | 593 | ||
589 | cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; | 594 | if (!(cap & HOST_CAP_SSS)) |
590 | 595 | return; | |
591 | if (cap & HOST_CAP_SSC) { | ||
592 | /* enable transitions to slumber mode */ | ||
593 | scontrol = readl(port_mmio + PORT_SCR_CTL); | ||
594 | if ((scontrol & 0x0f00) > 0x100) { | ||
595 | scontrol &= ~0xf00; | ||
596 | writel(scontrol, port_mmio + PORT_SCR_CTL); | ||
597 | } | ||
598 | |||
599 | /* put device into slumber mode */ | ||
600 | writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD); | ||
601 | |||
602 | /* wait for the transition to complete */ | ||
603 | ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER, | ||
604 | PORT_CMD_ICC_SLUMBER, 1, 50); | ||
605 | } | ||
606 | 596 | ||
607 | /* put device into listen mode */ | 597 | /* put device into listen mode, first set PxSCTL.DET to 0 */ |
608 | if (cap & HOST_CAP_SSS) { | 598 | scontrol = readl(port_mmio + PORT_SCR_CTL); |
609 | /* first set PxSCTL.DET to 0 */ | 599 | scontrol &= ~0xf; |
610 | scontrol = readl(port_mmio + PORT_SCR_CTL); | 600 | writel(scontrol, port_mmio + PORT_SCR_CTL); |
611 | scontrol &= ~0xf; | ||
612 | writel(scontrol, port_mmio + PORT_SCR_CTL); | ||
613 | 601 | ||
614 | /* then set PxCMD.SUD to 0 */ | 602 | /* then set PxCMD.SUD to 0 */ |
615 | cmd &= ~PORT_CMD_SPIN_UP; | 603 | cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; |
616 | writel(cmd, port_mmio + PORT_CMD); | 604 | cmd &= ~PORT_CMD_SPIN_UP; |
617 | } | 605 | writel(cmd, port_mmio + PORT_CMD); |
618 | } | 606 | } |
619 | 607 | ||
620 | static void ahci_init_port(void __iomem *port_mmio, u32 cap, | 608 | static void ahci_init_port(void __iomem *port_mmio, u32 cap, |
@@ -915,7 +903,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) | |||
915 | 903 | ||
916 | /* clear D2H reception area to properly wait for D2H FIS */ | 904 | /* clear D2H reception area to properly wait for D2H FIS */ |
917 | ata_tf_init(ap->device, &tf); | 905 | ata_tf_init(ap->device, &tf); |
918 | tf.command = 0xff; | 906 | tf.command = 0x80; |
919 | ata_tf_to_fis(&tf, d2h_fis, 0); | 907 | ata_tf_to_fis(&tf, d2h_fis, 0); |
920 | 908 | ||
921 | rc = sata_std_hardreset(ap, class); | 909 | rc = sata_std_hardreset(ap, class); |
@@ -1126,8 +1114,9 @@ static void ahci_host_intr(struct ata_port *ap) | |||
1126 | void __iomem *mmio = ap->host->mmio_base; | 1114 | void __iomem *mmio = ap->host->mmio_base; |
1127 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); | 1115 | void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); |
1128 | struct ata_eh_info *ehi = &ap->eh_info; | 1116 | struct ata_eh_info *ehi = &ap->eh_info; |
1117 | struct ahci_port_priv *pp = ap->private_data; | ||
1129 | u32 status, qc_active; | 1118 | u32 status, qc_active; |
1130 | int rc; | 1119 | int rc, known_irq = 0; |
1131 | 1120 | ||
1132 | status = readl(port_mmio + PORT_IRQ_STAT); | 1121 | status = readl(port_mmio + PORT_IRQ_STAT); |
1133 | writel(status, port_mmio + PORT_IRQ_STAT); | 1122 | writel(status, port_mmio + PORT_IRQ_STAT); |
@@ -1154,17 +1143,53 @@ static void ahci_host_intr(struct ata_port *ap) | |||
1154 | 1143 | ||
1155 | /* hmmm... a spurious interupt */ | 1144 | /* hmmm... a spurious interupt */ |
1156 | 1145 | ||
1157 | /* some devices send D2H reg with I bit set during NCQ command phase */ | 1146 | /* if !NCQ, ignore. No modern ATA device has broken HSM |
1158 | if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS)) | 1147 | * implementation for non-NCQ commands. |
1148 | */ | ||
1149 | if (!ap->sactive) | ||
1159 | return; | 1150 | return; |
1160 | 1151 | ||
1161 | /* ignore interim PIO setup fis interrupts */ | 1152 | if (status & PORT_IRQ_D2H_REG_FIS) { |
1162 | if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) | 1153 | if (!pp->ncq_saw_d2h) |
1163 | return; | 1154 | ata_port_printk(ap, KERN_INFO, |
1155 | "D2H reg with I during NCQ, " | ||
1156 | "this message won't be printed again\n"); | ||
1157 | pp->ncq_saw_d2h = 1; | ||
1158 | known_irq = 1; | ||
1159 | } | ||
1160 | |||
1161 | if (status & PORT_IRQ_DMAS_FIS) { | ||
1162 | if (!pp->ncq_saw_dmas) | ||
1163 | ata_port_printk(ap, KERN_INFO, | ||
1164 | "DMAS FIS during NCQ, " | ||
1165 | "this message won't be printed again\n"); | ||
1166 | pp->ncq_saw_dmas = 1; | ||
1167 | known_irq = 1; | ||
1168 | } | ||
1169 | |||
1170 | if (status & PORT_IRQ_SDB_FIS && | ||
1171 | pp->ncq_saw_spurious_sdb_cnt < 10) { | ||
1172 | /* SDB FIS containing spurious completions might be | ||
1173 | * dangerous, we need to know more about them. Print | ||
1174 | * more of it. | ||
1175 | */ | ||
1176 | const u32 *f = pp->rx_fis + RX_FIS_SDB; | ||
1177 | |||
1178 | ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ " | ||
1179 | "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n", | ||
1180 | readl(port_mmio + PORT_CMD_ISSUE), | ||
1181 | readl(port_mmio + PORT_SCR_ACT), | ||
1182 | le32_to_cpu(f[0]), le32_to_cpu(f[1]), | ||
1183 | pp->ncq_saw_spurious_sdb_cnt < 10 ? | ||
1184 | "" : ", shutting up"); | ||
1185 | |||
1186 | pp->ncq_saw_spurious_sdb_cnt++; | ||
1187 | known_irq = 1; | ||
1188 | } | ||
1164 | 1189 | ||
1165 | if (ata_ratelimit()) | 1190 | if (!known_irq) |
1166 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " | 1191 | ata_port_printk(ap, KERN_INFO, "spurious interrupt " |
1167 | "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", | 1192 | "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n", |
1168 | status, ap->active_tag, ap->sactive); | 1193 | status, ap->active_tag, ap->sactive); |
1169 | } | 1194 | } |
1170 | 1195 | ||
@@ -1257,7 +1282,7 @@ static void ahci_thaw(struct ata_port *ap) | |||
1257 | /* clear IRQ */ | 1282 | /* clear IRQ */ |
1258 | tmp = readl(port_mmio + PORT_IRQ_STAT); | 1283 | tmp = readl(port_mmio + PORT_IRQ_STAT); |
1259 | writel(tmp, port_mmio + PORT_IRQ_STAT); | 1284 | writel(tmp, port_mmio + PORT_IRQ_STAT); |
1260 | writel(1 << ap->id, mmio + HOST_IRQ_STAT); | 1285 | writel(1 << ap->port_no, mmio + HOST_IRQ_STAT); |
1261 | 1286 | ||
1262 | /* turn IRQ back on */ | 1287 | /* turn IRQ back on */ |
1263 | writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); | 1288 | writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); |