Staging: phison: depends on ATA_BMDMA
[safe/jmp/linux-2.6] / drivers / block / floppy.c
index 8e24aa3..90c4038 100644 (file)
  * Better audit of register_blkdev.
  */
 
-#define FLOPPY_SANITY_CHECK
 #undef  FLOPPY_SILENT_DCL_CLEAR
 
 #define REALLY_SLOW_IO
 
 #define DEBUGT 2
-#define DCL_DEBUG              /* debug disk change line */
 
+#define DPRINT(format, args...) \
+       pr_info("floppy%d: " format, current_drive, ##args)
+
+#define DCL_DEBUG              /* debug disk change line */
 #ifdef DCL_DEBUG
 #define debug_dcl(test, fmt, args...) \
        do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0)
        do { if (0) DPRINT(fmt, ##args); } while (0)
 #endif
 
-
 /* do print messages for unexpected interrupts */
 static int print_unex = 1;
 #include <linux/module.h>
@@ -309,9 +310,6 @@ static bool initialized;
 #define UDRWE  (&write_errors[drive])
 #define UFDCS  (&fdc_state[FDC(drive)])
 
-#define DPRINT(format, args...) \
-       pr_info("floppy%d: " format, current_drive, ##args)
-
 #define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2)
 #define STRETCH(floppy)        ((floppy)->stretch & FD_STRETCH)
 
@@ -346,7 +344,7 @@ static bool initialized;
  */
 #define MAX_REPLIES 16
 static unsigned char reply_buffer[MAX_REPLIES];
-static int inr;                        /* size of reply buffer, when called from interrupt */
+static int inr;                /* size of reply buffer, when called from interrupt */
 #define ST0            (reply_buffer[0])
 #define ST1            (reply_buffer[1])
 #define ST2            (reply_buffer[2])
@@ -618,14 +616,14 @@ static inline void set_debugt(void)
        debugtimer = jiffies;
 }
 
-static inline void debugt(const char *message)
+static inline void debugt(const char *func, const char *msg)
 {
        if (DP->flags & DEBUGT)
-               pr_info("%s dtime=%lu\n", message, jiffies - debugtimer);
+               pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer);
 }
 #else
 static inline void set_debugt(void) { }
-static inline void debugt(const char *message) { }
+static inline void debugt(const char *func, const char *msg) { }
 #endif /* DEBUGT */
 
 typedef void (*timeout_fn)(unsigned long);
@@ -633,21 +631,17 @@ static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
 
 static const char *timeout_message;
 
-#ifdef FLOPPY_SANITY_CHECK
-static void is_alive(const char *message)
+static void is_alive(const char *func, const char *message)
 {
        /* this routine checks whether the floppy driver is "alive" */
        if (test_bit(0, &fdc_busy) && command_status < 2 &&
            !timer_pending(&fd_timeout)) {
-               DPRINT("timeout handler died: %s\n", message);
+               DPRINT("%s: timeout handler died.  %s\n", func, message);
        }
 }
-#endif
 
 static void (*do_floppy)(void) = NULL;
 
-#ifdef FLOPPY_SANITY_CHECK
-
 #define OLOGSIZE 20
 
 static void (*lasthandler)(void);
@@ -663,12 +657,11 @@ static struct output_log {
 } output_log[OLOGSIZE];
 
 static int output_log_pos;
-#endif
 
 #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)
 {
        if (drive == current_reqD)
                drive = current_drive;
@@ -680,16 +673,16 @@ static void __reschedule_timeout(int drive, const char *message, int marg)
                fd_timeout.expires = jiffies + UDP->timeout;
        add_timer(&fd_timeout);
        if (UDP->flags & FD_DEBUG)
-               DPRINT("reschedule timeout %s %d\n", message, marg);
+               DPRINT("reschedule timeout %s\n", message);
        timeout_message = message;
 }
 
-static void reschedule_timeout(int drive, const char *message, int marg)
+static void reschedule_timeout(int drive, const char *message)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&floppy_lock, flags);
-       __reschedule_timeout(drive, message, marg);
+       __reschedule_timeout(drive, message);
        spin_unlock_irqrestore(&floppy_lock, flags);
 }
 
@@ -733,7 +726,6 @@ static int disk_change(int drive)
 {
        int fdc = FDC(drive);
 
-#ifdef FLOPPY_SANITY_CHECK
        if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
                DPRINT("WARNING disk change called early\n");
        if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
@@ -742,7 +734,6 @@ static int disk_change(int drive)
                DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive),
                       (unsigned int)FDCS->dor);
        }
