I asked "what more can you ask for" for 2.5.22, and somebody immediately
piped up with raid5 working again.
Well, here you have a big MD merge from Neil Brown, which may or may not
get you there. Good luck.
Other stuff: s390/x86-64/network/usb updates. Nonlinear CPU's. Build
updates: module versioning should work again. Various stuff.
Linus
-----
Summary of changes from v2.5.22 to v2.5.23
============================================
<[email protected]>:
o 2.5.22 SCSI tape buffering changes
<[email protected]>:
o 2.5.22: s390 fixes
o 2.5.22: common code changes for s/390
o 2.5.22: dasd patches
o 2.5.22: elevator exports
o 2.5.22: new xpram driver
o 2.5.22: ibm partition support
<[email protected]>:
o sparc64: Use SUNW,power-off to power off some Ultra systems
<[email protected]>:
o ip_gre.c: Use named struct initializers
<[email protected]>:
o Remove SCSI_BH
o remove tqueue.h from sched.h
o Remove sync_timers
<[email protected]>:
o Make SMP/APIC config option earlier
Adrian Bunk <[email protected]>:
o drivers/char/rio/func.h needs linux/kdev_t.h
Andi Kleen <[email protected]>:
o x86-64 merge
o Move jiffies_64 down into architectures
o Fix incorrect inline assembly in RAID-5
o change_page_attr and AGP update
Andrew Morton <[email protected]>:
o writeback tunables
o ext3 corruption fix
o update_atime cleanup
o grab_cache_page_nowait deadlock fix
o mark_buffer_dirty() speedup
o go back to 256 requests per queue
o mark_buffer_dirty_inode() speedup
o leave swapcache pages unlocked during writeout
o direct-to-BIO I/O for swapcache pages
o fix loop driver for large BIOs
o kmap_atomic fix in bio_copy()
o ext3: clean up journal_try_to_free_buffers()
o clean up alloc_buffer_head()
o take bio.h out of highmem.h
o remove set_page_buffers() and clear_page_buffers()
o allow GFP_NOFS allocators to perform swapcache writeout
o rename get_hash_table() to find_get_block()
o Reduce the radix tree nodes to 64 slots
o msync(bad address) should return -ENOMEM
Andries E. Brouwer <[email protected]>:
o small makefile correction
o remove path_init
Arnaldo Carvalho de Melo <[email protected]>:
o net/core/neighbour.c
o net/llc/*.c
o # net/core/datagram.c
o net/core/skbuff.c include/linux/skbuff.h
Benjamin LaHaise <[email protected]>:
o add wait queue function callback support
o add __fput for aio
David Brownell <[email protected]>:
o ohci misc fixes
David S. Miller <[email protected]>:
o skbuff.c: Fix preempt fix lossage from acme cleanups
o tg3.c: Fix typo in GA302T board ID
o Tigon3: Make fibre PHY support work
o ip-sysctl.txt fixes
o Tigon3: More fiber PHY tweaks
o MAINTAINERS: Remove Andi from networking as per his request
o LLC: Hand merge in of toplevel Makefile bits
o Sparc64: Update for scheduler changes
o arch/sparc64/defconfig: Update
Frank Davis <[email protected]>:
o 2.5.22 : include/linux/intermezzo_psdev.h
o 2.5.22 : fs/intermezzo/vfs.c
Greg Kroah-Hartman <[email protected]>:
o USB usb-midi driver: remove check for kernel version, as it's not
needed
Ingo Molnar <[email protected]>:
o sched_yield() is misbehaving
o comment and coding style fixes
o sync wakeup affinity fix: do not fast-migrate threads without
making sure that the target CPU is allowed.
o fix preemption bug in cli()
o sti() preemption fix
Jan Kara <[email protected]>:
o Rename of xqm.h
Jens Axboe <[email protected]>:
o ide locking botch
o missing tag blkdev.h stuff
Jes Degn S?rensen <[email protected]>:
o Tigon3: Use unsigned type for dest_idx_unmasked in tg3_recycle_rx
o Tigon3: MAX_WAIT_CNT is too large
Kai Germaschewski <[email protected]>:
o kbuild: asm offset generation for x86_64
o kbuild: asm offset generation for ARM
o kbuild: Remove remaining references to mkdep
o kbuild: Add support for alpha asm offset generation
o kbuild: Remove dead "make dep" commands
o kbuild: Remove archdep
o kbuild: modversions fix
o kbuild: Handle removed headers
o kbuild: Improve error message
o kbuild: Fix "make dep clean bzImage" and the like
o kbuild: Remove all .*.cmd files on make mrproper
o kbuild: Improve output and error behavior when making modversions
Linus Torvalds <[email protected]>:
o More IDE locking fixes. Found by Nick Piggin
o Missed parts of patch from Andries
o Missing tqueue.h includes from sched.h cleanup
o Compiler warning - unused variable
o Missing include file
o Physical address 0 is normal for ACPI - don't complain
o Linux version 2.5.23
Matthew Dharm <[email protected]>:
o USB storage: cleanup storage_probe()
o USB storage: change atomic_t to bitfield, consolidate #defines
Mikael Pettersson <[email protected]>:
o fix x86 initrd breakage
Neil Brown <[email protected]>:
o plugging initialisation
o Umem 1 of 2 - Fix compile warning in umem.c
o Umem 2 of 2 - Make device plugging work for umem
o md 1 of 22 - Fix three little compile problem when md or raid5
compiled with debugging
o md 2 of 22 - Make device plugging work for md/raid5
o md 3 of 22 - Remove md_maxreadahead
o md 4 of 22 - Make raid5 work for big bios
o md 5 of 22 - Fix various list.h list related problems in md.c
o md 6 of 22 - Discard "param" from mddev structure
o md 7 of 22 - Use wait_event_interuptible in md_thread
o md 8 of 22 - Discard md_make_request in favour of per-personality
make_request functions
o md 9 of 22 - Discard functions that have been "not yet" for a long
time
o md 10 of 22 - Remove nb_dev from mddev_s
o md 11 of 22 - Get rid of "OUT" macro in md.c
o md 12 of 22 - Remove "data" from dev_mapping and tidy up
o md 13 of 22 - First step to tidying mddev recounting and locking
o md 14 of 22 - Second step to tidying mddev refcounts and locking
o md 15 of 22 - Get rid of kdev_to_mddev
o md 16 of 22 - Next small step to improved mddev management
o md 17 of 22 - Strengthen the locking of mddev
o md 18 of 22 - More mddev tidyup - remove recovery_sem and
resync_sem
o md 19 of 22 - Improve serialisation of md syncing
o md 20 of 22 - Provide SMP safe locking for all_mddevs list
o md 21 of 22 - Improve handling of MD super blocks
o md 22 of 22 - Generalise md sync threads
Oliver Neukum <[email protected]>:
o make kaweth use the sk_buff directly on tx
Paul Menage <[email protected]>:
o Push BKL into ->permission() calls
Russell King <[email protected]>:
o net/ipv6/tcp_ipv6.c: Fix new socket creation
Rusty Russell <[email protected]>:
o ipv4/route.c: Cleanup ip_rt_acct_read
o Latest nonlinear CPU patches
o Make NTFS use a single uncompression-buffer
o Net updates / CPU hotplug infrastructure missed merge
Stelian Pop <[email protected]>:
o export pci_bus_type to modules
Stephen Rothwell <[email protected]>:
o remove getname32
o 2.5.22 compile fixes
o Make copy_siginfo_to_user mode explicit
o make file leases work as they should
Hmmm...looks like ITERATE_MDDEV interaction with _raw_spin_lock is hosed....I dont' quite see the problem
Line 754 is:
ITERATE_MDDEV(mddev,tmp) {
gcc -Wp,-MD,./.md.o.d -D__KERNEL__ -I/usr/src/linux-2.5.23/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-point
er -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -nostdinc -iwithprefix include -DKBUILD_BASENA
ME=md -DEXPORT_SYMTAB -c -o md.o md.c
md.c: In function `md_print_devices':
md.c:754: parse error before `do'
md.c:748: warning: unused variable `mddev'
md.c:747: warning: unused variable `rdev'
md.c:746: warning: unused variable `tmp2'
md.c:746: warning: unused variable `tmp'
md.c: At top level:
md.c:754: parse error before `while'
md.c:754: parse error before `&'
md.c:754: warning: type defaults to `int' in declaration of `_raw_spin_lock'
md.c:754: warning: function declaration isn't a prototype
md.c:754: conflicting types for `_raw_spin_lock'
/usr/src/linux-2.5.23/include/asm/spinlock.h:117: previous declaration of `_raw_spin_lock'
md.c:754: warning: data definition has no type or storage class
md.c:754: parse error before `&'
md.c:754: warning: type defaults to `int' in declaration of `_raw_spin_lock'
md.c:754: warning: function declaration isn't a prototype
md.c:754: warning: data definition has no type or storage class
md.c:757: warning: type defaults to `int' in declaration of `rdev'
diff -urN linux-2.5.23/drivers/ide/cmd64x.c linux/drivers/ide/cmd64x.c
--- linux-2.5.23/drivers/ide/cmd64x.c 2002-06-19 04:11:52.000000000 +0200
+++ linux/drivers/ide/cmd64x.c 2002-06-20 13:27:03.000000000 +0200
@@ -597,7 +602,6 @@
struct pci_dev *dev = ch->pci_dev;
u8 jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
@@ -647,7 +651,6 @@
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
- drive->waiting_for_dma = 0;
dma_stat = inb(dma_base+2); /* get DMA status */
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
diff -urN linux-2.5.23/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c
--- linux-2.5.23/drivers/ide/hpt34x.c 2002-06-19 04:11:47.000000000 +0200
+++ linux/drivers/ide/hpt34x.c 2002-06-20 13:25:25.000000000 +0200
@@ -157,7 +158,6 @@
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
@@ -184,7 +184,6 @@
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
outb(cmd, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
- drive->waiting_for_dma = 1;
if (drive->type == ATA_DISK) {
ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
diff -urN linux-2.5.23/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c
--- linux-2.5.23/drivers/ide/hpt366.c 2002-06-19 04:11:48.000000000 +0200
+++ linux/drivers/ide/hpt366.c 2002-06-20 13:25:12.000000000 +0200
@@ -890,7 +918,6 @@
do_udma_start(drive);
}
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
@@ -913,7 +940,6 @@
if ((bwsr_stat & bwsr_mask) == bwsr_mask)
pci_write_config_byte(dev, mscreg, msc_stat|0x30);
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
diff -urN linux-2.5.23/drivers/ide/icside.c linux/drivers/ide/icside.c
--- linux-2.5.23/drivers/ide/icside.c 2002-06-19 04:11:47.000000000 +0200
+++ linux/drivers/ide/icside.c 2002-06-20 13:27:16.000000000 +0200
@@ -440,7 +440,6 @@
{
struct ata_channel *ch = drive->channel;
- drive->waiting_for_dma = 0;
disable_dma(ch->hw.dma);
icside_destroy_dmatable(drive);
@@ -508,8 +507,6 @@
set_dma_sg(ch->hw.dma, ch->sg_table, count);
set_dma_mode(ch->hw.dma, dma_mode);
- drive->waiting_for_dma = 1;
-
return 0;
}
diff -urN linux-2.5.23/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.23/drivers/ide/ide.c 2002-06-19 04:11:59.000000000 +0200
+++ linux/drivers/ide/ide.c 2002-06-20 13:28:43.000000000 +0200
@@ -262,14 +262,14 @@
* Poll the interface for completion every 50ms during an ATAPI drive reset
* operation. If the drive has not yet responded, and we have not yet hit our
* maximum waiting time, then the timer is restarted for another 50ms.
+ *
+ * Channel lock should be held.
*/
static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
{
- unsigned long flags;
struct ata_channel *ch = drive->channel;
int ret = ide_stopped;
- spin_lock_irqsave(ch->lock, flags);
ata_select(drive, 10);
if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) {
@@ -287,7 +287,6 @@
ret = ide_stopped;
}
- spin_unlock_irqrestore(ch->lock, flags);
return ret;
}
@@ -296,14 +295,14 @@
* Poll the interface for completion every 50ms during an ata reset operation.
* If the drives have not yet responded, and we have not yet hit our maximum
* waiting time, then the timer is restarted for another 50ms.
+ *
+ * Channel lock should be held.
*/
static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
{
- unsigned long flags;
struct ata_channel *ch = drive->channel;
int ret;
- spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) {
ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
@@ -347,7 +346,6 @@
ret = ide_stopped;
}
ch->poll_timeout = 0; /* done polling */
- spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped;
}
@@ -443,12 +441,17 @@
static void dump_bits(struct ata_bit_messages *msgs, int nr, byte bits)
{
int i;
+ int first = 1;
printk(" [ ");
for (i = 0; i < nr; i++, msgs++)
- if ((bits & msgs->mask) == msgs->match)
- printk("%s ", msgs->msg);
+ if ((bits & msgs->mask) == msgs->match) {
+ if (!first)
+ printk(",");
+ printk("%s", msgs->msg);
+ first = 0;
+ }
printk("] ");
}
@@ -560,7 +563,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->sect;
args.cmd = WIN_RESTORE;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
printk(KERN_INFO "%s: done!\n", drive->name);
}
@@ -1030,12 +1033,12 @@
if (ch->poll_timeout) {
ret = handler(drive, drive->rq);
} else if (drive_is_ready(drive)) {
- if (drive->waiting_for_dma)
+ if (test_bit(IDE_DMA, ch->active))
udma_irq_lost(drive);
(void) ide_ack_intr(ch);
printk("%s: lost interrupt\n", drive->name);
ret = handler(drive, drive->rq);
- } else if (drive->waiting_for_dma) {
+ } else if (test_bit(IDE_DMA, ch->active)) {
struct request *rq = drive->rq;
/*
diff -urN linux-2.5.23/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.5.23/drivers/ide/ide-disk.c 2002-06-19 04:11:45.000000000 +0200
+++ linux/drivers/ide/ide-disk.c 2002-06-20 12:49:05.000000000 +0200
@@ -93,74 +93,61 @@
/*
* Handler for command with PIO data-in phase.
*/
-static ide_startstop_t pio_in_intr(struct ata_device *drive, struct request *rq)
+static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq)
{
unsigned long flags;
struct ata_channel *ch = drive->channel;
- unsigned int msect;
+ int ret;
spin_lock_irqsave(ch->lock, flags);
+
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
- if (drive->status & (ERR_STAT|DRQ_STAT)) {
+ if (drive->status & (ERR_STAT | DRQ_STAT)) {
spin_unlock_irqrestore(ch->lock, flags);
return ata_error(drive, rq, __FUNCTION__);
}
- if (!(drive->status & BUSY_STAT))
- goto cont;
- }
-
- msect = drive->mult_count;
- do {
- unsigned int nsect;
+ /* no data yet, so wait for another interrupt */
+ ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
- if (drive->mult_count) {
- nsect = rq->current_nr_sectors;
- /* Don't try to transfer more sectors at once then one
- * multi sector command can swallow.
- */
- if (nsect > msect)
- nsect = msect;
- } else {
- nsect = rq->current_nr_sectors;
- nsect = 1;
- }
+ ret = ide_started;
+ } else {
-// printk("Read: rq->current_nr_sectors: %d %d %d\n", msect, nsect, (int) rq->current_nr_sectors);
+ // printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
{
unsigned long flags;
char *buf;
buf = ide_map_rq(rq, &flags);
- ata_read(drive, buf, nsect * SECTOR_WORDS);
+ ata_read(drive, buf, SECTOR_WORDS);
ide_unmap_rq(rq, buf, &flags);
}
- /* Segment of the request is complete. note that this does not
- * necessarily mean that the entire request is done!! this is
- * only true if ata_end_request() returns 0.
+ /* First segment of the request is complete. note that this does not
+ * necessarily mean that the entire request is done!! this is only true
+ * if ata_end_request() returns 0.
*/
-
rq->errors = 0;
- rq->current_nr_sectors -= nsect;
+ --rq->current_nr_sectors;
if (rq->current_nr_sectors <= 0) {
if (!__ata_end_request(drive, rq, 1, 0)) {
+ // printk("Request Ended stat: %02x\n", drive->status);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped;
}
}
- msect -= nsect;
- } while (msect > 0);
-cont:
- /* still data left to transfer */
- ata_set_handler(drive, pio_in_intr, WAIT_CMD, NULL);
+ /* still data left to transfer */
+ ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
+
+ ret = ide_started;
+ }
spin_unlock_irqrestore(ch->lock, flags);
- return ide_started;
+ return ret;
}
/*
@@ -203,6 +190,77 @@
return ret;
}
+/*
+ * Handler for command with Read Multiple
+ */
+static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq)
+{
+ unsigned long flags;
+ struct ata_channel *ch = drive->channel;
+ int ret;
+
+ spin_lock_irqsave(ch->lock, flags);
+ if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
+ if (drive->status & (ERR_STAT | DRQ_STAT)) {
+ spin_unlock_irqrestore(ch->lock, flags);
+
+ return ata_error(drive, rq, __FUNCTION__);
+ }
+
+ /* no data yet, so wait for another interrupt */
+ ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
+
+ ret = ide_started;
+ } else {
+ unsigned int msect;
+
+ /* (ks/hs): Fixed Multi-Sector transfer */
+ msect = drive->mult_count;
+
+ do {
+ unsigned int nsect;
+
+ nsect = rq->current_nr_sectors;
+ if (nsect > msect)
+ nsect = msect;
+
+#if 0
+ printk("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n",
+ buf, nsect, rq->current_nr_sectors);
+#endif
+ {
+ unsigned long flags;
+ char *buf;
+
+ buf = ide_map_rq(rq, &flags);
+ ata_read(drive, buf, nsect * SECTOR_WORDS);
+ ide_unmap_rq(rq, buf, &flags);
+ }
+
+ rq->errors = 0;
+ rq->current_nr_sectors -= nsect;
+
+ /* FIXME: this seems buggy */
+ if (rq->current_nr_sectors <= 0) {
+ if (!__ata_end_request(drive, rq, 1, 0)) {
+ spin_unlock_irqrestore(ch->lock, flags);
+
+ return ide_stopped;
+ }
+ }
+ msect -= nsect;
+ } while (msect);
+
+ /* more data left */
+ ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
+
+ ret = ide_started;
+ }
+ spin_unlock_irqrestore(ch->lock, flags);
+
+ return ret;
+}
+
static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq)
{
unsigned long flags;
@@ -552,10 +610,10 @@
} else if (drive->using_dma) {
args.cmd = WIN_READDMA_EXT;
} else if (drive->mult_count) {
- args.XXX_handler = pio_in_intr;
+ args.XXX_handler = task_mulin_intr;
args.cmd = WIN_MULTREAD_EXT;
} else {
- args.XXX_handler = pio_in_intr;
+ args.XXX_handler = task_in_intr;
args.cmd = WIN_READ_EXT;
}
} else {
@@ -564,10 +622,11 @@
} else if (drive->using_dma) {
args.cmd = WIN_READDMA;
} else if (drive->mult_count) {
- args.XXX_handler = pio_in_intr;
+ /* FIXME : Shouldn't this be task_mulin_intr?! */
+ args.XXX_handler = task_in_intr;
args.cmd = WIN_MULTREAD;
} else {
- args.XXX_handler = pio_in_intr;
+ args.XXX_handler = task_in_intr;
args.cmd = WIN_READ;
}
}
@@ -614,19 +673,6 @@
return __do_request(drive, &args, rq);
}
-/*
- * Small helper function used to execute simple commands.
- */
-static int simple_taskfile(struct ata_device *drive, u8 cmd)
-{
- struct ata_taskfile args;
-
- memset(&args, 0, sizeof(args));
- args.cmd = cmd;
-
- return ide_raw_taskfile(drive, &args, NULL);
-}
-
static int idedisk_open(struct inode *inode, struct file *__fp, struct ata_device *drive)
{
MOD_INC_USE_COUNT;
@@ -635,11 +681,15 @@
/*
* Ignore the return code from door_lock, since the open() has
- * already succeeded once, and the door_lock is irrelevant at
- * this time.
+ * already succeeded once, and the door_lock is irrelevant at this
+ * time.
*/
if (drive->doorlocking) {
- if (simple_taskfile(drive, WIN_DOORLOCK))
+ struct ata_taskfile args;
+
+ memset(&args, 0, sizeof(args));
+ args.cmd = WIN_DOORLOCK;
+ if (ide_raw_taskfile(drive, &args))
drive->doorlocking = 0;
}
}
@@ -649,21 +699,30 @@
static int flush_cache(struct ata_device *drive)
{
- u8 cmd;
+ struct ata_taskfile args;
+
+ memset(&args, 0, sizeof(args));
if (drive->id->cfs_enable_2 & 0x2400)
- cmd = WIN_FLUSH_CACHE_EXT;
+ args.cmd = WIN_FLUSH_CACHE_EXT;
else
- cmd = WIN_FLUSH_CACHE;
+ args.cmd = WIN_FLUSH_CACHE;
- return simple_taskfile(drive, cmd);
+ return ide_raw_taskfile(drive, &args);
}
static void idedisk_release(struct inode *inode, struct file *filp, struct ata_device *drive)
{
if (drive->removable && !drive->usage) {
+ /* XXX I don't think this is up to the lowlevel drivers.. --hch */
+ invalidate_bdev(inode->i_bdev, 0);
+
if (drive->doorlocking) {
- if (simple_taskfile(drive, WIN_DOORUNLOCK))
+ struct ata_taskfile args;
+
+ memset(&args, 0, sizeof(args));
+ args.cmd = WIN_DOORUNLOCK;
+ if (ide_raw_taskfile(drive, &args))
drive->doorlocking = 0;
}
}
@@ -710,7 +769,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = arg;
args.cmd = WIN_SETMULT;
- if (!ide_raw_taskfile(drive, &args, NULL)) {
+ if (!ide_raw_taskfile(drive, &args)) {
/* all went well track this setting as valid */
drive->mult_count = arg;
@@ -739,7 +798,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
args.cmd = WIN_SETFEATURES;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
drive->wcache = arg;
@@ -748,7 +807,11 @@
static int idedisk_standby(struct ata_device *drive)
{
- return simple_taskfile(drive, WIN_STANDBYNOW1);
+ struct ata_taskfile args;
+
+ memset(&args, 0, sizeof(args));
+ args.cmd = WIN_STANDBYNOW1;
+ return ide_raw_taskfile(drive, &args);
}
static int set_acoustic(struct ata_device *drive, int arg)
@@ -759,7 +822,7 @@
args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
args.taskfile.sector_count = arg;
args.cmd = WIN_SETFEATURES;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
drive->acoustic = arg;
@@ -879,7 +942,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.device_head = 0x40;
args.cmd = WIN_READ_NATIVE_MAX;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if (!(drive->status & ERR_STAT)) {
@@ -901,9 +964,10 @@
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(args));
+
args.taskfile.device_head = 0x40;
args.cmd = WIN_READ_NATIVE_MAX_EXT;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if (!(drive->status & ERR_STAT)) {
@@ -941,7 +1005,7 @@
args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40;
args.cmd = WIN_SET_MAX;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
/* if OK, read new maximum address value */
if (!(drive->status & ERR_STAT)) {
@@ -974,7 +1038,7 @@
args.hobfile.high_cylinder = (addr_req >>= 8);
args.hobfile.device_head = 0x40;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if (!(drive->status & ERR_STAT)) {
@@ -1292,11 +1356,7 @@
if (arg < 0 || arg > (id ? id->max_multsect : 0))
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
val = set_multcount(drive, arg);
- spin_unlock_irq(drive->channel->lock);
return val;
}
@@ -1316,11 +1376,7 @@
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
val = set_nowerr(drive, arg);
- spin_unlock_irq(drive->channel->lock);
return val;
}
@@ -1340,11 +1396,7 @@
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
val = write_cache(drive, arg);
- spin_unlock_irq(drive->channel->lock);
return val;
}
@@ -1363,11 +1415,7 @@
if (arg < 0 || arg > 254)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
-
val = set_acoustic(drive, arg);
- spin_unlock_irq(drive->channel->lock);
return val;
}
diff -urN linux-2.5.23/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c
--- linux-2.5.23/drivers/ide/ide-pmac.c 2002-06-19 04:11:57.000000000 +0200
+++ linux/drivers/ide/ide-pmac.c 2002-06-20 13:31:16.000000000 +0200
@@ -1378,7 +1393,6 @@
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
- drive->waiting_for_dma = 0;
dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
pmac_ide_destroy_dmatable(drive->channel, ix);
@@ -1418,7 +1432,7 @@
((reading) ? 0x00800000UL : 0));
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
}
- drive->waiting_for_dma = 1;
+
if (drive->type != ATA_DISK)
return ide_started;
@@ -1466,6 +1480,8 @@
* - The dbdma fifo hasn't yet finished flushing to to system memory
* when the disk interrupt occurs.
*
+ * FIXME: The following *trick* is broken:
+ *
* The trick here is to increment drive->waiting_for_dma, and return as
* if no interrupt occured. If the counter reach a certain timeout
* value, we then return 1. If we really got the interrupt, it will
@@ -1480,15 +1496,16 @@
*/
if (!(in_le32(&dma->status) & ACTIVE))
return 1;
- if (!drive->waiting_for_dma)
+
+ if (!test_bit(IDE_DMA, drive->channel->active))
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
called while not waiting\n", ix);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set */
- drive->waiting_for_dma++;
- if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
- printk(KERN_WARNING "ide%d, timeout waiting \
+ set_bit(IDE_DMA, drive->channel->active);
+// if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
+// printk(KERN_WARNING "ide%d, timeout waiting \
for dbdma command stop\n", ix);
return 1;
}
diff -urN linux-2.5.23/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.23/drivers/ide/ide-taskfile.c 2002-06-19 04:11:55.000000000 +0200
+++ linux/drivers/ide/ide-taskfile.c 2002-06-20 13:32:55.000000000 +0200
@@ -148,7 +148,7 @@
*/
int drive_is_ready(struct ata_device *drive)
{
- if (drive->waiting_for_dma)
+ if (test_bit(IDE_DMA, drive->channel->active))
return udma_irq_status(drive);
/*
@@ -242,9 +242,8 @@
/*
* Invoked on completion of a special REQ_SPECIAL command.
*/
-static ide_startstop_t special_intr(struct ata_device *drive,
- struct request *rq)
-{
+ide_startstop_t ata_special_intr(struct ata_device *drive, struct
+ request *rq) {
struct ata_taskfile *ar = rq->special;
ide_startstop_t ret = ide_stopped;
@@ -293,18 +292,16 @@
return ret;
}
-int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar,
- char *buffer)
+int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar)
{
struct request req;
ar->command_type = IDE_DRIVE_TASK_NO_DATA;
- ar->XXX_handler = special_intr;
+ ar->XXX_handler = ata_special_intr;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
req.special = ar;
- req.buffer = buffer;
return ide_do_drive_cmd(drive, &req, ide_wait);
}
@@ -313,4 +310,5 @@
EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(ata_read);
EXPORT_SYMBOL(ata_write);
+EXPORT_SYMBOL(ata_special_intr);
EXPORT_SYMBOL(ide_raw_taskfile);
diff -urN linux-2.5.23/drivers/ide/ioctl.c linux/drivers/ide/ioctl.c
--- linux-2.5.23/drivers/ide/ioctl.c 2002-06-19 04:11:50.000000000 +0200
+++ linux/drivers/ide/ioctl.c 2002-06-20 11:45:13.000000000 +0200
@@ -47,6 +47,7 @@
u8 *argbuf = vals;
int argsize = 4;
struct ata_taskfile args;
+ struct request req;
/* Second phase.
*/
@@ -77,7 +78,17 @@
memset(argbuf + 4, 0, argsize - 4);
}
- err = ide_raw_taskfile(drive, &args, argbuf + 4);
+ /* Issue ATA command and wait for completion.
+ */
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.XXX_handler = ata_special_intr;
+
+ memset(&req, 0, sizeof(req));
+ req.flags = REQ_SPECIAL;
+ req.special = &args;
+
+ req.buffer = argbuf + 4;
+ err = ide_do_drive_cmd(drive, &req, ide_wait);
argbuf[0] = drive->status;
argbuf[1] = args.taskfile.feature;
diff -urN linux-2.5.23/drivers/ide/ns87415.c linux/drivers/ide/ns87415.c
--- linux-2.5.23/drivers/ide/ns87415.c 2002-06-19 04:11:52.000000000 +0200
+++ linux/drivers/ide/ns87415.c 2002-06-20 13:26:50.000000000 +0200
@@ -91,7 +91,6 @@
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
- drive->waiting_for_dma = 0;
dma_stat = inb(ch->dma_base+2);
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(inb(dma_base)|6, dma_base); /* from ERRATA: clear the INTR & ERROR bits */
diff -urN linux-2.5.23/drivers/ide/pcidma.c linux/drivers/ide/pcidma.c
--- linux-2.5.23/drivers/ide/pcidma.c 2002-06-19 04:11:49.000000000 +0200
+++ linux/drivers/ide/pcidma.c 2002-06-20 13:34:48.000000000 +0200
@@ -167,7 +167,6 @@
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
outb(reading, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
- drive->waiting_for_dma = 1;
return 0;
}
@@ -436,7 +435,6 @@
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
diff -urN linux-2.5.23/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- linux-2.5.23/drivers/ide/pdc202xx.c 2002-06-19 04:11:58.000000000 +0200
+++ linux/drivers/ide/pdc202xx.c 2002-06-20 13:38:06.000000000 +0200
@@ -571,7 +575,7 @@
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
}
-int pdc202xx_udma_stop(struct ata_device *drive)
+static int pdc202xx_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4);
@@ -585,7 +589,6 @@
OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + PDC_CLK);
}
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
@@ -604,7 +607,7 @@
#endif
-void pdc202xx_new_reset(struct ata_device *drive)
+static void pdc202xx_new_reset(struct ata_device *drive)
{
ata_reset(drive->channel);
mdelay(1000);
diff -urN linux-2.5.23/drivers/ide/serverworks.c linux/drivers/ide/serverworks.c
--- linux-2.5.23/drivers/ide/serverworks.c 2002-06-19 04:11:55.000000000 +0200
+++ linux/drivers/ide/serverworks.c 2002-06-20 13:26:38.000000000 +0200
@@ -331,7 +341,6 @@
#endif
}
- drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
diff -urN linux-2.5.23/drivers/ide/tcq.c linux/drivers/ide/tcq.c
--- linux-2.5.23/drivers/ide/tcq.c 2002-06-19 04:11:57.000000000 +0200
+++ linux/drivers/ide/tcq.c 2002-06-20 11:45:13.000000000 +0200
@@ -441,7 +441,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.feature = 0x01;
args.cmd = WIN_NOP;
- ide_raw_taskfile(drive, &args, NULL);
+ ide_raw_taskfile(drive, &args);
if (args.taskfile.feature & ABRT_ERR)
return 1;
@@ -469,7 +469,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_WCACHE;
args.cmd = WIN_SETFEATURES;
- if (ide_raw_taskfile(drive, &args, NULL)) {
+ if (ide_raw_taskfile(drive, &args)) {
printk("%s: failed to enable write cache\n", drive->name);
return 1;
}
@@ -481,7 +481,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_DIS_RI;
args.cmd = WIN_SETFEATURES;
- if (ide_raw_taskfile(drive, &args, NULL)) {
+ if (ide_raw_taskfile(drive, &args)) {
printk("%s: disabling release interrupt fail\n", drive->name);
return 1;
}
@@ -493,7 +493,7 @@
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_SI;
args.cmd = WIN_SETFEATURES;
- if (ide_raw_taskfile(drive, &args, NULL)) {
+ if (ide_raw_taskfile(drive, &args)) {
printk("%s: enabling service interrupt fail\n", drive->name);
return 1;
}
diff -urN linux-2.5.23/drivers/ide/trm290.c linux/drivers/ide/trm290.c
--- linux-2.5.23/drivers/ide/trm290.c 2002-06-19 04:11:49.000000000 +0200
+++ linux/drivers/ide/trm290.c 2002-06-20 13:38:52.000000000 +0200
@@ -185,8 +185,8 @@
{
struct ata_channel *ch = drive->channel;
- drive->waiting_for_dma = 0;
udma_destroy_table(ch); /* purge DMA mappings */
+
return (inw(ch->dma_base + 2) != 0x00ff);
}
@@ -224,7 +224,6 @@
trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(ch->dmatable_dma|reading|writing, ch->dma_base);
- drive->waiting_for_dma = 1;
outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type == ATA_DISK) {
diff -urN linux-2.5.23/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.5.23/include/linux/ide.h 2002-06-19 04:11:49.000000000 +0200
+++ linux/include/linux/ide.h 2002-06-20 13:35:15.000000000 +0200
@@ -298,7 +298,6 @@
unsigned using_tcq : 1; /* disk is using queueing */
unsigned dsc_overlap : 1; /* flag: DSC overlap */
- unsigned waiting_for_dma: 1; /* dma currently in progress */
unsigned busy : 1; /* currently doing revalidate_disk() */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
@@ -681,7 +680,8 @@
bio_kunmap_irq(to, flags);
}
-extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *);
+extern ide_startstop_t ata_special_intr(struct ata_device *, struct request *);
+extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *);
extern void ide_fix_driveid(struct hd_driveid *id);
extern int ide_config_drive_speed(struct ata_device *, byte);
@@ -756,6 +756,8 @@
static inline int udma_stop(struct ata_device *drive)
{
+ clear_bit(IDE_DMA, drive->channel->active);
+
return drive->channel->udma_stop(drive);
}
@@ -764,7 +766,11 @@
*/
static inline ide_startstop_t udma_init(struct ata_device *drive, struct request *rq)
{
- return drive->channel->udma_init(drive, rq);
+ int ret = drive->channel->udma_init(drive, rq);
+ if (ret == ide_started)
+ set_bit(IDE_DMA, drive->channel->active);
+
+ return ret;
}
static inline int udma_irq_status(struct ata_device *drive)