Skip to content

Commit a2cfe81

Browse files
Robert HancockJeff Garzik
authored andcommitted
sata_nv: wait for response on entering/leaving ADMA mode
Update sata_nv to wait for the controller to indicate via the status register that it has entered the requested state when switching between ADMA mode and register mode. This issue came up recently when debugging some problems with cache flush command timeouts and while it didn't appear to fix that problem, this is something we should likely be doing in any case. Signed-off-by: Robert Hancock <[email protected]> Cc: Tejun Heo <[email protected]> Cc: Jeff Garzik <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Jeff Garzik <[email protected]>
1 parent 382a665 commit a2cfe81

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

drivers/ata/sata_nv.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,22 +512,47 @@ static void nv_adma_register_mode(struct ata_port *ap)
512512
{
513513
struct nv_adma_port_priv *pp = ap->private_data;
514514
void __iomem *mmio = pp->ctl_block;
515-
u16 tmp;
515+
u16 tmp, status;
516+
int count = 0;
516517

517518
if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
518519
return;
519520

521+
status = readw(mmio + NV_ADMA_STAT);
522+
while(!(status & NV_ADMA_STAT_IDLE) && count < 20) {
523+
ndelay(50);
524+
status = readw(mmio + NV_ADMA_STAT);
525+
count++;
526+
}
527+
if(count == 20)
528+
ata_port_printk(ap, KERN_WARNING,
529+
"timeout waiting for ADMA IDLE, stat=0x%hx\n",
530+
status);
531+
520532
tmp = readw(mmio + NV_ADMA_CTL);
521533
writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
522534

535+
count = 0;
536+
status = readw(mmio + NV_ADMA_STAT);
537+
while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
538+
ndelay(50);
539+
status = readw(mmio + NV_ADMA_STAT);
540+
count++;
541+
}
542+
if(count == 20)
543+
ata_port_printk(ap, KERN_WARNING,
544+
"timeout waiting for ADMA LEGACY, stat=0x%hx\n",
545+
status);
546+
523547
pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
524548
}
525549

526550
static void nv_adma_mode(struct ata_port *ap)
527551
{
528552
struct nv_adma_port_priv *pp = ap->private_data;
529553
void __iomem *mmio = pp->ctl_block;
530-
u16 tmp;
554+
u16 tmp, status;
555+
int count = 0;
531556

532557
if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
533558
return;
@@ -537,6 +562,18 @@ static void nv_adma_mode(struct ata_port *ap)
537562
tmp = readw(mmio + NV_ADMA_CTL);
538563
writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
539564

565+
status = readw(mmio + NV_ADMA_STAT);
566+
while(((status & NV_ADMA_STAT_LEGACY) ||
567+
!(status & NV_ADMA_STAT_IDLE)) && count < 20) {
568+
ndelay(50);
569+
status = readw(mmio + NV_ADMA_STAT);
570+
count++;
571+
}
572+
if(count == 20)
573+
ata_port_printk(ap, KERN_WARNING,
574+
"timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
575+
status);
576+
540577
pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE;
541578
}
542579

0 commit comments

Comments
 (0)