-#endif
 
        debug_dcl(UDP->flags,
                  "checking disk change line for drive %d\n", drive);
@@ -763,8 +754,7 @@ static int disk_change(int drive)
                if (UDRS->keep_data >= 0) {
                        if ((UDP->flags & FTD_MSG) &&
                            current_type[drive] != NULL)
-                               DPRINT("Disk type is undefined after "
-                                      "disk change\n");
+                               DPRINT("Disk type is undefined after disk change\n");
                        current_type[drive] = NULL;
                        floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
                }
@@ -900,7 +890,7 @@ static int _lock_fdc(int drive, bool interruptible, int line)
        }
        command_status = FD_COMMAND_NONE;
 
-       __reschedule_timeout(drive, "lock fdc", 0);
+       __reschedule_timeout(drive, "lock fdc");
        set_fdc(drive);
        return 0;
 }
@@ -918,7 +908,7 @@ static inline void unlock_fdc(void)
                DPRINT("FDC access conflict!\n");
 
        if (do_floppy)
-               DPRINT("device interrupt still active at FDC release: %p!\n",
+               DPRINT("device interrupt still active at FDC release: %pf!\n",
                       do_floppy);
        command_status = FD_COMMAND_NONE;
        spin_lock_irqsave(&floppy_lock, flags);
@@ -1095,7 +1085,6 @@ static void setup_DMA(void)
 {
        unsigned long f;
 
-#ifdef FLOPPY_SANITY_CHECK
        if (raw_cmd->length == 0) {
                int i;
 
@@ -1113,7 +1102,6 @@ static void setup_DMA(void)
                FDCS->reset = 1;
                return;
        }
-#endif
        f = claim_dma_lock();
        fd_disable_dma();
 #ifdef fd_dma_setup
@@ -1173,12 +1161,10 @@ static int output_byte(char byte)
 
        if (is_ready_state(status)) {
                fd_outb(byte, FD_DATA);
-#ifdef FLOPPY_SANITY_CHECK
                output_log[output_log_pos].data = byte;
                output_log[output_log_pos].status = status;
                output_log[output_log_pos].jiffies = jiffies;
                output_log_pos = (output_log_pos + 1) % OLOGSIZE;
-#endif
                return 0;
        }
        FDCS->reset = 1;
@@ -1202,10 +1188,8 @@ static int result(void)
                        break;
                status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
                if ((status & ~STATUS_BUSY) == STATUS_READY) {
-#ifdef FLOPPY_SANITY_CHECK
                        resultjiffies = jiffies;
                        resultsize = i;
-#endif
                        return i;
                }
                if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
@@ -1461,7 +1445,7 @@ static int interpret_errors(void)
        char bad;
 
        if (inr != 7) {
-               DPRINT("-- FDC reply error");
+               DPRINT("-- FDC reply error\n");
                FDCS->reset = 1;
                return 1;
        }
@@ -1549,7 +1533,7 @@ static void setup_rw_floppy(void)
        for (i = 0; i < raw_cmd->cmd_count; i++)
                r |= output_byte(raw_cmd->cmd[i]);
 
-       debugt("rw_command: ");
+       debugt(__func__, "rw_command");
 
        if (r) {
                cont->error();
@@ -1572,7 +1556,7 @@ static int blind_seek;
  */
 static void seek_interrupt(void)
 {
-       debugt("seek interrupt:");
+       debugt(__func__, "");
        if (inr != 2 || (ST0 & 0xF8) != 0x20) {
                DPRINT("seek failed\n");
                DRS->track = NEED_2_RECAL;
@@ -1620,7 +1604,7 @@ static void seek_floppy(void)
 
        blind_seek = 0;
 
-       debug_dcl(DP->flags, "calling disk change from seek\n");
+       debug_dcl(DP->flags, "calling disk change from %s\n", __func__);
 
        if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) &&
            disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
@@ -1669,18 +1653,18 @@ static void seek_floppy(void)
                reset_fdc();
                return;
        }
-       debugt("seek command:");
+       debugt(__func__, "");
 }
 
 static void recal_interrupt(void)
 {
-       debugt("recal interrupt:");
+       debugt(__func__, "");
        if (inr != 2)
                FDCS->reset = 1;
        else if (ST0 & ST0_ECE) {
                switch (DRS->track) {
                case NEED_1_RECAL:
-                       debugt("recal interrupt need 1 recal:");
+                       debugt(__func__, "need 1 recal");
                        /* after a second recalibrate, we still haven't
                         * reached track 0. Probably no drive. Raise an
                         * error, as failing immediately might upset
@@ -1689,7 +1673,7 @@ static void recal_interrupt(void)
                        cont->redo();
                        return;
                case NEED_2_RECAL:
-                       debugt("recal interrupt need 2 recal:");
+                       debugt(__func__, "need 2 recal");
                        /* If we already did a recalibrate,
                         * and we are not at track 0, this
                         * means we have moved. (The only way
@@ -1703,7 +1687,7 @@ static void recal_interrupt(void)
                        DRS->select_date = jiffies;
                        /* fall through */
                default:
-                       debugt("recal interrupt default:");
+                       debugt(__func__, "default");
                        /* Recalibrate moves the head by at
                         * most 80 steps. If after one
                         * recalibrate we don't have reached
@@ -1749,8 +1733,8 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id)
                /* we don't even know which FDC is the culprit */
                pr_info("DOR0=%x\n", fdc_state[0].dor);
                pr_info("floppy interrupt on bizarre fdc %d\n", fdc);
-               pr_info("handler=%p\n", handler);
-               is_alive("bizarre fdc");
+               pr_info("handler=%pf\n", handler);
+               is_alive(__func__, "bizarre fdc");
                return IRQ_NONE;
        }
 
@@ -1785,7 +1769,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id)
                return IRQ_NONE;
        }
        schedule_bh(handler);
-       is_alive("normal interrupt end");
+       is_alive(__func__, "normal interrupt end");
 
        /* FIXME! Was it really for us? */
        return IRQ_HANDLED;
@@ -1793,7 +1777,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id)
 
 static void recalibrate_floppy(void)
 {
-       debugt("recalibrate floppy:");
+       debugt(__func__, "");
        do_floppy = recal_interrupt;
        output_byte(FD_RECALIBRATE);
        if (output_byte(UNIT(current_drive)) < 0)
@@ -1805,10 +1789,10 @@ static void recalibrate_floppy(void)
  */
 static void reset_interrupt(void)
 {
-       debugt("reset interrupt:");
+       debugt(__func__, "");
        result();               /* get the status ready for set_fdc */
        if (FDCS->reset) {
-               pr_info("reset set in interrupt, calling %p\n", cont->error);
+               pr_info("reset set in interrupt, calling %pf\n", cont->error);
                cont->error();  /* a reset just after a reset. BAD! */
        }
        cont->redo();
@@ -1849,11 +1833,10 @@ static void show_floppy(void)
        pr_info("\n");
        pr_info("floppy driver state\n");
        pr_info("-------------------\n");
-       pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
+       pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%pf\n",
                jiffies, interruptjiffies, jiffies - interruptjiffies,
                lasthandler);
 
-#ifdef FLOPPY_SANITY_CHECK
        pr_info("timeout_message=%s\n", timeout_message);
        pr_info("last output bytes:\n");
        for (i = 0; i < OLOGSIZE; i++)
@@ -1865,18 +1848,17 @@ static void show_floppy(void)
        pr_info("last redo_fd_request at %lu\n", lastredo);
        print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
                       reply_buffer, resultsize, true);
-#endif
 
        pr_info("status=%x\n", fd_inb(FD_STATUS));
        pr_info("fdc_busy=%lu\n", fdc_busy);
        if (do_floppy)
-               pr_info("do_floppy=%p\n", do_floppy);
+               pr_info("do_floppy=%pf\n", do_floppy);
        if (work_pending(&floppy_work))
-               pr_info("floppy_work.func=%p\n", floppy_work.func);
+               pr_info("floppy_work.func=%pf\n", floppy_work.func);
        if (timer_pending(&fd_timer))
-               pr_info("fd_timer.function=%p\n", fd_timer.function);
+               pr_info("fd_timer.function=%pf\n", fd_timer.function);
        if (timer_pending(&fd_timeout)) {
-               pr_info("timer_function=%p\n", fd_timeout.function);
+               pr_info("timer_function=%pf\n", fd_timeout.function);
                pr_info("expires=%lu\n", fd_timeout.expires - jiffies);
                pr_info("now=%lu\n", jiffies);
        }
@@ -1912,7 +1894,7 @@ static void floppy_shutdown(unsigned long data)
                pr_info("no cont in shutdown!\n");
                process_fd_request();
        }
