aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-07-03 03:24:23 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-03 18:27:00 -0400
commit3e541a4ae534a7e59ad464af9abea382b3035724 (patch)
treea3f0de1022e4459d0eadb1f8583956ab7067011a
parent5863aa651bd79a6bb15972894306923db088e71c (diff)
[PATCH] lockdep: floppy.c irq release fix
The lock validator triggered a number of bugs in the floppy driver, all related to the floppy driver allocating and freeing irq and dma resources from interrupt context. The initial solution was to use schedule_work() to push this into process context, but this caused further problems: for example the current floppy driver in -mm2 is totally broken and all floppy commands time out with an error. (as reported by Barry K. Nathan) This patch tries another solution: simply get rid of all that dynamic IRQ and DMA allocation/freeing. I doubt it made much sense back in the heydays of floppies (if two devices raced for DMA or IRQ resources then we didnt handle those cases too gracefully anyway), and today it makes near zero sense. So the new code does the simplest and most straightforward thing: allocate IRQ and DMA resources at module init time, and free them at module removal time. Dont try to release while the driver is operational. This, besides making the floppy driver functional again has an added bonus, floppy IRQ stats are finally persistent and visible in /proc/interrupts: 6: 63 XT-PIC-level floppy Besides normal floppy IO i have also tested IO error handling, motor-off timeouts, etc. - and everything seems to be working fine. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/block/floppy.c42
1 files changed, 4 insertions, 38 deletions
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 0242cbb86a87..5109fa37c662 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -249,18 +249,6 @@ static int irqdma_allocated;
249#include <linux/cdrom.h> /* for the compatibility eject ioctl */ 249#include <linux/cdrom.h> /* for the compatibility eject ioctl */
250#include <linux/completion.h> 250#include <linux/completion.h>
251 251
252/*
253 * Interrupt freeing also means /proc VFS work - dont do it
254 * from interrupt context. We push this work into keventd:
255 */
256static void fd_free_irq_fn(void *data)
257{
258 fd_free_irq();
259}
260
261static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL);
262
263
264static struct request *current_req; 252static struct request *current_req;
265static struct request_queue *floppy_queue; 253static struct request_queue *floppy_queue;
266static void do_fd_request(request_queue_t * q); 254static void do_fd_request(request_queue_t * q);
@@ -826,15 +814,6 @@ static int set_dor(int fdc, char mask, char data)
826 UDRS->select_date = jiffies; 814 UDRS->select_date = jiffies;
827 } 815 }
828 } 816 }
829 /*
830 * We should propagate failures to grab the resources back
831 * nicely from here. Actually we ought to rewrite the fd
832 * driver some day too.
833 */
834 if (newdor & FLOPPY_MOTOR_MASK)
835 floppy_grab_irq_and_dma();
836 if (olddor & FLOPPY_MOTOR_MASK)
837 floppy_release_irq_and_dma();
838 return olddor; 817 return olddor;
839} 818}
840 819
@@ -892,8 +871,6 @@ static int _lock_fdc(int drive, int interruptible, int line)
892 line); 871 line);
893 return -1; 872 return -1;
894 } 873 }
895 if (floppy_grab_irq_and_dma() == -1)
896 return -EBUSY;
897 874
898 if (test_and_set_bit(0, &fdc_busy)) { 875 if (test_and_set_bit(0, &fdc_busy)) {
899 DECLARE_WAITQUEUE(wait, current); 876 DECLARE_WAITQUEUE(wait, current);
@@ -915,6 +892,8 @@ static int _lock_fdc(int drive, int interruptible, int line)
915 892
916 set_current_state(TASK_RUNNING); 893 set_current_state(TASK_RUNNING);
917 remove_wait_queue(&fdc_wait, &wait); 894 remove_wait_queue(&fdc_wait, &wait);
895
896 flush_scheduled_work();
918 } 897 }
919 command_status = FD_COMMAND_NONE; 898 command_status = FD_COMMAND_NONE;
920 899
@@ -948,7 +927,6 @@ static inline void unlock_fdc(void)
948 if (elv_next_request(floppy_queue)) 927 if (elv_next_request(floppy_queue))
949 do_fd_request(floppy_queue); 928 do_fd_request(floppy_queue);
950 spin_unlock_irqrestore(&floppy_lock, flags); 929 spin_unlock_irqrestore(&floppy_lock, flags);
951 floppy_release_irq_and_dma();
952 wake_up(&fdc_wait); 930 wake_up(&fdc_wait);
953} 931}
954 932
@@ -3694,8 +3672,8 @@ static int floppy_release(struct inode *inode, struct file *filp)
3694 } 3672 }
3695 if (!UDRS->fd_ref) 3673 if (!UDRS->fd_ref)
3696 opened_bdev[drive] = NULL; 3674 opened_bdev[drive] = NULL;
3697 floppy_release_irq_and_dma();
3698 mutex_unlock(&open_lock); 3675 mutex_unlock(&open_lock);
3676
3699 return 0; 3677 return 0;
3700} 3678}
3701 3679
@@ -3726,9 +3704,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
3726 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL))) 3704 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
3727 goto out2; 3705 goto out2;
3728 3706
3729 if (floppy_grab_irq_and_dma())
3730 goto out2;
3731
3732 if (filp->f_flags & O_EXCL) 3707 if (filp->f_flags & O_EXCL)
3733 UDRS->fd_ref = -1; 3708 UDRS->fd_ref = -1;
3734 else 3709 else
@@ -3805,7 +3780,6 @@ out:
3805 UDRS->fd_ref--; 3780 UDRS->fd_ref--;
3806 if (!UDRS->fd_ref) 3781 if (!UDRS->fd_ref)
3807 opened_bdev[drive] = NULL; 3782 opened_bdev[drive] = NULL;
3808 floppy_release_irq_and_dma();
3809out2: 3783out2:
3810 mutex_unlock(&open_lock); 3784 mutex_unlock(&open_lock);
3811 return res; 3785 return res;
@@ -3822,14 +3796,9 @@ static int check_floppy_change(struct gendisk *disk)
3822 return 1; 3796 return 1;
3823 3797
3824 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { 3798 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
3825 if (floppy_grab_irq_and_dma()) {
3826 return 1;
3827 }
3828
3829 lock_fdc(drive, 0); 3799 lock_fdc(drive, 0);
3830 poll_drive(0, 0); 3800 poll_drive(0, 0);
3831 process_fd_request(); 3801 process_fd_request();
3832 floppy_release_irq_and_dma();
3833 } 3802 }
3834 3803
3835 if (UTESTF(FD_DISK_CHANGED) || 3804 if (UTESTF(FD_DISK_CHANGED) ||
@@ -4346,7 +4315,6 @@ static int __init floppy_init(void)
4346 fdc = 0; 4315 fdc = 0;
4347 del_timer(&fd_timeout); 4316 del_timer(&fd_timeout);
4348 current_drive = 0; 4317 current_drive = 0;
4349 floppy_release_irq_and_dma();
4350 initialising = 0; 4318 initialising = 0;
4351 if (have_no_fdc) { 4319 if (have_no_fdc) {
4352 DPRINT("no floppy controllers found\n"); 4320 DPRINT("no floppy controllers found\n");
@@ -4504,7 +4472,7 @@ static void floppy_release_irq_and_dma(void)
4504 if (irqdma_allocated) { 4472 if (irqdma_allocated) {
4505 fd_disable_dma(); 4473 fd_disable_dma();
4506 fd_free_dma(); 4474 fd_free_dma();
4507 schedule_work(&fd_free_irq_work); 4475 fd_free_irq();
4508 irqdma_allocated = 0; 4476 irqdma_allocated = 0;
4509 } 4477 }
4510 set_dor(0, ~0, 8); 4478 set_dor(0, ~0, 8);
@@ -4600,8 +4568,6 @@ void cleanup_module(void)
4600 /* eject disk, if any */ 4568 /* eject disk, if any */
4601 fd_eject(0); 4569 fd_eject(0);
4602 4570
4603 flush_scheduled_work(); /* fd_free_irq() might be pending */
4604
4605 wait_for_completion(&device_release); 4571 wait_for_completion(&device_release);
4606} 4572}
4607 4573