Commit 3e541a4ae534a7e59ad464af9abea382b3035724

Authored by Ingo Molnar
Committed by Linus Torvalds
1 parent 5863aa651b

[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 }