-       is_alive("floppy shutdown");
+       is_alive(__func__, "");
 }
 
 /* start motor, check media-changed condition and write protection */
@@ -1983,7 +1965,7 @@ static void floppy_ready(void)
 
 static void floppy_start(void)
 {
-       reschedule_timeout(current_reqD, "floppy start", 0);
+       reschedule_timeout(current_reqD, "floppy start");
 
        scandrives();
        debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n");
@@ -2007,7 +1989,7 @@ static void floppy_start(void)
 
 static void do_wakeup(void)
 {
-       reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
+       reschedule_timeout(MAXTIMEOUT, "do wakeup");
        cont = NULL;
        command_status += 2;
        wake_up(&command_done);
@@ -2045,7 +2027,7 @@ static int wait_til_done(void (*handler)(void), bool interruptible)
                        if (command_status >= 2 || !NO_SIGNAL)
                                break;
 
-                       is_alive("wait_til_done");
+                       is_alive(__func__, "");
                        schedule();
                }
 
@@ -2161,7 +2143,6 @@ static void format_interrupt(void)
        cont->redo();
 }
 
-#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
 #define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1))
 #define CT(x) ((x) | 0xc0)
 
@@ -2239,7 +2220,7 @@ static void redo_format(void)
        buffer_track = -1;
        setup_format_params(format_req.track << STRETCH(_floppy));
        floppy_start();
