ATA Patch #7 (Re: ATA Patch #6)
YONETANI Tomokazu
qhwt+dfly at les.ath.cx
Mon Nov 29 09:05:47 PST 2004
On Mon, Nov 29, 2004 at 09:32:21PM +0900, YONETANI Tomokazu wrote:
> On Mon, Nov 29, 2004 at 07:42:58AM +0100, Jeroen Ruigrok/asmodai wrote:
> > -On [20041128 14:32], YONETANI Tomokazu (qhwt+dfly at xxxxxxxxxx) wrote:
> > >I hope so(I'm talking without knowing the ATA spec, do you have a reference
> > >to a documentation I can read?)
> >
> > http://www.t13.org/
>
> Thanks! I'll be silent(at least for this issue) for a while in order to
> read them through.
Ok, it may be too early to speak, but if I understand the documents
correctly, the device control register should not be accessed when
DMACK is assert -- that is, you can't disable device interrupt after
ata_dmastart(), right? Here's a small modification to ATA Patch #7
that just worked(but slightly worse numbers from dd command compared
to unpatched kernel) on Dynabook SS3500.
- reduced DELAY()'s you added down to 1
- move up ata_clear_interlock() before ata_dmastart()
- add missing ata_clear_interlock() after calls to ata_command()
with ATA_WAIT_READY flag.
diff -u ata-7/ata-all.c ata/ata-all.c
--- ata-7/ata-all.c 2004-11-28 21:59:02.000000000 +0900
+++ ata/ata-all.c 2004-11-30 01:51:32.000000000 +0900
@@ -1189,7 +1189,7 @@
crit_enter();
atadev->channel->flags |= ATA_INTERRUPT_INTERLOCK;
ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit);
- DELAY(10);
+ DELAY(1);
ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT);
crit_exit();
@@ -1269,7 +1269,7 @@
*/
atadev->channel->active |= flags & (ATA_WAIT_INTR | ATA_WAIT_READY);
ATA_OUTB(atadev->channel->r_io, ATA_CMD, command);
- DELAY(10);
+ DELAY(1);
/*
* ATA_IMMEDIATE means that the caller is going to do more setup, do
diff -u ata-7/ata-disk.c ata/ata-disk.c
--- ata-7/ata-disk.c 2004-11-28 21:59:02.000000000 +0900
+++ ata/ata-disk.c 2004-11-30 01:52:21.000000000 +0900
@@ -265,6 +265,7 @@
if (flush) {
if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
ata_prtdev(atadev, "flushing cache on detach failed\n");
+ ata_clear_interlock(atadev);
}
if (adp->flags & AD_F_RAID_SUBDISK)
ata_raiddisk_detach(adp);
@@ -295,6 +296,7 @@
ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL);
if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
ata_prtdev(adp->device, "flushing cache on close failed\n");
+ ata_clear_interlock(adp->device);
ATA_UNLOCK_CH(adp->device->channel);
splx(s);
return 0;
@@ -571,10 +573,10 @@
* clear the interrupt interlock and reenable interrupts. It
* is possible that this will generate an immediate interrupt.
*/
+ ata_clear_interlock(adp->device);
ata_dmastart(adp->device, request->data, request->bytecount,
request->flags & ADR_F_READ);
ad_start_timeout(request);
- ata_clear_interlock(adp->device);
return ATA_OP_CONTINUES;
}
@@ -843,9 +845,9 @@
ad_invalidatequeue(adp, NULL);
return ATA_OP_FINISHED;
}
+ ata_clear_interlock(adp->device);
ata_dmastart(adp->device, request->data, request->bytecount,
request->flags & ADR_F_READ);
- ata_clear_interlock(adp->device);
return ATA_OP_CONTINUES;
}
return ATA_OP_FINISHED;
@@ -881,6 +883,7 @@
if (ata_command(adp->device, ATA_C_NOP,
0, 0, ATA_C_F_FLUSHQUEUE, ATA_WAIT_READY))
ata_prtdev(adp->device, "flush queue failed\n");
+ ata_clear_interlock(adp->device);
adp->outstanding = 0;
}
}
@@ -993,6 +996,7 @@
ata_umode(adp->device->param));
else
ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1);
+ ata_clear_interlock(atadev);
}
void
More information about the Kernel
mailing list