| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | * Changes: | 
|---|
| 3 | 4 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 08/23/2000 | 
|---|
| .. | .. | 
|---|
| 116 | 117 | case NOT_READY:	/* This happens if there is no disc in drive */ | 
|---|
| 117 | 118 | if (sdev->removable) | 
|---|
| 118 | 119 | break; | 
|---|
| 119 |  | -			/* FALLTHROUGH */ | 
|---|
|  | 120 | +			fallthrough; | 
|---|
| 120 | 121 | case UNIT_ATTENTION: | 
|---|
| 121 | 122 | if (sdev->removable) { | 
|---|
| 122 | 123 | sdev->changed = 1; | 
|---|
| 123 | 124 | result = 0;	/* This is no longer considered an error */ | 
|---|
| 124 | 125 | break; | 
|---|
| 125 | 126 | } | 
|---|
| 126 |  | -			/* FALLTHROUGH -- for non-removable media */ | 
|---|
|  | 127 | +			fallthrough;	/* for non-removable media */ | 
|---|
| 127 | 128 | default: | 
|---|
| 128 | 129 | sdev_printk(KERN_INFO, sdev, | 
|---|
| 129 | 130 | "ioctl_internal_command return code = %x\n", | 
|---|
| .. | .. | 
|---|
| 188 | 189 | } | 
|---|
| 189 | 190 |  | 
|---|
| 190 | 191 |  | 
|---|
| 191 |  | -/** | 
|---|
| 192 |  | - * scsi_ioctl - Dispatch ioctl to scsi device | 
|---|
| 193 |  | - * @sdev: scsi device receiving ioctl | 
|---|
| 194 |  | - * @cmd: which ioctl is it | 
|---|
| 195 |  | - * @arg: data associated with ioctl | 
|---|
| 196 |  | - * | 
|---|
| 197 |  | - * Description: The scsi_ioctl() function differs from most ioctls in that it | 
|---|
| 198 |  | - * does not take a major/minor number as the dev field.  Rather, it takes | 
|---|
| 199 |  | - * a pointer to a &struct scsi_device. | 
|---|
| 200 |  | - */ | 
|---|
| 201 |  | -int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 
|---|
|  | 192 | +static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg) | 
|---|
| 202 | 193 | { | 
|---|
| 203 | 194 | char scsi_cmd[MAX_COMMAND_SIZE]; | 
|---|
| 204 | 195 | struct scsi_sense_hdr sense_hdr; | 
|---|
| .. | .. | 
|---|
| 220 | 211 | } | 
|---|
| 221 | 212 |  | 
|---|
| 222 | 213 | switch (cmd) { | 
|---|
| 223 |  | -	case SCSI_IOCTL_GET_IDLUN: | 
|---|
| 224 |  | -		if (!access_ok(VERIFY_WRITE, arg, sizeof(struct scsi_idlun))) | 
|---|
|  | 214 | +	case SCSI_IOCTL_GET_IDLUN: { | 
|---|
|  | 215 | +		struct scsi_idlun v = { | 
|---|
|  | 216 | +			.dev_id = (sdev->id & 0xff) | 
|---|
|  | 217 | +				 + ((sdev->lun & 0xff) << 8) | 
|---|
|  | 218 | +				 + ((sdev->channel & 0xff) << 16) | 
|---|
|  | 219 | +				 + ((sdev->host->host_no & 0xff) << 24), | 
|---|
|  | 220 | +			.host_unique_id = sdev->host->unique_id | 
|---|
|  | 221 | +		}; | 
|---|
|  | 222 | +		if (copy_to_user(arg, &v, sizeof(struct scsi_idlun))) | 
|---|
| 225 | 223 | return -EFAULT; | 
|---|
| 226 |  | - | 
|---|
| 227 |  | -		__put_user((sdev->id & 0xff) | 
|---|
| 228 |  | -			 + ((sdev->lun & 0xff) << 8) | 
|---|
| 229 |  | -			 + ((sdev->channel & 0xff) << 16) | 
|---|
| 230 |  | -			 + ((sdev->host->host_no & 0xff) << 24), | 
|---|
| 231 |  | -			 &((struct scsi_idlun __user *)arg)->dev_id); | 
|---|
| 232 |  | -		__put_user(sdev->host->unique_id, | 
|---|
| 233 |  | -			 &((struct scsi_idlun __user *)arg)->host_unique_id); | 
|---|
| 234 | 224 | return 0; | 
|---|
|  | 225 | +	} | 
|---|
| 235 | 226 | case SCSI_IOCTL_GET_BUS_NUMBER: | 
|---|
| 236 | 227 | return put_user(sdev->host->host_no, (int __user *)arg); | 
|---|
| 237 | 228 | case SCSI_IOCTL_PROBE_HOST: | 
|---|
| .. | .. | 
|---|
| 265 | 256 | return scsi_ioctl_get_pci(sdev, arg); | 
|---|
| 266 | 257 | case SG_SCSI_RESET: | 
|---|
| 267 | 258 | return scsi_ioctl_reset(sdev, arg); | 
|---|
| 268 |  | -	default: | 
|---|
| 269 |  | -		if (sdev->host->hostt->ioctl) | 
|---|
| 270 |  | -			return sdev->host->hostt->ioctl(sdev, cmd, arg); | 
|---|
| 271 | 259 | } | 
|---|
|  | 260 | +	return -ENOIOCTLCMD; | 
|---|
|  | 261 | +} | 
|---|
|  | 262 | + | 
|---|
|  | 263 | +/** | 
|---|
|  | 264 | + * scsi_ioctl - Dispatch ioctl to scsi device | 
|---|
|  | 265 | + * @sdev: scsi device receiving ioctl | 
|---|
|  | 266 | + * @cmd: which ioctl is it | 
|---|
|  | 267 | + * @arg: data associated with ioctl | 
|---|
|  | 268 | + * | 
|---|
|  | 269 | + * Description: The scsi_ioctl() function differs from most ioctls in that it | 
|---|
|  | 270 | + * does not take a major/minor number as the dev field.  Rather, it takes | 
|---|
|  | 271 | + * a pointer to a &struct scsi_device. | 
|---|
|  | 272 | + */ | 
|---|
|  | 273 | +int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 
|---|
|  | 274 | +{ | 
|---|
|  | 275 | +	int ret = scsi_ioctl_common(sdev, cmd, arg); | 
|---|
|  | 276 | + | 
|---|
|  | 277 | +	if (ret != -ENOIOCTLCMD) | 
|---|
|  | 278 | +		return ret; | 
|---|
|  | 279 | + | 
|---|
|  | 280 | +	if (sdev->host->hostt->ioctl) | 
|---|
|  | 281 | +		return sdev->host->hostt->ioctl(sdev, cmd, arg); | 
|---|
|  | 282 | + | 
|---|
| 272 | 283 | return -EINVAL; | 
|---|
| 273 | 284 | } | 
|---|
| 274 | 285 | EXPORT_SYMBOL(scsi_ioctl); | 
|---|
| 275 | 286 |  | 
|---|
|  | 287 | +#ifdef CONFIG_COMPAT | 
|---|
|  | 288 | +int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 
|---|
|  | 289 | +{ | 
|---|
|  | 290 | +	int ret = scsi_ioctl_common(sdev, cmd, arg); | 
|---|
|  | 291 | + | 
|---|
|  | 292 | +	if (ret != -ENOIOCTLCMD) | 
|---|
|  | 293 | +		return ret; | 
|---|
|  | 294 | + | 
|---|
|  | 295 | +	if (sdev->host->hostt->compat_ioctl) | 
|---|
|  | 296 | +		return sdev->host->hostt->compat_ioctl(sdev, cmd, arg); | 
|---|
|  | 297 | + | 
|---|
|  | 298 | +	return ret; | 
|---|
|  | 299 | +} | 
|---|
|  | 300 | +EXPORT_SYMBOL(scsi_compat_ioctl); | 
|---|
|  | 301 | +#endif | 
|---|
|  | 302 | + | 
|---|
| 276 | 303 | /* | 
|---|
| 277 | 304 | * We can process a reset even when a device isn't fully operable. | 
|---|
| 278 | 305 | */ | 
|---|