-       debugt("queue format request");
+       debugt(__func__, "queue format request");
 }
 
 static struct cont_t format_cont = {
@@ -2306,9 +2287,11 @@ static void request_done(int uptodate)
        struct request *req = current_req;
        unsigned long flags;
        int block;
+       char msg[sizeof("request done ") + sizeof(int) * 3];
 
        probing = 0;
-       reschedule_timeout(MAXTIMEOUT, "request done", uptodate);
+       snprintf(msg, sizeof(msg), "request done %d", uptodate);
+       reschedule_timeout(MAXTIMEOUT, msg);
 
        if (!req) {
                pr_info("floppy.c: no request in request_done\n");
@@ -2363,7 +2346,7 @@ static void rw_interrupt(void)
                DRS->first_read_date = jiffies;
 
        nr_sectors = 0;
-       CODE2SIZE;
+       ssize = DIV_ROUND_UP(1 << SIZECODE, 4);
 
        if (ST1 & ST1_EOC)
                eoc = 1;
@@ -2379,7 +2362,6 @@ static void rw_interrupt(void)
                       R_HEAD - HEAD) * SECT_PER_TRACK +
                      R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
 
-#ifdef FLOPPY_SANITY_CHECK
        if (nr_sectors / ssize >
            DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
                DPRINT("long rw: %x instead of %lx\n",
@@ -2392,7 +2374,6 @@ static void rw_interrupt(void)
                        SECT_PER_TRACK, fsector_t, ssize);
                pr_info("in_sector_offset=%d\n", in_sector_offset);
        }
-#endif
 
        nr_sectors -= in_sector_offset;
        INFBOUND(nr_sectors, 0);
@@ -2497,7 +2478,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                                              blk_rq_sectors(current_req));
 
        remaining = current_count_sectors << 9;
-#ifdef FLOPPY_SANITY_CHECK
        if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) {
                DPRINT("in copy buffer\n");
                pr_info("current_count_sectors=%ld\n", current_count_sectors);
@@ -2509,7 +2489,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                pr_info("max_sector=%d\n", max_sector);
                pr_info("ssize=%d\n", ssize);
        }
-#endif
 
        buffer_max = max(max_sector, buffer_max);
 
@@ -2525,7 +2504,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                SUPBOUND(size, remaining);
 
                buffer = page_address(bv->bv_page) + bv->bv_offset;
-#ifdef FLOPPY_SANITY_CHECK
                if (dma_buffer + size >
                    floppy_track_buffer + (max_buffer_sectors << 10) ||
                    dma_buffer < floppy_track_buffer) {
@@ -2543,7 +2521,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                }
                if (((unsigned long)buffer) % 512)
                        DPRINT("%p buffer not aligned\n", buffer);
