aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c101
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
207static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); 212static 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
620static void ahci_init_port(void __iomem *port_mmio, u32 cap, 608static 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);