aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMikael Pettersson <mikpe@it.uu.se>2009-09-15 09:08:47 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-09-17 16:46:34 -0400
commitff7cddf59e3618d29e12b061651ab3f5a53f4a98 (patch)
treeb45b879b6ca820b074ea69ee218f92247932ebd4 /drivers
parent0ae6654da437db4ae6333d232e718b570c7a3eac (diff)
sata_promise: update reset code
sata_promise's reset code has deviated quite a bit from the Promise reference driver's, and it has been observed to fail to recover from errors in some cases. This patch thus updates the reset code to more closely match the reference driver: - soft reset (pdc_reset_port): * wait for ATA engine to not be in packet command mode (2nd gen only) * write reset bit in PDC_CTLSTAT before the first read in the loop * for 2nd gen SATA follow up with FPDMA reset and clearing error status registers - hard reset (pdc_sata_hardreset): * wait for ATA engine to not be in packet command mode (2nd gen only) * reset ATA engine via the PCI control register * Tejun's change to use non-waiting hardreset + follow-up SRST I'm not changing the hotplug mask bits since they are taken care of by sata_promise's ->freeze() and ->thaw() operations. And I'm not writing the PMP port # because that's always zero (for now). Tested here on various controllers. In particular, one disk which used to timeout and fail to recover from certain hdparm and smartmonctl commands now works nicely. Signed-off-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/sata_promise.c121
1 files changed, 120 insertions, 1 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 4d18d5a59afe..07d8d00b4d34 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -56,6 +56,7 @@ enum {
56 /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */ 56 /* host register offsets (from host->iomap[PDC_MMIO_BAR]) */
57 PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ 57 PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
58 PDC_FLASH_CTL = 0x44, /* Flash control register */ 58 PDC_FLASH_CTL = 0x44, /* Flash control register */
59 PDC_PCI_CTL = 0x48, /* PCI control/status reg */
59 PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ 60 PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
60 PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */ 61 PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
61 PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ 62 PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */
@@ -75,7 +76,17 @@ enum {
75 PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */ 76 PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
76 77
77 /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */ 78 /* per-port SATA register offsets (from ap->ioaddr.scr_addr) */
79 PDC_SATA_ERROR = 0x04,
78 PDC_PHYMODE4 = 0x14, 80 PDC_PHYMODE4 = 0x14,
81 PDC_LINK_LAYER_ERRORS = 0x6C,
82 PDC_FPDMA_CTLSTAT = 0xD8,
83 PDC_INTERNAL_DEBUG_1 = 0xF8, /* also used for PATA */
84 PDC_INTERNAL_DEBUG_2 = 0xFC, /* also used for PATA */
85
86 /* PDC_FPDMA_CTLSTAT bit definitions */
87 PDC_FPDMA_CTLSTAT_RESET = 1 << 3,
88 PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG = 1 << 10,
89 PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG = 1 << 11,
79 90
80 /* PDC_GLOBAL_CTL bit definitions */ 91 /* PDC_GLOBAL_CTL bit definitions */
81 PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ 92 PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */
@@ -359,12 +370,76 @@ static int pdc_sata_port_start(struct ata_port *ap)
359 return 0; 370 return 0;
360} 371}
361 372
373static void pdc_fpdma_clear_interrupt_flag(struct ata_port *ap)
374{
375 void __iomem *sata_mmio = ap->ioaddr.scr_addr;
376 u32 tmp;
377
378 tmp = readl(sata_mmio + PDC_FPDMA_CTLSTAT);
379 tmp |= PDC_FPDMA_CTLSTAT_DMASETUP_INT_FLAG;
380 tmp |= PDC_FPDMA_CTLSTAT_SETDB_INT_FLAG;
381
382 /* It's not allowed to write to the entire FPDMA_CTLSTAT register
383 when NCQ is running. So do a byte-sized write to bits 10 and 11. */
384 writeb(tmp >> 8, sata_mmio + PDC_FPDMA_CTLSTAT + 1);
385 readb(sata_mmio + PDC_FPDMA_CTLSTAT + 1); /* flush */
386}
387
388static void pdc_fpdma_reset(struct ata_port *ap)
389{
390 void __iomem *sata_mmio = ap->ioaddr.scr_addr;
391 u8 tmp;
392
393 tmp = (u8)readl(sata_mmio + PDC_FPDMA_CTLSTAT);
394 tmp &= 0x7F;
395 tmp |= PDC_FPDMA_CTLSTAT_RESET;
396 writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT);
397 readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */
398 udelay(100);
399 tmp &= ~PDC_FPDMA_CTLSTAT_RESET;
400 writeb(tmp, sata_mmio + PDC_FPDMA_CTLSTAT);
401 readl(sata_mmio + PDC_FPDMA_CTLSTAT); /* flush */
402
403 pdc_fpdma_clear_interrupt_flag(ap);
404}
405
406static void pdc_not_at_command_packet_phase(struct ata_port *ap)
407{
408 void __iomem *sata_mmio = ap->ioaddr.scr_addr;
409 unsigned int i;
410 u32 tmp;
411
412 /* check not at ASIC packet command phase */
413 for (i = 0; i < 100; ++i) {
414 writel(0, sata_mmio + PDC_INTERNAL_DEBUG_1);
415 tmp = readl(sata_mmio + PDC_INTERNAL_DEBUG_2);
416 if ((tmp & 0xF) != 1)
417 break;
418 udelay(100);
419 }
420}
421
422static void pdc_clear_internal_debug_record_error_register(struct ata_port *ap)
423{
424 void __iomem *sata_mmio = ap->ioaddr.scr_addr;
425
426 writel(0xffffffff, sata_mmio + PDC_SATA_ERROR);
427 writel(0xffff0000, sata_mmio + PDC_LINK_LAYER_ERRORS);
428}
429
362static void pdc_reset_port(struct ata_port *ap) 430static void pdc_reset_port(struct ata_port *ap)
363{ 431{
364 void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT; 432 void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
365 unsigned int i; 433 unsigned int i;
366 u32 tmp; 434 u32 tmp;
367 435
436 if (ap->flags & PDC_FLAG_GEN_II)
437 pdc_not_at_command_packet_phase(ap);
438
439 tmp = readl(ata_ctlstat_mmio);
440 tmp |= PDC_RESET;
441 writel(tmp, ata_ctlstat_mmio);
442
368 for (i = 11; i > 0; i--) { 443 for (i = 11; i > 0; i--) {
369 tmp = readl(ata_ctlstat_mmio); 444 tmp = readl(ata_ctlstat_mmio);
370 if (tmp & PDC_RESET) 445 if (tmp & PDC_RESET)
@@ -379,6 +454,11 @@ static void pdc_reset_port(struct ata_port *ap)
379 tmp &= ~PDC_RESET; 454 tmp &= ~PDC_RESET;
380 writel(tmp, ata_ctlstat_mmio); 455 writel(tmp, ata_ctlstat_mmio);
381 readl(ata_ctlstat_mmio); /* flush */ 456 readl(ata_ctlstat_mmio); /* flush */
457
458 if (sata_scr_valid(&ap->link) && (ap->flags & PDC_FLAG_GEN_II)) {
459 pdc_fpdma_reset(ap);
460 pdc_clear_internal_debug_record_error_register(ap);
461 }
382} 462}
383 463
384static int pdc_pata_cable_detect(struct ata_port *ap) 464static int pdc_pata_cable_detect(struct ata_port *ap)
@@ -706,11 +786,50 @@ static int pdc_pata_softreset(struct ata_link *link, unsigned int *class,
706 return ata_sff_softreset(link, class, deadline); 786 return ata_sff_softreset(link, class, deadline);
707} 787}
708 788
789static unsigned int pdc_ata_port_to_ata_no(const struct ata_port *ap)
790{
791 void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
792 void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
793
794 /* ata_mmio == host_mmio + 0x200 + ata_no * 0x80 */
795 return (ata_mmio - host_mmio - 0x200) / 0x80;
796}
797
798static void pdc_hard_reset_port(struct ata_port *ap)
799{
800 void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
801 void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1;
802 unsigned int ata_no = pdc_ata_port_to_ata_no(ap);
803 u8 tmp;
804
805 spin_lock(&ap->host->lock);
806
807 tmp = readb(pcictl_b1_mmio);
808 tmp &= ~(0x10 << ata_no);
809 writeb(tmp, pcictl_b1_mmio);
810 readb(pcictl_b1_mmio); /* flush */
811 udelay(100);
812 tmp |= (0x10 << ata_no);
813 writeb(tmp, pcictl_b1_mmio);
814 readb(pcictl_b1_mmio); /* flush */
815
816 spin_unlock(&ap->host->lock);
817}
818
709static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, 819static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
710 unsigned long deadline) 820 unsigned long deadline)
711{ 821{
822 if (link->ap->flags & PDC_FLAG_GEN_II)
823 pdc_not_at_command_packet_phase(link->ap);
824 /* hotplug IRQs should have been masked by pdc_sata_freeze() */
825 pdc_hard_reset_port(link->ap);
712 pdc_reset_port(link->ap); 826 pdc_reset_port(link->ap);
713 return sata_sff_hardreset(link, class, deadline); 827
828 /* sata_promise can't reliably acquire the first D2H Reg FIS
829 * after hardreset. Do non-waiting hardreset and request
830 * follow-up SRST.
831 */
832 return sata_std_hardreset(link, class, deadline);
714} 833}
715 834
716static void pdc_error_handler(struct ata_port *ap) 835static void pdc_error_handler(struct ata_port *ap)