diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-06-06 14:09:48 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-06-06 14:09:48 +0000 |
commit | 5327c141d1c7ccbdf07e0bb0178a617bf073478b (patch) | |
tree | 8d15ee13aba6f1b5587fe05b81e00d17f1851923 /sys/dev/ata/ata-lowlevel.c | |
parent | 1a0d1f33835b644df56baa59f295df363e168874 (diff) | |
download | FreeBSD-src-5327c141d1c7ccbdf07e0bb0178a617bf073478b.zip FreeBSD-src-5327c141d1c7ccbdf07e0bb0178a617bf073478b.tar.gz |
Some revisions of the Serverworks K2 SATA controller have a data
corruption bug where if an ATA command is issued before DMA is started,
data will become available to the controller before it knows what to do
with it. This results in either data corruption or a controller crash.
This patch remedies the problem by adopting the workaround employed
by Linux and Darwin: starting the DMA engine prior to sending the ATA
command.
Observer on: Xserve G5
Reviewed by: mav
MFC after: 1 week
Diffstat (limited to 'sys/dev/ata/ata-lowlevel.c')
-rw-r--r-- | sys/dev/ata/ata-lowlevel.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index 566b8f6..6c196d6 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -141,6 +141,14 @@ ata_begin_transaction(struct ata_request *request) goto begin_finished; } + /* start DMA engine if necessary */ + if ((ch->flags & ATA_DMA_BEFORE_CMD) && + ch->dma.start && ch->dma.start(request)) { + device_printf(request->parent, "error starting DMA\n"); + request->result = EIO; + goto begin_finished; + } + /* issue command */ if (ch->hw.command(request)) { device_printf(request->parent, "error issuing %s command\n", @@ -150,7 +158,8 @@ ata_begin_transaction(struct ata_request *request) } /* start DMA engine */ - if (ch->dma.start && ch->dma.start(request)) { + if (!(ch->flags & ATA_DMA_BEFORE_CMD) && + ch->dma.start && ch->dma.start(request)) { device_printf(request->parent, "error starting DMA\n"); request->result = EIO; goto begin_finished; |