Commit 3e541a4ae534a7e59ad464af9abea382b3035724
Committed by
Linus Torvalds
1 parent
5863aa651b
Exists in
master
and in
4 other branches
[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>
Showing 1 changed file with 4 additions and 38 deletions Side-by-side Diff
drivers/block/floppy.c
| ... | ... | @@ -249,18 +249,6 @@ |
| 249 | 249 | #include <linux/cdrom.h> /* for the compatibility eject ioctl */ |
| 250 | 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 | - */ | |
| 256 | -static void fd_free_irq_fn(void *data) | |
| 257 | -{ | |
| 258 | - fd_free_irq(); | |
| 259 | -} | |
| 260 | - | |
| 261 | -static DECLARE_WORK(fd_free_irq_work, fd_free_irq_fn, NULL); | |
| 262 | - | |
| 263 | - | |
| 264 | 252 | static struct request *current_req; |
| 265 | 253 | static struct request_queue *floppy_queue; |
| 266 | 254 | static void do_fd_request(request_queue_t * q); |
| ... | ... | @@ -826,15 +814,6 @@ |
| 826 | 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 | 817 | return olddor; |
| 839 | 818 | } |
| 840 | 819 | |
| ... | ... | @@ -892,8 +871,6 @@ |
| 892 | 871 | line); |
| 893 | 872 | return -1; |
| 894 | 873 | } |
| 895 | - if (floppy_grab_irq_and_dma() == -1) | |
| 896 | - return -EBUSY; | |
| 897 | 874 | |
| 898 | 875 | if (test_and_set_bit(0, &fdc_busy)) { |
| 899 | 876 | DECLARE_WAITQUEUE(wait, current); |
| ... | ... | @@ -915,6 +892,8 @@ |
| 915 | 892 | |
| 916 | 893 | set_current_state(TASK_RUNNING); |
| 917 | 894 | remove_wait_queue(&fdc_wait, &wait); |
| 895 | + | |
| 896 | + flush_scheduled_work(); | |
| 918 | 897 | } |
| 919 | 898 | command_status = FD_COMMAND_NONE; |
| 920 | 899 | |
| ... | ... | @@ -948,7 +927,6 @@ |
| 948 | 927 | if (elv_next_request(floppy_queue)) |
| 949 | 928 | do_fd_request(floppy_queue); |
| 950 | 929 | spin_unlock_irqrestore(&floppy_lock, flags); |
| 951 | - floppy_release_irq_and_dma(); | |
| 952 | 930 | wake_up(&fdc_wait); |
| 953 | 931 | } |
| 954 | 932 | |
| 955 | 933 | |
| ... | ... | @@ -3694,8 +3672,8 @@ |
| 3694 | 3672 | } |
| 3695 | 3673 | if (!UDRS->fd_ref) |
| 3696 | 3674 | opened_bdev[drive] = NULL; |
| 3697 | - floppy_release_irq_and_dma(); | |
| 3698 | 3675 | mutex_unlock(&open_lock); |
| 3676 | + | |
| 3699 | 3677 | return 0; |
| 3700 | 3678 | } |
| 3701 | 3679 | |
| ... | ... | @@ -3726,9 +3704,6 @@ |
| 3726 | 3704 | if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL))) |
| 3727 | 3705 | goto out2; |
| 3728 | 3706 | |
| 3729 | - if (floppy_grab_irq_and_dma()) | |
| 3730 | - goto out2; | |
| 3731 | - | |
| 3732 | 3707 | if (filp->f_flags & O_EXCL) |
| 3733 | 3708 | UDRS->fd_ref = -1; |
| 3734 | 3709 | else |
| ... | ... | @@ -3805,7 +3780,6 @@ |
| 3805 | 3780 | UDRS->fd_ref--; |
| 3806 | 3781 | if (!UDRS->fd_ref) |
| 3807 | 3782 | opened_bdev[drive] = NULL; |
| 3808 | - floppy_release_irq_and_dma(); | |
| 3809 | 3783 | out2: |
| 3810 | 3784 | mutex_unlock(&open_lock); |
| 3811 | 3785 | return res; |
| 3812 | 3786 | |
| ... | ... | @@ -3822,14 +3796,9 @@ |
| 3822 | 3796 | return 1; |
| 3823 | 3797 | |
| 3824 | 3798 | if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { |
| 3825 | - if (floppy_grab_irq_and_dma()) { | |
| 3826 | - return 1; | |
| 3827 | - } | |
| 3828 | - | |
| 3829 | 3799 | lock_fdc(drive, 0); |
| 3830 | 3800 | poll_drive(0, 0); |
| 3831 | 3801 | process_fd_request(); |
| 3832 | - floppy_release_irq_and_dma(); | |
| 3833 | 3802 | } |
| 3834 | 3803 | |
| 3835 | 3804 | if (UTESTF(FD_DISK_CHANGED) || |
| ... | ... | @@ -4346,7 +4315,6 @@ |
| 4346 | 4315 | fdc = 0; |
| 4347 | 4316 | del_timer(&fd_timeout); |
| 4348 | 4317 | current_drive = 0; |
| 4349 | - floppy_release_irq_and_dma(); | |
| 4350 | 4318 | initialising = 0; |
| 4351 | 4319 | if (have_no_fdc) { |
| 4352 | 4320 | DPRINT("no floppy controllers found\n"); |
| ... | ... | @@ -4504,7 +4472,7 @@ |
| 4504 | 4472 | if (irqdma_allocated) { |
| 4505 | 4473 | fd_disable_dma(); |
| 4506 | 4474 | fd_free_dma(); |
| 4507 | - schedule_work(&fd_free_irq_work); | |
| 4475 | + fd_free_irq(); | |
| 4508 | 4476 | irqdma_allocated = 0; |
| 4509 | 4477 | } |
| 4510 | 4478 | set_dor(0, ~0, 8); |
| ... | ... | @@ -4599,8 +4567,6 @@ |
| 4599 | 4567 | |
| 4600 | 4568 | /* eject disk, if any */ |
| 4601 | 4569 | fd_eject(0); |
| 4602 | - | |
| 4603 | - flush_scheduled_work(); /* fd_free_irq() might be pending */ | |
| 4604 | 4570 | |
| 4605 | 4571 | wait_for_completion(&device_release); |
| 4606 | 4572 | } |