drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / block / floppy.c
index 4807203..90c4038 100644 (file)
@@ -616,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);
@@ -1533,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();
@@ -1556,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;
@@ -1604,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)) {
@@ -1653,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
@@ -1673,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
@@ -1687,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
@@ -1777,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)
@@ -1789,7 +1789,7 @@ 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 %pf\n", cont->error);
@@ -2143,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)
 
@@ -2221,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 = {
@@ -2347,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;
@@ -2647,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);
@@ -2918,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;
 }
 
@@ -3126,6 +3125,7 @@ static inline int raw_cmd_copyout(int cmd, void __user *param,
                }
                ptr = ptr->next;
        }
+
        return 0;
 }
 
@@ -3156,18 +3156,19 @@ static inline int raw_cmd_copyin(int cmd, void __user *param,
        int i;
 
        *rcmd = NULL;
-       while (1) {
-               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)
+
+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
@@ -3176,34 +3177,35 @@ static inline int raw_cmd_copyin(int cmd, void __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)
@@ -3418,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;
@@ -3431,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
@@ -3452,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;
 
@@ -3495,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;
@@ -3531,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))
@@ -3554,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)