}
 
        default:
-               return scsi_ioctl(ch->device, cmd, argp);
+               return scsi_ioctl(ch->device, NULL, file->f_mode, cmd, argp);
 
        }
 }
 
 /**
  * scsi_ioctl - Dispatch ioctl to scsi device
  * @sdev: scsi device receiving ioctl
+ * @disk: disk receiving the ioctl
+ * @mode: mode the block/char device is opened with
  * @cmd: which ioctl is it
  * @arg: data associated with ioctl
  *
  * does not take a major/minor number as the dev field.  Rather, it takes
  * a pointer to a &struct scsi_device.
  */
-int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+               int cmd, void __user *arg)
 {
+       struct request_queue *q = sdev->request_queue;
        char scsi_cmd[MAX_COMMAND_SIZE];
        struct scsi_sense_hdr sense_hdr;
+       int error;
 
        /* Check for deprecated ioctls ... all the ioctls which don't
         * follow the new unique numbering scheme are deprecated */
                break;
        }
 
+       if (cmd != SCSI_IOCTL_GET_IDLUN && cmd != SCSI_IOCTL_GET_BUS_NUMBER) {
+               error = scsi_cmd_ioctl(q, disk, mode, cmd, arg);
+               if (error != -ENOTTY)
+                       return error;
+       }
+
        switch (cmd) {
        case SCSI_IOCTL_GET_IDLUN: {
                struct scsi_idlun v = {
                return put_user(sdev->host->host_no, (int __user *)arg);
        case SCSI_IOCTL_PROBE_HOST:
                return ioctl_probe(sdev->host, arg);
-       case SCSI_IOCTL_SEND_COMMAND:
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg);
        case SCSI_IOCTL_DOORLOCK:
                return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
        case SCSI_IOCTL_DOORUNLOCK:
 
 
        if (is_sed_ioctl(cmd))
                return sed_ioctl(sdkp->opal_dev, cmd, p);
-
-       /*
-        * Send SCSI addressing ioctls directly to mid level, send other
-        * ioctls to block level and then onto mid level if they can't be
-        * resolved.
-        */
-       switch (cmd) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
-       default:
-               error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
-               if (error != -ENOTTY)
-                       return error;
-       }
-
-       return scsi_ioctl(sdp, cmd, p);
+       return scsi_ioctl(sdp, disk, mode, cmd, p);
 }
 
 static void set_media_not_present(struct scsi_disk *sdkp)
 
        ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
        if (ret != -ENOIOCTLCMD)
                return ret;
-       return scsi_ioctl(sdp->device, cmd_in, p);
+       return scsi_ioctl(sdp->device, NULL, filp->f_mode, cmd_in, p);
 }
 
 static __poll_t
 
 
        scsi_autopm_get_device(sdev);
 
-       /*
-        * Send SCSI addressing ioctls directly to mid level, send other
-        * ioctls to cdrom/block level.
-        */
-       switch (cmd) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
-       default:
-               ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
-               if (ret != -ENOTTY)
-                       goto put;
+       if (ret != CDROMCLOSETRAY && ret != CDROMEJECT) {
                ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg);
                if (ret != -ENOSYS)
                        goto put;
        }
-
-       ret = scsi_ioctl(sdev, cmd, argp);
+       ret = scsi_ioctl(sdev, disk, mode, cmd, argp);
 
 put:
        scsi_autopm_put_device(sdev);
 
        mutex_unlock(&STp->lock);
 
        switch (cmd_in) {
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-               break;
        case SG_IO:
        case SCSI_IOCTL_SEND_COMMAND:
        case CDROM_SEND_PACKET:
                if (!capable(CAP_SYS_RAWIO))
                        return -EPERM;
-               fallthrough;
        default:
-               retval = scsi_cmd_ioctl(STp->disk->queue, STp->disk,
-                                       file->f_mode, cmd_in, p);
-               if (retval != -ENOTTY)
-                       return retval;
                break;
        }
 
-       retval = scsi_ioctl(STp->device, cmd_in, p);
+       retval = scsi_ioctl(STp->device, STp->disk, file->f_mode, cmd_in, p);
        if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
                /* unload */
                STp->rew_at_close = 0;
 
 
 #ifdef __KERNEL__
 
+struct gendisk;
 struct scsi_device;
 
 /*
 
 int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
                int cmd, bool ndelay);
-extern int scsi_ioctl(struct scsi_device *, int, void __user *);
+int scsi_ioctl(struct scsi_device *sdev, struct gendisk *disk, fmode_t mode,
+               int cmd, void __user *arg);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */