aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2009-04-08 16:02:18 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-05-15 14:05:22 -0400
commit67651ee5710c45ea62fae68b768d65395ccf47c2 (patch)
tree91232a79eb11e7f68091cf4c062a97b250e58553
parent5d41343ac88eeddd25dc4ffb7050c9095c41a70d (diff)
[libata] sata_sx4: convert to new exception handling methods
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/sata_sx4.c166
1 files changed, 121 insertions, 45 deletions
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index dce3dccced3f..1ce98afa69b6 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -213,8 +213,9 @@ struct pdc_host_priv {
213 213
214 214
215static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 215static int pdc_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
216static void pdc_eng_timeout(struct ata_port *ap); 216static void pdc_error_handler(struct ata_port *ap);
217static void pdc_20621_phy_reset(struct ata_port *ap); 217static void pdc_freeze(struct ata_port *ap);
218static void pdc_thaw(struct ata_port *ap);
218static int pdc_port_start(struct ata_port *ap); 219static int pdc_port_start(struct ata_port *ap);
219static void pdc20621_qc_prep(struct ata_queued_cmd *qc); 220static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
220static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); 221static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
@@ -233,6 +234,10 @@ static void pdc20621_put_to_dimm(struct ata_host *host,
233 void *psource, u32 offset, u32 size); 234 void *psource, u32 offset, u32 size);
234static void pdc20621_irq_clear(struct ata_port *ap); 235static void pdc20621_irq_clear(struct ata_port *ap);
235static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc); 236static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc);
237static int pdc_softreset(struct ata_link *link, unsigned int *class,
238 unsigned long deadline);
239static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
240static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
236 241
237 242
238static struct scsi_host_template pdc_sata_sht = { 243static struct scsi_host_template pdc_sata_sht = {
@@ -243,20 +248,24 @@ static struct scsi_host_template pdc_sata_sht = {
243 248
244/* TODO: inherit from base port_ops after converting to new EH */ 249/* TODO: inherit from base port_ops after converting to new EH */
245static struct ata_port_operations pdc_20621_ops = { 250static struct ata_port_operations pdc_20621_ops = {
246 .sff_tf_load = pdc_tf_load_mmio, 251 .inherits = &ata_sff_port_ops,
247 .sff_tf_read = ata_sff_tf_read, 252
248 .sff_check_status = ata_sff_check_status, 253 .check_atapi_dma = pdc_check_atapi_dma,
249 .sff_exec_command = pdc_exec_command_mmio,
250 .sff_dev_select = ata_sff_dev_select,
251 .phy_reset = pdc_20621_phy_reset,
252 .qc_prep = pdc20621_qc_prep, 254 .qc_prep = pdc20621_qc_prep,
253 .qc_issue = pdc20621_qc_issue, 255 .qc_issue = pdc20621_qc_issue,
254 .qc_fill_rtf = ata_sff_qc_fill_rtf, 256
255 .sff_data_xfer = ata_sff_data_xfer, 257 .freeze = pdc_freeze,
256 .eng_timeout = pdc_eng_timeout, 258 .thaw = pdc_thaw,
257 .sff_irq_clear = pdc20621_irq_clear, 259 .softreset = pdc_softreset,
258 .sff_irq_on = ata_sff_irq_on, 260 .error_handler = pdc_error_handler,
261 .lost_interrupt = ATA_OP_NULL,
262 .post_internal_cmd = pdc_post_internal_cmd,
263
259 .port_start = pdc_port_start, 264 .port_start = pdc_port_start,
265
266 .sff_tf_load = pdc_tf_load_mmio,
267 .sff_exec_command = pdc_exec_command_mmio,
268 .sff_irq_clear = pdc20621_irq_clear,
260}; 269};
261 270
262static const struct ata_port_info pdc_port_info[] = { 271static const struct ata_port_info pdc_port_info[] = {
@@ -310,14 +319,6 @@ static int pdc_port_start(struct ata_port *ap)
310 return 0; 319 return 0;
311} 320}
312 321
313static void pdc_20621_phy_reset(struct ata_port *ap)
314{
315 VPRINTK("ENTER\n");
316 ap->cbl = ATA_CBL_SATA;
317 ata_port_probe(ap);
318 ata_bus_reset(ap);
319}
320
321static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf, 322static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
322 unsigned int portno, 323 unsigned int portno,
323 unsigned int total_len) 324 unsigned int total_len)
@@ -859,40 +860,115 @@ static irqreturn_t pdc20621_interrupt(int irq, void *dev_instance)
859 return IRQ_RETVAL(handled); 860 return IRQ_RETVAL(handled);
860} 861}
861 862
862static void pdc_eng_timeout(struct ata_port *ap) 863static void pdc_freeze(struct ata_port *ap)
863{ 864{
864 u8 drv_stat; 865 void __iomem *mmio = ap->ioaddr.cmd_addr;
865 struct ata_host *host = ap->host; 866 u32 tmp;
866 struct ata_queued_cmd *qc;
867 unsigned long flags;
868 867
869 DPRINTK("ENTER\n"); 868 /* FIXME: if all 4 ATA engines are stopped, also stop HDMA engine */
870 869
871 spin_lock_irqsave(&host->lock, flags); 870 tmp = readl(mmio + PDC_CTLSTAT);
871 tmp |= PDC_MASK_INT;
872 tmp &= ~PDC_DMA_ENABLE;
873 writel(tmp, mmio + PDC_CTLSTAT);
874 readl(mmio + PDC_CTLSTAT); /* flush */
875}
872 876
873 qc = ata_qc_from_tag(ap, ap->link.active_tag); 877static void pdc_thaw(struct ata_port *ap)
878{
879 void __iomem *mmio = ap->ioaddr.cmd_addr;
880 void __iomem *mmio_base;
881 u32 tmp;
874 882
875 switch (qc->tf.protocol) { 883 /* FIXME: start HDMA engine, if zero ATA engines running */
876 case ATA_PROT_DMA:
877 case ATA_PROT_NODATA:
878 ata_port_printk(ap, KERN_ERR, "command timeout\n");
879 qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
880 break;
881 884
882 default: 885 /* reading SEQ mask register clears IRQ */
883 drv_stat = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); 886 mmio_base = ap->host->iomap[PDC_MMIO_BAR] + PDC_CHIP0_OFS;
887 readl(mmio_base + PDC_20621_SEQMASK);
884 888
885 ata_port_printk(ap, KERN_ERR, 889 /* turn IRQ back on */
886 "unknown timeout, cmd 0x%x stat 0x%x\n", 890 tmp = readl(mmio + PDC_CTLSTAT);
887 qc->tf.command, drv_stat); 891 tmp &= ~PDC_MASK_INT;
892 writel(tmp, mmio + PDC_CTLSTAT);
893 readl(mmio + PDC_CTLSTAT); /* flush */
894}
888 895
889 qc->err_mask |= ac_err_mask(drv_stat); 896static void pdc_reset_port(struct ata_port *ap)
890 break; 897{
898 void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
899 unsigned int i;
900 u32 tmp;
901
902 /* FIXME: handle HDMA copy engine */
903
904 for (i = 11; i > 0; i--) {
905 tmp = readl(mmio);
906 if (tmp & PDC_RESET)
907 break;
908
909 udelay(100);
910
911 tmp |= PDC_RESET;
912 writel(tmp, mmio);
891 } 913 }
892 914
893 spin_unlock_irqrestore(&host->lock, flags); 915 tmp &= ~PDC_RESET;
894 ata_eh_qc_complete(qc); 916 writel(tmp, mmio);
895 DPRINTK("EXIT\n"); 917 readl(mmio); /* flush */
918}
919
920static int pdc_softreset(struct ata_link *link, unsigned int *class,
921 unsigned long deadline)
922{
923 pdc_reset_port(link->ap);
924 return ata_sff_softreset(link, class, deadline);
925}
926
927static void pdc_error_handler(struct ata_port *ap)
928{
929 if (!(ap->pflags & ATA_PFLAG_FROZEN))
930 pdc_reset_port(ap);
931
932 ata_std_error_handler(ap);
933}
934
935static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
936{
937 struct ata_port *ap = qc->ap;
938
939 /* make DMA engine forget about the failed command */
940 if (qc->flags & ATA_QCFLAG_FAILED)
941 pdc_reset_port(ap);
942}
943
944static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
945{
946 u8 *scsicmd = qc->scsicmd->cmnd;
947 int pio = 1; /* atapi dma off by default */
948
949 /* Whitelist commands that may use DMA. */
950 switch (scsicmd[0]) {
951 case WRITE_12:
952 case WRITE_10:
953 case WRITE_6:
954 case READ_12:
955 case READ_10:
956 case READ_6:
957 case 0xad: /* READ_DVD_STRUCTURE */
958 case 0xbe: /* READ_CD */
959 pio = 0;
960 }
961 /* -45150 (FFFF4FA2) to -1 (FFFFFFFF) shall use PIO mode */
962 if (scsicmd[0] == WRITE_10) {
963 unsigned int lba =
964 (scsicmd[2] << 24) |
965 (scsicmd[3] << 16) |
966 (scsicmd[4] << 8) |
967 scsicmd[5];
968 if (lba >= 0xFFFF4FA2)
969 pio = 1;
970 }
971 return pio;
896} 972}
897 973
898static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) 974static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)