-#endif
+
                if (CT(COMMAND) == FD_READ)
                        memcpy(buffer, dma_buffer, size);
                else
@@ -2552,13 +2530,11 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                remaining -= size;
                dma_buffer += size;
        }
-#ifdef FLOPPY_SANITY_CHECK
        if (remaining) {
                if (remaining > 0)
                        max_sector -= remaining >> 9;
                DPRINT("weirdness: remaining %d\n", remaining >> 9);
        }
-#endif
 }
 
 /* work around a bug in pseudo DMA
@@ -2578,13 +2554,11 @@ static void virtualdmabug_workaround(void)
 
                hard_sectors = raw_cmd->length >> (7 + SIZECODE);
                end_sector = SECTOR + hard_sectors - 1;
-#ifdef FLOPPY_SANITY_CHECK
                if (end_sector > SECT_PER_TRACK) {
                        pr_info("too many sectors %d > %d\n",
                                end_sector, SECT_PER_TRACK);
                        return;
                }
-#endif
                SECT_PER_TRACK = end_sector;
                                        /* make sure SECT_PER_TRACK
                                         * points to end of transfer */
@@ -2627,7 +2601,7 @@ static int make_raw_rw_request(void)
                raw_cmd->flags |= FD_RAW_WRITE;
                COMMAND = FM_MODE(_floppy, FD_WRITE);
        } else {
-               DPRINT("make_raw_rw_request: unknown command\n");
+               DPRINT("%s: unknown command\n", __func__);
                return 0;
        }
 
@@ -2672,7 +2646,7 @@ static int make_raw_rw_request(void)
        raw_cmd->track = TRACK << STRETCH(_floppy);
        DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
        GAP = _floppy->gap;
-       CODE2SIZE;
+       ssize = DIV_ROUND_UP(1 << SIZECODE, 4);
        SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
        SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
            FD_SECTBASE(_floppy);
@@ -2768,7 +2742,7 @@ static int make_raw_rw_request(void)
                        raw_cmd->kernel_data = current_req->buffer;
                        raw_cmd->length = current_count_sectors << 9;
                        if (raw_cmd->length == 0) {
-                               DPRINT("zero dma transfer attempted from make_raw_request\n");
+                               DPRINT("%s: zero dma transfer attempted\n", __func__);
                                DPRINT("indirect=%d direct=%d fsector_t=%d\n",
                                       indirect, direct, fsector_t);
                                return 0;
@@ -2803,10 +2777,8 @@ static int make_raw_rw_request(void)
                 * if we get here, we know that the write
                 * is either aligned or the data already in the buffer
                 * (buffer will be overwritten) */
-#ifdef FLOPPY_SANITY_CHECK
                if (in_sector_offset && buffer_track == -1)
                        DPRINT("internal error offset !=0 on write\n");
-#endif
                buffer_track = raw_cmd->track;
                buffer_drive = current_drive;
                copy_buffer(ssize, max_sector,
@@ -2820,7 +2792,6 @@ static int make_raw_rw_request(void)
        raw_cmd->length = in_sector_offset + current_count_sectors;
        raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
        raw_cmd->length <<= 9;
-#ifdef FLOPPY_SANITY_CHECK
        if ((raw_cmd->length < current_count_sectors << 9) ||
            (raw_cmd->kernel_data != current_req->buffer &&
             CT(COMMAND) == FD_WRITE &&
@@ -2877,7 +2848,6 @@ static int make_raw_rw_request(void)
                DPRINT("zero dma transfer attempted from make_raw_request\n");
                return 0;
        }
-#endif
 
        virtualdmabug_workaround();
        return 2;
@@ -2908,7 +2878,7 @@ do_request:
        }
        drive = (long)current_req->rq_disk->private_data;
        set_fdc(drive);
-       reschedule_timeout(current_reqD, "redo fd request", 0);
+       reschedule_timeout(current_reqD, "redo fd request");
 
        set_floppy(drive);
        raw_cmd = &default_raw_cmd;
@@ -2947,7 +2917,7 @@ do_request:
        if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags))
                twaddle();
        schedule_bh(floppy_start);
-       debugt("queue fd request");
+       debugt(__func__, "queue fd request");
        return;
 }
 
