From: Jens Axboe Here is the port of the floppy smp fixes from 2.4 drivers/block/floppy.c | 32 +++++++++++++++++++++++++++----- 1 files changed, 27 insertions(+), 5 deletions(-) diff -puN drivers/block/floppy.c~floppy-smp-fixes drivers/block/floppy.c --- 25/drivers/block/floppy.c~floppy-smp-fixes 2003-07-25 23:42:33.000000000 -0700 +++ 25-akpm/drivers/block/floppy.c 2003-07-25 23:42:33.000000000 -0700 @@ -249,6 +249,7 @@ static int irqdma_allocated; static struct request *current_req; static struct request_queue floppy_queue; +static void do_fd_request(request_queue_t * q); #ifndef fd_get_dma_residue #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) @@ -631,7 +632,8 @@ static const char *timeout_message; static void is_alive(const char *message) { /* this routine checks whether the floppy driver is "alive" */ - if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){ + if (test_bit(0, &fdc_busy) && command_status < 2 + && !timer_pending(&fd_timeout)) { DPRINT("timeout handler died: %s\n",message); } } @@ -661,7 +663,7 @@ static int output_log_pos; #define current_reqD -1 #define MAXTIMEOUT -2 -static void reschedule_timeout(int drive, const char *message, int marg) +static void __reschedule_timeout(int drive, const char *message, int marg) { if (drive == current_reqD) drive = current_drive; @@ -680,6 +682,15 @@ static void reschedule_timeout(int drive timeout_message = message; } +static void reschedule_timeout(int drive, const char *message, int marg) +{ + unsigned long flags; + + spin_lock_irqsave(&floppy_lock, flags); + __reschedule_timeout(drive, message, marg); + spin_unlock_irqrestore(&floppy_lock, flags); +} + static int maximum(int a, int b) { if (a > b) @@ -908,7 +919,7 @@ static int _lock_fdc(int drive, int inte } command_status = FD_COMMAND_NONE; - reschedule_timeout(drive, "lock fdc", 0); + __reschedule_timeout(drive, "lock fdc", 0); set_fdc(drive); return 0; } @@ -922,17 +933,23 @@ if (lock_fdc(drive,interruptible)) retur /* unlocks the driver */ static inline void unlock_fdc(void) { + unsigned long flags; + raw_cmd = 0; - if (!fdc_busy) + if (!test_bit(0, &fdc_busy)) DPRINT("FDC access conflict!\n"); if (do_floppy) DPRINT("device interrupt still active at FDC release: %p!\n", do_floppy); command_status = FD_COMMAND_NONE; + spin_lock_irqsave(&floppy_lock, flags); del_timer(&fd_timeout); cont = NULL; clear_bit(0, &fdc_busy); + if (elv_next_request(&floppy_queue)) + do_fd_request(&floppy_queue); + spin_unlock_irqrestore(&floppy_lock, flags); floppy_release_irq_and_dma(); wake_up(&fdc_wait); } @@ -1010,9 +1027,13 @@ static struct timer_list fd_timer = TIME static void cancel_activity(void) { + unsigned long flags; + + spin_lock_irqsave(&floppy_lock, flags); do_floppy = NULL; PREPARE_WORK(&floppy_work, (void*)(void*)empty, NULL); del_timer(&fd_timer); + spin_unlock_irqrestore(&floppy_lock, flags); } /* this function makes sure that the disk stays in the drive during the @@ -2995,7 +3016,7 @@ static void do_fd_request(request_queue_ printk("sect=%ld flags=%lx\n", (long)current_req->sector, current_req->flags); return; } - if (fdc_busy){ + if (test_bit(0, &fdc_busy)) { /* fdc busy, this new request will be treated when the current one is done */ is_alive("do fd request, old request running"); @@ -4261,6 +4282,7 @@ int __init floppy_init(void) floppy_sizes[i] = MAX_DISK_SIZE << 1; blk_init_queue(&floppy_queue, do_fd_request, &floppy_lock); + blk_queue_max_sectors(&floppy_queue, 64); reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); config_types(); _