Skip to content

Commit ff7cddf

Browse files
Mikael PetterssonJeff Garzik
authored andcommitted
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>
1 parent 0ae6654 commit ff7cddf

File tree

1 file changed

+120
-1
lines changed

1 file changed

+120
-1
lines changed

drivers/ata/sata_promise.c

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum {
5656
/* host register offsets (from host->iomap[PDC_MMIO_BAR]) */
5757
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
5858
PDC_FLASH_CTL = 0x44, /* Flash control register */
59+
PDC_PCI_CTL = 0x48, /* PCI control/status reg */
5960
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
6061
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
6162
PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */
@@ -75,7 +76,17 @@ enum {
7576
PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
7677

7778
/* per-port SATA register offsets (from ap->ioaddr.scr_addr) */
79+
PDC_SATA_ERROR = 0x04,
7880
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,
7990

8091
/* PDC_GLOBAL_CTL bit definitions */
8192
PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */
@@ -359,12 +370,76 @@ static int pdc_sata_port_start(struct ata_port *ap)
359370
return 0;
360371
}
361372

373+
static 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+
388+
static 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+
406+
static 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+
422+
static 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+
362430
static void pdc_reset_port(struct ata_port *ap)
363431
{
364432
void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
365433
unsigned int i;
366434
u32 tmp;
367435

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+
368443
for (i = 11; i > 0; i--) {
369444
tmp = readl(ata_ctlstat_mmio);
370445
if (tmp & PDC_RESET)
@@ -379,6 +454,11 @@ static void pdc_reset_port(struct ata_port *ap)
379454
tmp &= ~PDC_RESET;
380455
writel(tmp, ata_ctlstat_mmio);
381456
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+
}
382462
}
383463

384464
static 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,
706786
return ata_sff_softreset(link, class, deadline);
707787
}
708788

789+
static 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+
798+
static 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+
709819
static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
710820
unsigned long deadline)
711821
{
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);
712826
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);
714833
}
715834

716835
static void pdc_error_handler(struct ata_port *ap)

0 commit comments

Comments
 (0)