aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ahci.c237
1 files changed, 137 insertions, 100 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index a4fb8d0a6c08..d6894bd67980 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -71,6 +71,7 @@ enum {
71 AHCI_CMD_CLR_BUSY = (1 << 10), 71 AHCI_CMD_CLR_BUSY = (1 << 10),
72 72
73 RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ 73 RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
74 RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */
74 75
75 board_ahci = 0, 76 board_ahci = 0,
76 board_ahci_vt8251 = 1, 77 board_ahci_vt8251 = 1,
@@ -128,15 +129,16 @@ enum {
128 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */ 129 PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
129 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */ 130 PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
130 131
131 PORT_IRQ_FATAL = PORT_IRQ_TF_ERR | 132 PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
132 PORT_IRQ_HBUS_ERR | 133 PORT_IRQ_IF_ERR |
133 PORT_IRQ_HBUS_DATA_ERR | 134 PORT_IRQ_CONNECT |
134 PORT_IRQ_IF_ERR, 135 PORT_IRQ_UNK_FIS,
135 DEF_PORT_IRQ = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY | 136 PORT_IRQ_ERROR = PORT_IRQ_FREEZE |
136 PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE | 137 PORT_IRQ_TF_ERR |
137 PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS | 138 PORT_IRQ_HBUS_DATA_ERR,
138 PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS | 139 DEF_PORT_IRQ = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
139 PORT_IRQ_D2H_REG_FIS, 140 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
141 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
140 142
141 /* PORT_CMD bits */ 143 /* PORT_CMD bits */
142 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ 144 PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
@@ -197,13 +199,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
197static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); 199static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
198static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); 200static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
199static void ahci_irq_clear(struct ata_port *ap); 201static void ahci_irq_clear(struct ata_port *ap);
200static void ahci_eng_timeout(struct ata_port *ap);
201static int ahci_port_start(struct ata_port *ap); 202static int ahci_port_start(struct ata_port *ap);
202static void ahci_port_stop(struct ata_port *ap); 203static void ahci_port_stop(struct ata_port *ap);
203static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); 204static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
204static void ahci_qc_prep(struct ata_queued_cmd *qc); 205static void ahci_qc_prep(struct ata_queued_cmd *qc);
205static u8 ahci_check_status(struct ata_port *ap); 206static u8 ahci_check_status(struct ata_port *ap);
206static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); 207static void ahci_freeze(struct ata_port *ap);
208static void ahci_thaw(struct ata_port *ap);
209static void ahci_error_handler(struct ata_port *ap);
210static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
207static void ahci_remove_one (struct pci_dev *pdev); 211static void ahci_remove_one (struct pci_dev *pdev);
208 212
209static struct scsi_host_template ahci_sht = { 213static struct scsi_host_template ahci_sht = {
@@ -237,14 +241,18 @@ static const struct ata_port_operations ahci_ops = {
237 .qc_prep = ahci_qc_prep, 241 .qc_prep = ahci_qc_prep,
238 .qc_issue = ahci_qc_issue, 242 .qc_issue = ahci_qc_issue,
239 243
240 .eng_timeout = ahci_eng_timeout,
241
242 .irq_handler = ahci_interrupt, 244 .irq_handler = ahci_interrupt,
243 .irq_clear = ahci_irq_clear, 245 .irq_clear = ahci_irq_clear,
244 246
245 .scr_read = ahci_scr_read, 247 .scr_read = ahci_scr_read,
246 .scr_write = ahci_scr_write, 248 .scr_write = ahci_scr_write,
247 249
250 .freeze = ahci_freeze,
251 .thaw = ahci_thaw,
252
253 .error_handler = ahci_error_handler,
254 .post_internal_cmd = ahci_post_internal_cmd,
255
248 .port_start = ahci_port_start, 256 .port_start = ahci_port_start,
249 .port_stop = ahci_port_stop, 257 .port_stop = ahci_port_stop,
250}; 258};
@@ -789,108 +797,97 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
789 ahci_fill_cmd_slot(pp, opts); 797 ahci_fill_cmd_slot(pp, opts);
790} 798}
791 799
792static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) 800static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
793{ 801{
794 void __iomem *mmio = ap->host_set->mmio_base; 802 struct ahci_port_priv *pp = ap->private_data;
795 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 803 struct ata_eh_info *ehi = &ap->eh_info;
796 u32 tmp; 804 unsigned int err_mask = 0, action = 0;
805 struct ata_queued_cmd *qc;
806 u32 serror;
797 807
798 if ((ap->device[0].class != ATA_DEV_ATAPI) || 808 ata_ehi_clear_desc(ehi);
799 ((irq_stat & PORT_IRQ_TF_ERR) == 0))
800 ata_port_printk(ap, KERN_WARNING, "port reset, "
801 "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
802 irq_stat,
803 readl(mmio + HOST_IRQ_STAT),
804 readl(port_mmio + PORT_IRQ_STAT),
805 readl(port_mmio + PORT_CMD),
806 readl(port_mmio + PORT_TFDATA),
807 readl(port_mmio + PORT_SCR_STAT),
808 readl(port_mmio + PORT_SCR_ERR));
809
810 /* stop DMA */
811 ahci_stop_engine(ap);
812 809
813 /* clear SATA phy error, if any */ 810 /* AHCI needs SError cleared; otherwise, it might lock up */
814 tmp = readl(port_mmio + PORT_SCR_ERR); 811 serror = ahci_scr_read(ap, SCR_ERROR);
815 writel(tmp, port_mmio + PORT_SCR_ERR); 812 ahci_scr_write(ap, SCR_ERROR, serror);
816 813
817 /* if DRQ/BSY is set, device needs to be reset. 814 /* analyze @irq_stat */
818 * if so, issue COMRESET 815 ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
819 */ 816
820 tmp = readl(port_mmio + PORT_TFDATA); 817 if (irq_stat & PORT_IRQ_TF_ERR)
821 if (tmp & (ATA_BUSY | ATA_DRQ)) { 818 err_mask |= AC_ERR_DEV;
822 writel(0x301, port_mmio + PORT_SCR_CTL); 819
823 readl(port_mmio + PORT_SCR_CTL); /* flush */ 820 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
824 udelay(10); 821 err_mask |= AC_ERR_HOST_BUS;
825 writel(0x300, port_mmio + PORT_SCR_CTL); 822 action |= ATA_EH_SOFTRESET;
826 readl(port_mmio + PORT_SCR_CTL); /* flush */
827 } 823 }
828 824
829 /* re-start DMA */ 825 if (irq_stat & PORT_IRQ_IF_ERR) {
830 ahci_start_engine(ap); 826 err_mask |= AC_ERR_ATA_BUS;
831} 827 action |= ATA_EH_SOFTRESET;
828 ata_ehi_push_desc(ehi, ", interface fatal error");
829 }
832 830
833static void ahci_eng_timeout(struct ata_port *ap) 831 if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
834{ 832 err_mask |= AC_ERR_ATA_BUS;
835 struct ata_host_set *host_set = ap->host_set; 833 action |= ATA_EH_SOFTRESET;
836 void __iomem *mmio = host_set->mmio_base; 834 ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
837 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 835 "connection status changed" : "PHY RDY changed");
838 struct ata_queued_cmd *qc; 836 }
839 unsigned long flags; 837
838 if (irq_stat & PORT_IRQ_UNK_FIS) {
839 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
840 840
841 ata_port_printk(ap, KERN_WARNING, "handling error/timeout\n"); 841 err_mask |= AC_ERR_HSM;
842 action |= ATA_EH_SOFTRESET;
843 ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
844 unk[0], unk[1], unk[2], unk[3]);
845 }
842 846
843 spin_lock_irqsave(&host_set->lock, flags); 847 /* okay, let's hand over to EH */
848 ehi->serror |= serror;
849 ehi->action |= action;
844 850
845 ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
846 qc = ata_qc_from_tag(ap, ap->active_tag); 851 qc = ata_qc_from_tag(ap, ap->active_tag);
847 qc->err_mask |= AC_ERR_TIMEOUT; 852 if (qc)
848 853 qc->err_mask |= err_mask;
849 spin_unlock_irqrestore(&host_set->lock, flags); 854 else
855 ehi->err_mask |= err_mask;
850 856
851 ata_eh_qc_complete(qc); 857 if (irq_stat & PORT_IRQ_FREEZE)
858 ata_port_freeze(ap);
859 else
860 ata_port_abort(ap);
852} 861}
853 862
854static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) 863static void ahci_host_intr(struct ata_port *ap)
855{ 864{
856 void __iomem *mmio = ap->host_set->mmio_base; 865 void __iomem *mmio = ap->host_set->mmio_base;
857 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 866 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
858 u32 status, serr, ci; 867 struct ata_queued_cmd *qc;
859 868 u32 status, ci;
860 serr = readl(port_mmio + PORT_SCR_ERR);
861 writel(serr, port_mmio + PORT_SCR_ERR);
862 869
863 status = readl(port_mmio + PORT_IRQ_STAT); 870 status = readl(port_mmio + PORT_IRQ_STAT);
864 writel(status, port_mmio + PORT_IRQ_STAT); 871 writel(status, port_mmio + PORT_IRQ_STAT);
865 872
866 ci = readl(port_mmio + PORT_CMD_ISSUE); 873 if (unlikely(status & PORT_IRQ_ERROR)) {
867 if (likely((ci & 0x1) == 0)) { 874 ahci_error_intr(ap, status);
868 if (qc) { 875 return;
869 WARN_ON(qc->err_mask);
870 ata_qc_complete(qc);
871 qc = NULL;
872 }
873 } 876 }
874 877
875 if (status & PORT_IRQ_FATAL) { 878 if ((qc = ata_qc_from_tag(ap, ap->active_tag))) {
876 unsigned int err_mask; 879 ci = readl(port_mmio + PORT_CMD_ISSUE);
877 if (status & PORT_IRQ_TF_ERR) 880 if ((ci & 0x1) == 0) {
878 err_mask = AC_ERR_DEV;
879 else if (status & PORT_IRQ_IF_ERR)
880 err_mask = AC_ERR_ATA_BUS;
881 else
882 err_mask = AC_ERR_HOST_BUS;
883
884 /* command processing has stopped due to error; restart */
885 ahci_restart_port(ap, status);
886
887 if (qc) {
888 qc->err_mask |= err_mask;
889 ata_qc_complete(qc); 881 ata_qc_complete(qc);
882 return;
890 } 883 }
891 } 884 }
892 885
893 return 1; 886 /* spurious interrupt */
887 if (ata_ratelimit())
888 ata_port_printk(ap, KERN_INFO, "spurious interrupt "
889 "(irq_stat 0x%x active_tag %d)\n",
890 status, ap->active_tag);
894} 891}
895 892
896static void ahci_irq_clear(struct ata_port *ap) 893static void ahci_irq_clear(struct ata_port *ap)
@@ -927,14 +924,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
927 924
928 ap = host_set->ports[i]; 925 ap = host_set->ports[i];
929 if (ap) { 926 if (ap) {
930 struct ata_queued_cmd *qc; 927 ahci_host_intr(ap);
931 qc = ata_qc_from_tag(ap, ap->active_tag);
932 if (!ahci_host_intr(ap, qc))
933 if (ata_ratelimit())
934 dev_printk(KERN_WARNING, host_set->dev,
935 "unhandled interrupt on port %u\n",
936 i);
937
938 VPRINTK("port %u\n", i); 928 VPRINTK("port %u\n", i);
939 } else { 929 } else {
940 VPRINTK("port %u (no irq)\n", i); 930 VPRINTK("port %u (no irq)\n", i);
@@ -951,7 +941,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
951 handled = 1; 941 handled = 1;
952 } 942 }
953 943
954 spin_unlock(&host_set->lock); 944 spin_unlock(&host_set->lock);
955 945
956 VPRINTK("EXIT\n"); 946 VPRINTK("EXIT\n");
957 947
@@ -969,6 +959,56 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
969 return 0; 959 return 0;
970} 960}
971 961
962static void ahci_freeze(struct ata_port *ap)
963{
964 void __iomem *mmio = ap->host_set->mmio_base;
965 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
966
967 /* turn IRQ off */
968 writel(0, port_mmio + PORT_IRQ_MASK);
969}
970
971static void ahci_thaw(struct ata_port *ap)
972{
973 void __iomem *mmio = ap->host_set->mmio_base;
974 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
975 u32 tmp;
976
977 /* clear IRQ */
978 tmp = readl(port_mmio + PORT_IRQ_STAT);
979 writel(tmp, port_mmio + PORT_IRQ_STAT);
980 writel(1 << ap->id, mmio + HOST_IRQ_STAT);
981
982 /* turn IRQ back on */
983 writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
984}
985
986static void ahci_error_handler(struct ata_port *ap)
987{
988 if (!(ap->flags & ATA_FLAG_FROZEN)) {
989 /* restart engine */
990 ahci_stop_engine(ap);
991 ahci_start_engine(ap);
992 }
993
994 /* perform recovery */
995 ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset);
996}
997
998static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
999{
1000 struct ata_port *ap = qc->ap;
1001
1002 if (qc->flags & ATA_QCFLAG_FAILED)
1003 qc->err_mask |= AC_ERR_OTHER;
1004
1005 if (qc->err_mask) {
1006 /* make DMA engine forget about the failed command */
1007 ahci_stop_engine(ap);
1008 ahci_start_engine(ap);
1009 }
1010}
1011
972static void ahci_setup_port(struct ata_ioports *port, unsigned long base, 1012static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
973 unsigned int port_idx) 1013 unsigned int port_idx)
974{ 1014{
@@ -1113,9 +1153,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
1113 writel(tmp, port_mmio + PORT_IRQ_STAT); 1153 writel(tmp, port_mmio + PORT_IRQ_STAT);
1114 1154
1115 writel(1 << i, mmio + HOST_IRQ_STAT); 1155 writel(1 << i, mmio + HOST_IRQ_STAT);
1116
1117 /* set irq mask (enables interrupts) */
1118 writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
1119 } 1156 }
1120 1157
1121 tmp = readl(mmio + HOST_CTL); 1158 tmp = readl(mmio + HOST_CTL);