@@ -2967,7 +2937,7 @@ static void process_fd_request(void)
 static void do_fd_request(struct request_queue *q)
 {
        if (max_buffer_sectors == 0) {
-               pr_info("VFS: do_fd_request called on non-open device\n");
+               pr_info("VFS: %s called on non-open device\n", __func__);
                return;
        }
 
@@ -2982,12 +2952,12 @@ static void do_fd_request(struct request_queue *q)
        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");
+               is_alive(__func__, "old request running");
                return;
        }
        lock_fdc(MAXTIMEOUT, false);
        process_fd_request();
-       is_alive("do fd request");
+       is_alive(__func__, "");
 }
 
 static struct cont_t poll_cont = {
@@ -3133,13 +3103,13 @@ static struct cont_t raw_cmd_cont = {
        .done           = raw_cmd_done
 };
 
-static inline int raw_cmd_copyout(int cmd, char __user *param,
+static inline int raw_cmd_copyout(int cmd, void __user *param,
                                  struct floppy_raw_cmd *ptr)
 {
        int ret;
 
        while (ptr) {
-               ret = copy_to_user((void __user *)param, ptr, sizeof(*ptr));
+               ret = copy_to_user(param, ptr, sizeof(*ptr));
                if (ret)
                        return -EFAULT;
                param += sizeof(struct floppy_raw_cmd);
@@ -3155,6 +3125,7 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
                }
                ptr = ptr->next;
        }
+
        return 0;
 }
 
@@ -3177,7 +3148,7 @@ static void raw_cmd_free(struct floppy_raw_cmd **ptr)
        }
 }
 
-static inline int raw_cmd_copyin(int cmd, char __user *param,
+static inline int raw_cmd_copyin(int cmd, void __user *param,
                                 struct floppy_raw_cmd **rcmd)
 {
        struct floppy_raw_cmd *ptr;
@@ -3185,19 +3156,19 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
        int i;
 
        *rcmd = NULL;
-       while (1) {
-               ptr = (struct floppy_raw_cmd *)
-                   kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
-               if (!ptr)
-                       return -ENOMEM;
-               *rcmd = ptr;
-               ret = copy_from_user(ptr, (void __user *)param, sizeof(*ptr));
-               if (ret)
-                       return -EFAULT;
-               ptr->next = NULL;
-               ptr->buffer_length = 0;
-               param += sizeof(struct floppy_raw_cmd);
-               if (ptr->cmd_count > 33)
+
+loop:
+       ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
+       if (!ptr)
+               return -ENOMEM;
+       *rcmd = ptr;
+       ret = copy_from_user(ptr, param, sizeof(*ptr));
+       if (ret)
+               return -EFAULT;
+       ptr->next = NULL;
+       ptr->buffer_length = 0;
+       param += sizeof(struct floppy_raw_cmd);
+       if (ptr->cmd_count > 33)
                        /* the command may now also take up the space
                         * initially intended for the reply & the
                         * reply count. Needed for long 82078 commands
@@ -3206,34 +3177,35 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
                         * 16 bytes for a structure, you'll one day
                         * discover that you really need 17...
                         */
+               return -EINVAL;
+
+       for (i = 0; i < 16; i++)
+               ptr->reply[i] = 0;
+       ptr->resultcode = 0;
+       ptr->kernel_data = NULL;
+
+       if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
+               if (ptr->length <= 0)
                        return -EINVAL;
+               ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length);
+               fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
+               if (!ptr->kernel_data)
+                       return -ENOMEM;
+               ptr->buffer_length = ptr->length;
+       }
+       if (ptr->flags & FD_RAW_WRITE) {
+               ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length);
+               if (ret)
+                       return ret;
+       }
 
-               for (i = 0; i < 16; i++)
-                       ptr->reply[i] = 0;
-               ptr->resultcode = 0;
-               ptr->kernel_data = NULL;
-
-               if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
-                       if (ptr->length <= 0)
-                               return -EINVAL;
-                       ptr->kernel_data =
-                           (char *)fd_dma_mem_alloc(ptr->length);
-                       fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
-                       if (!ptr->kernel_data)
-                               return -ENOMEM;
-                       ptr->buffer_length = ptr->length;
-               }
-               if (ptr->flags & FD_RAW_WRITE) {
-                       ret = fd_copyin(ptr->data, ptr->kernel_data,
-                                       ptr->length);
-                       if (ret)
-                               return ret;
-               }
+       if (ptr->flags & FD_RAW_MORE) {
                rcmd = &(ptr->next);
-               if (!(ptr->flags & FD_RAW_MORE))
-                       return 0;
                ptr->rate &= 0x43;
+               goto loop;
        }
