diff options
author | Andrew Morton <akpm@osdl.org> | 2005-10-31 14:08:53 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-31 14:22:04 -0800 |
commit | a717f77362d4fe044721c126c89e2a38e731a576 (patch) | |
tree | b899e97f5c73a1679613903a1c378352a0997749 | |
parent | f2c84c0e84bfa637a7161eac10157cf3b05b4a73 (diff) | |
download | op-kernel-dev-a717f77362d4fe044721c126c89e2a38e731a576.zip op-kernel-dev-a717f77362d4fe044721c126c89e2a38e731a576.tar.gz |
[PATCH] revert ide-scsi highmem cleanup
Jeff Garzik <jgarzik@pobox.com> points out that this was wrong: we need to
disable local interrupts while holding KM_IRQ0 due to IRQ sharing.
And holding interrupts off during a big PIO opration is expensive, so we only
want to do that if we know the page was highmem.
So revert commit 17fd47ab4d33e764216b87006d8118fa050b4c92
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/scsi/ide-scsi.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 00d6a66..a440ea3 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -180,12 +180,22 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne return; } count = min(pc->sg->length - pc->b_count, bcount); - buf = kmap_atomic(pc->sg->page, KM_IRQ0); - drive->hwif->atapi_input_bytes(drive, - buf + pc->b_count + pc->sg->offset, count); - kunmap_atomic(buf, KM_IRQ0); - bcount -= count; - pc->b_count += count; + if (PageHighMem(pc->sg->page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(pc->sg->page, KM_IRQ0) + + pc->sg->offset; + drive->hwif->atapi_input_bytes(drive, + buf + pc->b_count, count); + kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(pc->sg->page) + pc->sg->offset; + drive->hwif->atapi_input_bytes(drive, + buf + pc->b_count, count); + } + bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; @@ -205,12 +215,22 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign return; } count = min(pc->sg->length - pc->b_count, bcount); - buf = kmap_atomic(pc->sg->page, KM_IRQ0); - drive->hwif->atapi_output_bytes(drive, - buf + pc->b_count + pc->sg->offset, count); - kunmap_atomic(buf, KM_IRQ0); - bcount -= count; - pc->b_count += count; + if (PageHighMem(pc->sg->page)) { + unsigned long flags; + + local_irq_save(flags); + buf = kmap_atomic(pc->sg->page, KM_IRQ0) + + pc->sg->offset; + drive->hwif->atapi_output_bytes(drive, + buf + pc->b_count, count); + kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); + local_irq_restore(flags); + } else { + buf = page_address(pc->sg->page) + pc->sg->offset; + drive->hwif->atapi_output_bytes(drive, + buf + pc->b_count, count); + } + bcount -= count; pc->b_count += count; if (pc->b_count == pc->sg->length) { pc->sg++; pc->b_count = 0; |