|
@@ -178,6 +178,7 @@ static int print_unex = 1;
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/bio.h>
|
|
#include <linux/bio.h>
|
|
|
|
+#include <linux/smp_lock.h>
|
|
#include <linux/string.h>
|
|
#include <linux/string.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/fcntl.h>
|
|
#include <linux/fcntl.h>
|
|
@@ -514,8 +515,6 @@ static unsigned long fdc_busy;
|
|
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
|
|
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
|
|
static DECLARE_WAIT_QUEUE_HEAD(command_done);
|
|
static DECLARE_WAIT_QUEUE_HEAD(command_done);
|
|
|
|
|
|
-#define NO_SIGNAL (!interruptible || !signal_pending(current))
|
|
|
|
-
|
|
|
|
/* Errors during formatting are counted here. */
|
|
/* Errors during formatting are counted here. */
|
|
static int format_errors;
|
|
static int format_errors;
|
|
|
|
|
|
@@ -539,7 +538,7 @@ static int max_buffer_sectors;
|
|
|
|
|
|
static int *errors;
|
|
static int *errors;
|
|
typedef void (*done_f)(int);
|
|
typedef void (*done_f)(int);
|
|
-static struct cont_t {
|
|
|
|
|
|
+static const struct cont_t {
|
|
void (*interrupt)(void);
|
|
void (*interrupt)(void);
|
|
/* this is called after the interrupt of the
|
|
/* this is called after the interrupt of the
|
|
* main command */
|
|
* main command */
|
|
@@ -578,7 +577,7 @@ static void reset_fdc(void);
|
|
#define NEED_1_RECAL -2
|
|
#define NEED_1_RECAL -2
|
|
#define NEED_2_RECAL -3
|
|
#define NEED_2_RECAL -3
|
|
|
|
|
|
-static int usage_count;
|
|
|
|
|
|
+static atomic_t usage_count = ATOMIC_INIT(0);
|
|
|
|
|
|
/* buffer related variables */
|
|
/* buffer related variables */
|
|
static int buffer_track = -1;
|
|
static int buffer_track = -1;
|
|
@@ -858,36 +857,15 @@ static void set_fdc(int drive)
|
|
}
|
|
}
|
|
|
|
|
|
/* locks the driver */
|
|
/* locks the driver */
|
|
-static int _lock_fdc(int drive, bool interruptible, int line)
|
|
|
|
|
|
+static int lock_fdc(int drive, bool interruptible)
|
|
{
|
|
{
|
|
- if (!usage_count) {
|
|
|
|
- pr_err("Trying to lock fdc while usage count=0 at line %d\n",
|
|
|
|
- line);
|
|
|
|
|
|
+ if (WARN(atomic_read(&usage_count) == 0,
|
|
|
|
+ "Trying to lock fdc while usage count=0\n"))
|
|
return -1;
|
|
return -1;
|
|
- }
|
|
|
|
-
|
|
|
|
- if (test_and_set_bit(0, &fdc_busy)) {
|
|
|
|
- DECLARE_WAITQUEUE(wait, current);
|
|
|
|
- add_wait_queue(&fdc_wait, &wait);
|
|
|
|
-
|
|
|
|
- for (;;) {
|
|
|
|
- set_current_state(TASK_INTERRUPTIBLE);
|
|
|
|
-
|
|
|
|
- if (!test_and_set_bit(0, &fdc_busy))
|
|
|
|
- break;
|
|
|
|
|
|
|
|
- schedule();
|
|
|
|
-
|
|
|
|
- if (!NO_SIGNAL) {
|
|
|
|
- remove_wait_queue(&fdc_wait, &wait);
|
|
|
|
- return -EINTR;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (wait_event_interruptible(fdc_wait, !test_and_set_bit(0, &fdc_busy)))
|
|
|
|
+ return -EINTR;
|
|
|
|
|
|
- set_current_state(TASK_RUNNING);
|
|
|
|
- remove_wait_queue(&fdc_wait, &wait);
|
|
|
|
- flush_scheduled_work();
|
|
|
|
- }
|
|
|
|
command_status = FD_COMMAND_NONE;
|
|
command_status = FD_COMMAND_NONE;
|
|
|
|
|
|
__reschedule_timeout(drive, "lock fdc");
|
|
__reschedule_timeout(drive, "lock fdc");
|
|
@@ -895,11 +873,8 @@ static int _lock_fdc(int drive, bool interruptible, int line)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-#define lock_fdc(drive, interruptible) \
|
|
|
|
- _lock_fdc(drive, interruptible, __LINE__)
|
|
|
|
-
|
|
|
|
/* unlocks the driver */
|
|
/* unlocks the driver */
|
|
-static inline void unlock_fdc(void)
|
|
|
|
|
|
+static void unlock_fdc(void)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
@@ -1224,7 +1199,7 @@ static int need_more_output(void)
|
|
/* Set perpendicular mode as required, based on data rate, if supported.
|
|
/* Set perpendicular mode as required, based on data rate, if supported.
|
|
* 82077 Now tested. 1Mbps data rate only possible with 82077-1.
|
|
* 82077 Now tested. 1Mbps data rate only possible with 82077-1.
|
|
*/
|
|
*/
|
|
-static inline void perpendicular_mode(void)
|
|
|
|
|
|
+static void perpendicular_mode(void)
|
|
{
|
|
{
|
|
unsigned char perp_mode;
|
|
unsigned char perp_mode;
|
|
|
|
|
|
@@ -1995,14 +1970,14 @@ static void do_wakeup(void)
|
|
wake_up(&command_done);
|
|
wake_up(&command_done);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t wakeup_cont = {
|
|
|
|
|
|
+static const struct cont_t wakeup_cont = {
|
|
.interrupt = empty,
|
|
.interrupt = empty,
|
|
.redo = do_wakeup,
|
|
.redo = do_wakeup,
|
|
.error = empty,
|
|
.error = empty,
|
|
.done = (done_f)empty
|
|
.done = (done_f)empty
|
|
};
|
|
};
|
|
|
|
|
|
-static struct cont_t intr_cont = {
|
|
|
|
|
|
+static const struct cont_t intr_cont = {
|
|
.interrupt = empty,
|
|
.interrupt = empty,
|
|
.redo = process_fd_request,
|
|
.redo = process_fd_request,
|
|
.error = empty,
|
|
.error = empty,
|
|
@@ -2015,25 +1990,10 @@ static int wait_til_done(void (*handler)(void), bool interruptible)
|
|
|
|
|
|
schedule_bh(handler);
|
|
schedule_bh(handler);
|
|
|
|
|
|
- if (command_status < 2 && NO_SIGNAL) {
|
|
|
|
- DECLARE_WAITQUEUE(wait, current);
|
|
|
|
-
|
|
|
|
- add_wait_queue(&command_done, &wait);
|
|
|
|
- for (;;) {
|
|
|
|
- set_current_state(interruptible ?
|
|
|
|
- TASK_INTERRUPTIBLE :
|
|
|
|
- TASK_UNINTERRUPTIBLE);
|
|
|
|
-
|
|
|
|
- if (command_status >= 2 || !NO_SIGNAL)
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- is_alive(__func__, "");
|
|
|
|
- schedule();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- set_current_state(TASK_RUNNING);
|
|
|
|
- remove_wait_queue(&command_done, &wait);
|
|
|
|
- }
|
|
|
|
|
|
+ if (interruptible)
|
|
|
|
+ wait_event_interruptible(command_done, command_status >= 2);
|
|
|
|
+ else
|
|
|
|
+ wait_event(command_done, command_status >= 2);
|
|
|
|
|
|
if (command_status < 2) {
|
|
if (command_status < 2) {
|
|
cancel_activity();
|
|
cancel_activity();
|
|
@@ -2223,7 +2183,7 @@ static void redo_format(void)
|
|
debugt(__func__, "queue format request");
|
|
debugt(__func__, "queue format request");
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t format_cont = {
|
|
|
|
|
|
+static const struct cont_t format_cont = {
|
|
.interrupt = format_interrupt,
|
|
.interrupt = format_interrupt,
|
|
.redo = redo_format,
|
|
.redo = redo_format,
|
|
.error = bad_flp_intr,
|
|
.error = bad_flp_intr,
|
|
@@ -2583,10 +2543,8 @@ static int make_raw_rw_request(void)
|
|
int tracksize;
|
|
int tracksize;
|
|
int ssize;
|
|
int ssize;
|
|
|
|
|
|
- if (max_buffer_sectors == 0) {
|
|
|
|
- pr_info("VFS: Block I/O scheduled on unopened device\n");
|
|
|
|
|
|
+ if (WARN(max_buffer_sectors == 0, "VFS: Block I/O scheduled on unopened device\n"))
|
|
return 0;
|
|
return 0;
|
|
- }
|
|
|
|
|
|
|
|
set_fdc((long)current_req->rq_disk->private_data);
|
|
set_fdc((long)current_req->rq_disk->private_data);
|
|
|
|
|
|
@@ -2921,7 +2879,7 @@ do_request:
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t rw_cont = {
|
|
|
|
|
|
+static const struct cont_t rw_cont = {
|
|
.interrupt = rw_interrupt,
|
|
.interrupt = rw_interrupt,
|
|
.redo = redo_fd_request,
|
|
.redo = redo_fd_request,
|
|
.error = bad_flp_intr,
|
|
.error = bad_flp_intr,
|
|
@@ -2936,19 +2894,16 @@ static void process_fd_request(void)
|
|
|
|
|
|
static void do_fd_request(struct request_queue *q)
|
|
static void do_fd_request(struct request_queue *q)
|
|
{
|
|
{
|
|
- if (max_buffer_sectors == 0) {
|
|
|
|
- pr_info("VFS: %s called on non-open device\n", __func__);
|
|
|
|
|
|
+ if (WARN(max_buffer_sectors == 0,
|
|
|
|
+ "VFS: %s called on non-open device\n", __func__))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
- if (usage_count == 0) {
|
|
|
|
- pr_info("warning: usage count=0, current_req=%p exiting\n",
|
|
|
|
- current_req);
|
|
|
|
- pr_info("sect=%ld type=%x flags=%x\n",
|
|
|
|
- (long)blk_rq_pos(current_req), current_req->cmd_type,
|
|
|
|
- current_req->cmd_flags);
|
|
|
|
|
|
+ if (WARN(atomic_read(&usage_count) == 0,
|
|
|
|
+ "warning: usage count=0, current_req=%p sect=%ld type=%x flags=%x\n",
|
|
|
|
+ current_req, (long)blk_rq_pos(current_req), current_req->cmd_type,
|
|
|
|
+ current_req->cmd_flags))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
+
|
|
if (test_bit(0, &fdc_busy)) {
|
|
if (test_bit(0, &fdc_busy)) {
|
|
/* fdc busy, this new request will be treated when the
|
|
/* fdc busy, this new request will be treated when the
|
|
current one is done */
|
|
current one is done */
|
|
@@ -2960,7 +2915,7 @@ static void do_fd_request(struct request_queue *q)
|
|
is_alive(__func__, "");
|
|
is_alive(__func__, "");
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t poll_cont = {
|
|
|
|
|
|
+static const struct cont_t poll_cont = {
|
|
.interrupt = success_and_wakeup,
|
|
.interrupt = success_and_wakeup,
|
|
.redo = floppy_ready,
|
|
.redo = floppy_ready,
|
|
.error = generic_failure,
|
|
.error = generic_failure,
|
|
@@ -2991,7 +2946,7 @@ static void reset_intr(void)
|
|
pr_info("weird, reset interrupt called\n");
|
|
pr_info("weird, reset interrupt called\n");
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t reset_cont = {
|
|
|
|
|
|
+static const struct cont_t reset_cont = {
|
|
.interrupt = reset_intr,
|
|
.interrupt = reset_intr,
|
|
.redo = success_and_wakeup,
|
|
.redo = success_and_wakeup,
|
|
.error = generic_failure,
|
|
.error = generic_failure,
|
|
@@ -3033,7 +2988,7 @@ static inline int fd_copyin(void __user *param, void *address,
|
|
return copy_from_user(address, param, size) ? -EFAULT : 0;
|
|
return copy_from_user(address, param, size) ? -EFAULT : 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline const char *drive_name(int type, int drive)
|
|
|
|
|
|
+static const char *drive_name(int type, int drive)
|
|
{
|
|
{
|
|
struct floppy_struct *floppy;
|
|
struct floppy_struct *floppy;
|
|
|
|
|
|
@@ -3096,14 +3051,14 @@ static void raw_cmd_done(int flag)
|
|
generic_done(flag);
|
|
generic_done(flag);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct cont_t raw_cmd_cont = {
|
|
|
|
|
|
+static const struct cont_t raw_cmd_cont = {
|
|
.interrupt = success_and_wakeup,
|
|
.interrupt = success_and_wakeup,
|
|
.redo = floppy_start,
|
|
.redo = floppy_start,
|
|
.error = generic_failure,
|
|
.error = generic_failure,
|
|
.done = raw_cmd_done
|
|
.done = raw_cmd_done
|
|
};
|
|
};
|
|
|
|
|
|
-static inline int raw_cmd_copyout(int cmd, void __user *param,
|
|
|
|
|
|
+static int raw_cmd_copyout(int cmd, void __user *param,
|
|
struct floppy_raw_cmd *ptr)
|
|
struct floppy_raw_cmd *ptr)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
@@ -3148,7 +3103,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static inline int raw_cmd_copyin(int cmd, void __user *param,
|
|
|
|
|
|
+static int raw_cmd_copyin(int cmd, void __user *param,
|
|
struct floppy_raw_cmd **rcmd)
|
|
struct floppy_raw_cmd **rcmd)
|
|
{
|
|
{
|
|
struct floppy_raw_cmd *ptr;
|
|
struct floppy_raw_cmd *ptr;
|
|
@@ -3266,7 +3221,7 @@ static int invalidate_drive(struct block_device *bdev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
|
|
|
|
|
|
+static int set_geometry(unsigned int cmd, struct floppy_struct *g,
|
|
int drive, int type, struct block_device *bdev)
|
|
int drive, int type, struct block_device *bdev)
|
|
{
|
|
{
|
|
int cnt;
|
|
int cnt;
|
|
@@ -3337,7 +3292,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
|
|
}
|
|
}
|
|
|
|
|
|
/* handle obsolete ioctl's */
|
|
/* handle obsolete ioctl's */
|
|
-static int ioctl_table[] = {
|
|
|
|
|
|
+static unsigned int ioctl_table[] = {
|
|
FDCLRPRM,
|
|
FDCLRPRM,
|
|
FDSETPRM,
|
|
FDSETPRM,
|
|
FDDEFPRM,
|
|
FDDEFPRM,
|
|
@@ -3365,7 +3320,7 @@ static int ioctl_table[] = {
|
|
FDTWADDLE
|
|
FDTWADDLE
|
|
};
|
|
};
|
|
|
|
|
|
-static inline int normalize_ioctl(int *cmd, int *size)
|
|
|
|
|
|
+static int normalize_ioctl(unsigned int *cmd, int *size)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
|
|
@@ -3417,7 +3372,7 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
|
|
|
|
|
|
+static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
|
|
unsigned long param)
|
|
unsigned long param)
|
|
{
|
|
{
|
|
int drive = (long)bdev->bd_disk->private_data;
|
|
int drive = (long)bdev->bd_disk->private_data;
|
|
@@ -3593,6 +3548,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int fd_ioctl(struct block_device *bdev, fmode_t mode,
|
|
|
|
+ unsigned int cmd, unsigned long param)
|
|
|
|
+{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ lock_kernel();
|
|
|
|
+ ret = fd_locked_ioctl(bdev, mode, cmd, param);
|
|
|
|
+ unlock_kernel();
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static void __init config_types(void)
|
|
static void __init config_types(void)
|
|
{
|
|
{
|
|
bool has_drive = false;
|
|
bool has_drive = false;
|
|
@@ -3649,6 +3616,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
|
|
{
|
|
{
|
|
int drive = (long)disk->private_data;
|
|
int drive = (long)disk->private_data;
|
|
|
|
|
|
|
|
+ lock_kernel();
|
|
mutex_lock(&open_lock);
|
|
mutex_lock(&open_lock);
|
|
if (UDRS->fd_ref < 0)
|
|
if (UDRS->fd_ref < 0)
|
|
UDRS->fd_ref = 0;
|
|
UDRS->fd_ref = 0;
|
|
@@ -3659,6 +3627,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode)
|
|
if (!UDRS->fd_ref)
|
|
if (!UDRS->fd_ref)
|
|
opened_bdev[drive] = NULL;
|
|
opened_bdev[drive] = NULL;
|
|
mutex_unlock(&open_lock);
|
|
mutex_unlock(&open_lock);
|
|
|
|
+ unlock_kernel();
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3676,6 +3645,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
|
|
int res = -EBUSY;
|
|
int res = -EBUSY;
|
|
char *tmp;
|
|
char *tmp;
|
|
|
|
|
|
|
|
+ lock_kernel();
|
|
mutex_lock(&open_lock);
|
|
mutex_lock(&open_lock);
|
|
old_dev = UDRS->fd_device;
|
|
old_dev = UDRS->fd_device;
|
|
if (opened_bdev[drive] && opened_bdev[drive] != bdev)
|
|
if (opened_bdev[drive] && opened_bdev[drive] != bdev)
|
|
@@ -3752,6 +3722,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
mutex_unlock(&open_lock);
|
|
mutex_unlock(&open_lock);
|
|
|
|
+ unlock_kernel();
|
|
return 0;
|
|
return 0;
|
|
out:
|
|
out:
|
|
if (UDRS->fd_ref < 0)
|
|
if (UDRS->fd_ref < 0)
|
|
@@ -3762,6 +3733,7 @@ out:
|
|
opened_bdev[drive] = NULL;
|
|
opened_bdev[drive] = NULL;
|
|
out2:
|
|
out2:
|
|
mutex_unlock(&open_lock);
|
|
mutex_unlock(&open_lock);
|
|
|
|
+ unlock_kernel();
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3829,6 +3801,7 @@ static int __floppy_read_block_0(struct block_device *bdev)
|
|
bio.bi_size = size;
|
|
bio.bi_size = size;
|
|
bio.bi_bdev = bdev;
|
|
bio.bi_bdev = bdev;
|
|
bio.bi_sector = 0;
|
|
bio.bi_sector = 0;
|
|
|
|
+ bio.bi_flags = BIO_QUIET;
|
|
init_completion(&complete);
|
|
init_completion(&complete);
|
|
bio.bi_private = &complete;
|
|
bio.bi_private = &complete;
|
|
bio.bi_end_io = floppy_rb0_complete;
|
|
bio.bi_end_io = floppy_rb0_complete;
|
|
@@ -3857,10 +3830,10 @@ static int floppy_revalidate(struct gendisk *disk)
|
|
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
|
|
if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
|
|
test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
|
|
test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
|
|
test_bit(drive, &fake_change) || NO_GEOM) {
|
|
test_bit(drive, &fake_change) || NO_GEOM) {
|
|
- if (usage_count == 0) {
|
|
|
|
- pr_info("VFS: revalidate called on non-open device.\n");
|
|
|
|
|
|
+ if (WARN(atomic_read(&usage_count) == 0,
|
|
|
|
+ "VFS: revalidate called on non-open device.\n"))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
- }
|
|
|
|
|
|
+
|
|
lock_fdc(drive, false);
|
|
lock_fdc(drive, false);
|
|
cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
|
|
cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
|
|
test_bit(FD_VERIFY_BIT, &UDRS->flags));
|
|
test_bit(FD_VERIFY_BIT, &UDRS->flags));
|
|
@@ -3893,7 +3866,7 @@ static const struct block_device_operations floppy_fops = {
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
.open = floppy_open,
|
|
.open = floppy_open,
|
|
.release = floppy_release,
|
|
.release = floppy_release,
|
|
- .locked_ioctl = fd_ioctl,
|
|
|
|
|
|
+ .ioctl = fd_ioctl,
|
|
.getgeo = fd_getgeo,
|
|
.getgeo = fd_getgeo,
|
|
.media_changed = check_floppy_change,
|
|
.media_changed = check_floppy_change,
|
|
.revalidate_disk = floppy_revalidate,
|
|
.revalidate_disk = floppy_revalidate,
|
|
@@ -4126,7 +4099,7 @@ static ssize_t floppy_cmos_show(struct device *dev,
|
|
return sprintf(buf, "%X\n", UDP->cmos);
|
|
return sprintf(buf, "%X\n", UDP->cmos);
|
|
}
|
|
}
|
|
|
|
|
|
-DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
|
|
|
|
|
|
+static DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
|
|
|
|
|
|
static void floppy_device_release(struct device *dev)
|
|
static void floppy_device_release(struct device *dev)
|
|
{
|
|
{
|
|
@@ -4175,6 +4148,9 @@ static int __init floppy_init(void)
|
|
int i, unit, drive;
|
|
int i, unit, drive;
|
|
int err, dr;
|
|
int err, dr;
|
|
|
|
|
|
|
|
+ set_debugt();
|
|
|
|
+ interruptjiffies = resultjiffies = jiffies;
|
|
|
|
+
|
|
#if defined(CONFIG_PPC)
|
|
#if defined(CONFIG_PPC)
|
|
if (check_legacy_ioport(FDC1))
|
|
if (check_legacy_ioport(FDC1))
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
@@ -4353,7 +4329,7 @@ out_unreg_platform_dev:
|
|
platform_device_unregister(&floppy_device[drive]);
|
|
platform_device_unregister(&floppy_device[drive]);
|
|
out_flush_work:
|
|
out_flush_work:
|
|
flush_scheduled_work();
|
|
flush_scheduled_work();
|
|
- if (usage_count)
|
|
|
|
|
|
+ if (atomic_read(&usage_count))
|
|
floppy_release_irq_and_dma();
|
|
floppy_release_irq_and_dma();
|
|
out_unreg_region:
|
|
out_unreg_region:
|
|
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
|
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
|
@@ -4370,8 +4346,6 @@ out_put_disk:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-static DEFINE_SPINLOCK(floppy_usage_lock);
|
|
|
|
-
|
|
|
|
static const struct io_region {
|
|
static const struct io_region {
|
|
int offset;
|
|
int offset;
|
|
int size;
|
|
int size;
|
|
@@ -4417,14 +4391,8 @@ static void floppy_release_regions(int fdc)
|
|
|
|
|
|
static int floppy_grab_irq_and_dma(void)
|
|
static int floppy_grab_irq_and_dma(void)
|
|
{
|
|
{
|
|
- unsigned long flags;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&floppy_usage_lock, flags);
|
|
|
|
- if (usage_count++) {
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+ if (atomic_inc_return(&usage_count) > 1)
|
|
return 0;
|
|
return 0;
|
|
- }
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* We might have scheduled a free_irq(), wait it to
|
|
* We might have scheduled a free_irq(), wait it to
|
|
@@ -4435,9 +4403,7 @@ static int floppy_grab_irq_and_dma(void)
|
|
if (fd_request_irq()) {
|
|
if (fd_request_irq()) {
|
|
DPRINT("Unable to grab IRQ%d for the floppy driver\n",
|
|
DPRINT("Unable to grab IRQ%d for the floppy driver\n",
|
|
FLOPPY_IRQ);
|
|
FLOPPY_IRQ);
|
|
- spin_lock_irqsave(&floppy_usage_lock, flags);
|
|
|
|
- usage_count--;
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+ atomic_dec(&usage_count);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
if (fd_request_dma()) {
|
|
if (fd_request_dma()) {
|
|
@@ -4447,9 +4413,7 @@ static int floppy_grab_irq_and_dma(void)
|
|
use_virtual_dma = can_use_virtual_dma = 1;
|
|
use_virtual_dma = can_use_virtual_dma = 1;
|
|
if (!(can_use_virtual_dma & 1)) {
|
|
if (!(can_use_virtual_dma & 1)) {
|
|
fd_free_irq();
|
|
fd_free_irq();
|
|
- spin_lock_irqsave(&floppy_usage_lock, flags);
|
|
|
|
- usage_count--;
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+ atomic_dec(&usage_count);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -4484,9 +4448,7 @@ cleanup:
|
|
fd_free_dma();
|
|
fd_free_dma();
|
|
while (--fdc >= 0)
|
|
while (--fdc >= 0)
|
|
floppy_release_regions(fdc);
|
|
floppy_release_regions(fdc);
|
|
- spin_lock_irqsave(&floppy_usage_lock, flags);
|
|
|
|
- usage_count--;
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+ atomic_dec(&usage_count);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4498,14 +4460,10 @@ static void floppy_release_irq_and_dma(void)
|
|
#endif
|
|
#endif
|
|
long tmpsize;
|
|
long tmpsize;
|
|
unsigned long tmpaddr;
|
|
unsigned long tmpaddr;
|
|
- unsigned long flags;
|
|
|
|
|
|
|
|
- spin_lock_irqsave(&floppy_usage_lock, flags);
|
|
|
|
- if (--usage_count) {
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+ if (!atomic_dec_and_test(&usage_count))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
- spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
|
|
|
|
|
+
|
|
if (irqdma_allocated) {
|
|
if (irqdma_allocated) {
|
|
fd_disable_dma();
|
|
fd_disable_dma();
|
|
fd_free_dma();
|
|
fd_free_dma();
|
|
@@ -4598,7 +4556,7 @@ static void __exit floppy_module_exit(void)
|
|
del_timer_sync(&fd_timer);
|
|
del_timer_sync(&fd_timer);
|
|
blk_cleanup_queue(floppy_queue);
|
|
blk_cleanup_queue(floppy_queue);
|
|
|
|
|
|
- if (usage_count)
|
|
|
|
|
|
+ if (atomic_read(&usage_count))
|
|
floppy_release_irq_and_dma();
|
|
floppy_release_irq_and_dma();
|
|
|
|
|
|
/* eject disk, if any */
|
|
/* eject disk, if any */
|