+
+       return 0;
 }
 
 static int raw_cmd_ioctl(int cmd, void __user *param)
@@ -3448,8 +3420,6 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                    unsigned long param)
 {
-#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
-
        int drive = (long)bdev->bd_disk->private_data;
        int type = ITYPE(UDRS->fd_device);
        int i;
@@ -3461,7 +3431,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                struct floppy_max_errors max_errors;
                struct floppy_drive_params dp;
        } inparam;              /* parameters coming from user space */
-       const char *outparam;   /* parameters passed back to user space */
+       const void *outparam;   /* parameters passed back to user space */
 
        /* convert compatibility eject ioctls into floppy eject ioctl.
         * We do this in order to provide a means to eject floppy disks before
@@ -3482,7 +3452,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                return ret;
 
        /* permission checks */
-       if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
+       if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) ||
            ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
                return -EPERM;
 
@@ -3525,8 +3495,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                return set_geometry(cmd, &inparam.g, drive, type, bdev);
        case FDGETPRM:
                ret = get_floppy_geometry(drive, type,
-                                         (struct floppy_struct **)
-                                         &outparam);
+                                         (struct floppy_struct **)&outparam);
                if (ret)
                        return ret;
                break;
@@ -3561,20 +3530,20 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                UDP->max_errors.reporting = (unsigned short)(param & 0x0f);
                return 0;
        case FDGETMAXERRS:
-               outparam = (const char *)&UDP->max_errors;
+               outparam = &UDP->max_errors;
                break;
        case FDSETMAXERRS:
                UDP->max_errors = inparam.max_errors;
                break;
        case FDGETDRVTYP:
                outparam = drive_name(type, drive);
-               SUPBOUND(size, strlen(outparam) + 1);
+               SUPBOUND(size, strlen((const char *)outparam) + 1);
                break;
        case FDSETDRVPRM:
                *UDP = inparam.dp;
                break;
        case FDGETDRVPRM:
-               outparam = (const char *)UDP;
+               outparam = UDP;
                break;
        case FDPOLLDRVSTAT:
                if (lock_fdc(drive, true))
@@ -3584,18 +3553,18 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                process_fd_request();
                /* fall through */
        case FDGETDRVSTAT:
-               outparam = (const char *)UDRS;
+               outparam = UDRS;
                break;
        case FDRESET:
                return user_reset_fdc(drive, (int)param, true);
        case FDGETFDCSTAT:
-               outparam = (const char *)UFDCS;
+               outparam = UFDCS;
                break;
        case FDWERRORCLR:
                memset(UDRWE, 0, sizeof(*UDRWE));
                return 0;
        case FDWERRORGET:
-               outparam = (const char *)UDRWE;
+               outparam = UDRWE;
                break;
        case FDRAWCMD:
                if (type)
@@ -4254,7 +4223,7 @@ static int __init floppy_init(void)
                else
                        floppy_sizes[i] = MAX_DISK_SIZE << 1;
 
-       reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
+       reschedule_timeout(MAXTIMEOUT, "floppy init");
        config_types();
 
        for (i = 0; i < N_FDC; i++) {
@@ -4524,11 +4493,9 @@ cleanup:
 static void floppy_release_irq_and_dma(void)
 {
        int old_fdc;
-#ifdef FLOPPY_SANITY_CHECK
 #ifndef __sparc__
        int drive;
 #endif
-#endif
        long tmpsize;
        unsigned long tmpaddr;
        unsigned long flags;
@@ -4559,7 +4526,6 @@ static void floppy_release_irq_and_dma(void)
                buffer_min = buffer_max = -1;
                fd_dma_mem_free(tmpaddr, tmpsize);
        }
-#ifdef FLOPPY_SANITY_CHECK
 #ifndef __sparc__
        for (drive = 0; drive < N_FDC * 4; drive++)
                if (timer_pending(motor_off_timer + drive))
@@ -4572,7 +4538,6 @@ static void floppy_release_irq_and_dma(void)
                pr_info("auxiliary floppy timer still active\n");
        if (work_pending(&floppy_work))
                pr_info("work still pending\n");
-#endif
        old_fdc = fdc;
        for (fdc = 0; fdc < N_FDC; fdc++)
                if (FDCS->address != -1)