blob: 83a095185d330fbf1469c5df9683086beb928d9f [file] [log] [blame]
Christoph Hellwig8c165672019-04-30 14:42:39 -04001// SPDX-License-Identifier: GPL-2.0
Jens Axboe3d6392c2007-07-09 12:38:05 +02002/*
FUJITA Tomonori0c6a89b2007-07-29 23:00:46 +09003 * bsg.c - block layer implementation of the sg v4 interface
Jens Axboe3d6392c2007-07-09 12:38:05 +02004 */
Jens Axboe3d6392c2007-07-09 12:38:05 +02005#include <linux/module.h>
6#include <linux/init.h>
7#include <linux/file.h>
8#include <linux/blkdev.h>
Jens Axboe3d6392c2007-07-09 12:38:05 +02009#include <linux/cdev.h>
Randy Dunlapad5ebd22009-11-11 13:47:45 +010010#include <linux/jiffies.h>
Jens Axboe3d6392c2007-07-09 12:38:05 +020011#include <linux/percpu.h>
FUJITA Tomonori598443a2007-07-23 09:33:26 +090012#include <linux/idr.h>
Jens Axboe3d6392c2007-07-09 12:38:05 +020013#include <linux/bsg.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090014#include <linux/slab.h>
Jens Axboe3d6392c2007-07-09 12:38:05 +020015
16#include <scsi/scsi.h>
17#include <scsi/scsi_ioctl.h>
Jens Axboe3d6392c2007-07-09 12:38:05 +020018#include <scsi/sg.h>
19
FUJITA Tomonori0ed081c2007-07-17 12:21:35 +020020#define BSG_DESCRIPTION "Block layer SCSI generic (bsg) driver"
21#define BSG_VERSION "0.4"
Jens Axboe3d6392c2007-07-09 12:38:05 +020022
Jens Axboe3d6392c2007-07-09 12:38:05 +020023struct bsg_device {
Jens Axboe165125e2007-07-24 09:28:11 +020024 struct request_queue *queue;
Christoph Hellwigead09dd2021-07-29 08:48:42 +020025 const struct bsg_ops *ops;
26 struct device device;
27 struct cdev cdev;
Jens Axboe3d6392c2007-07-09 12:38:05 +020028 int max_queue;
Jens Axboe3d6392c2007-07-09 12:38:05 +020029};
30
Christoph Hellwigead09dd2021-07-29 08:48:42 +020031static inline struct bsg_device *to_bsg_device(struct inode *inode)
32{
33 return container_of(inode->i_cdev, struct bsg_device, cdev);
34}
35
Jens Axboe5309cb32007-01-23 16:24:41 +010036#define BSG_DEFAULT_CMDS 64
FUJITA Tomonori292b7f22007-03-28 13:29:58 +020037#define BSG_MAX_DEVS 32768
Jens Axboe3d6392c2007-07-09 12:38:05 +020038
Christoph Hellwigead09dd2021-07-29 08:48:42 +020039static DEFINE_IDA(bsg_minor_ida);
Jens Axboe3d6392c2007-07-09 12:38:05 +020040static struct class *bsg_class;
Jens Axboe46f6ef42007-07-17 08:56:10 +020041static int bsg_major;
Jens Axboe3d6392c2007-07-09 12:38:05 +020042
Christoph Hellwig17cb9602018-03-13 17:28:41 +010043#define uptr64(val) ((void __user *)(uintptr_t)(val))
Christoph Hellwig82ed4db2017-01-27 09:46:29 +010044
Christoph Hellwigead09dd2021-07-29 08:48:42 +020045static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg)
Christoph Hellwig17cb9602018-03-13 17:28:41 +010046{
Christoph Hellwig972248e2019-01-29 09:32:03 +010047 struct request *rq;
48 struct bio *bio;
Christoph Hellwigccf32092018-11-09 20:12:25 +010049 struct sg_io_v4 hdr;
Christoph Hellwig17cb9602018-03-13 17:28:41 +010050 int ret;
51
Christoph Hellwigccf32092018-11-09 20:12:25 +010052 if (copy_from_user(&hdr, uarg, sizeof(hdr)))
53 return -EFAULT;
54
Christoph Hellwigccf32092018-11-09 20:12:25 +010055 if (hdr.guard != 'Q')
56 return -EINVAL;
Christoph Hellwigead09dd2021-07-29 08:48:42 +020057 ret = bd->ops->check_proto(&hdr);
Christoph Hellwig17cb9602018-03-13 17:28:41 +010058 if (ret)
Christoph Hellwigccf32092018-11-09 20:12:25 +010059 return ret;
Christoph Hellwig17cb9602018-03-13 17:28:41 +010060
Christoph Hellwigead09dd2021-07-29 08:48:42 +020061 rq = blk_get_request(bd->queue, hdr.dout_xfer_len ?
Christoph Hellwigda6269d2021-06-24 14:39:34 +020062 REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
Christoph Hellwig17cb9602018-03-13 17:28:41 +010063 if (IS_ERR(rq))
Christoph Hellwigccf32092018-11-09 20:12:25 +010064 return PTR_ERR(rq);
Christoph Hellwig17cb9602018-03-13 17:28:41 +010065
Christoph Hellwigead09dd2021-07-29 08:48:42 +020066 ret = bd->ops->fill_hdr(rq, &hdr, mode);
Pan Bian0f7b4bc2021-01-19 04:33:11 -080067 if (ret) {
68 blk_put_request(rq);
Christoph Hellwig972248e2019-01-29 09:32:03 +010069 return ret;
Pan Bian0f7b4bc2021-01-19 04:33:11 -080070 }
Jens Axboe3d6392c2007-07-09 12:38:05 +020071
Christoph Hellwigccf32092018-11-09 20:12:25 +010072 rq->timeout = msecs_to_jiffies(hdr.timeout);
FUJITA Tomonori70e36ec2006-12-20 11:20:15 +010073 if (!rq->timeout)
Christoph Hellwigead09dd2021-07-29 08:48:42 +020074 rq->timeout = rq->q->sg_timeout;
FUJITA Tomonori70e36ec2006-12-20 11:20:15 +010075 if (!rq->timeout)
76 rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
Linus Torvaldsf2f1fa72008-12-05 14:49:18 -080077 if (rq->timeout < BLK_MIN_SG_TIMEOUT)
78 rq->timeout = BLK_MIN_SG_TIMEOUT;
Jens Axboe3d6392c2007-07-09 12:38:05 +020079
Christoph Hellwigccf32092018-11-09 20:12:25 +010080 if (hdr.dout_xfer_len) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +020081 ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr.dout_xferp),
Christoph Hellwigccf32092018-11-09 20:12:25 +010082 hdr.dout_xfer_len, GFP_KERNEL);
83 } else if (hdr.din_xfer_len) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +020084 ret = blk_rq_map_user(rq->q, rq, NULL, uptr64(hdr.din_xferp),
Christoph Hellwigccf32092018-11-09 20:12:25 +010085 hdr.din_xfer_len, GFP_KERNEL);
Jens Axboe3d6392c2007-07-09 12:38:05 +020086 }
Boaz Harroshc1c20122009-02-03 07:47:29 +010087
Christoph Hellwig17cb9602018-03-13 17:28:41 +010088 if (ret)
Christoph Hellwig972248e2019-01-29 09:32:03 +010089 goto out_free_rq;
Christoph Hellwigccf32092018-11-09 20:12:25 +010090
91 bio = rq->bio;
Christoph Hellwigccf32092018-11-09 20:12:25 +010092
Guoqing Jiang684da762021-01-25 05:49:58 +010093 blk_execute_rq(NULL, rq, !(hdr.flags & BSG_FLAG_Q_AT_TAIL));
Christoph Hellwigead09dd2021-07-29 08:48:42 +020094 ret = bd->ops->complete_rq(rq, &hdr);
Christoph Hellwigccf32092018-11-09 20:12:25 +010095 blk_rq_unmap_user(bio);
Christoph Hellwig972248e2019-01-29 09:32:03 +010096
97out_free_rq:
Christoph Hellwigead09dd2021-07-29 08:48:42 +020098 bd->ops->free_rq(rq);
Christoph Hellwigccf32092018-11-09 20:12:25 +010099 blk_put_request(rq);
Christoph Hellwig972248e2019-01-29 09:32:03 +0100100 if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
Christoph Hellwigccf32092018-11-09 20:12:25 +0100101 return -EFAULT;
102 return ret;
FUJITA Tomonori70e36ec2006-12-20 11:20:15 +0100103}
104
Jens Axboe3d6392c2007-07-09 12:38:05 +0200105static int bsg_open(struct inode *inode, struct file *file)
106{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200107 if (!blk_get_queue(to_bsg_device(inode)->queue))
108 return -ENXIO;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200109 return 0;
110}
111
112static int bsg_release(struct inode *inode, struct file *file)
113{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200114 blk_put_queue(to_bsg_device(inode)->queue);
115 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200116}
117
Christoph Hellwigccf32092018-11-09 20:12:25 +0100118static int bsg_get_command_q(struct bsg_device *bd, int __user *uarg)
119{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200120 return put_user(READ_ONCE(bd->max_queue), uarg);
Christoph Hellwigccf32092018-11-09 20:12:25 +0100121}
122
123static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
124{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200125 int max_queue;
Christoph Hellwigccf32092018-11-09 20:12:25 +0100126
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200127 if (get_user(max_queue, uarg))
Christoph Hellwigccf32092018-11-09 20:12:25 +0100128 return -EFAULT;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200129 if (max_queue < 1)
Christoph Hellwigccf32092018-11-09 20:12:25 +0100130 return -EINVAL;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200131 WRITE_ONCE(bd->max_queue, max_queue);
Christoph Hellwigccf32092018-11-09 20:12:25 +0100132 return 0;
133}
134
Jens Axboe25fd1642007-07-17 08:52:29 +0200135static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200136{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200137 struct bsg_device *bd = to_bsg_device(file_inode(file));
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200138 struct request_queue *q = bd->queue;
Christoph Hellwigccf32092018-11-09 20:12:25 +0100139 void __user *uarg = (void __user *) arg;
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200140 int __user *intp = uarg;
141 int val;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200142
Jens Axboe3d6392c2007-07-09 12:38:05 +0200143 switch (cmd) {
Christoph Hellwigccf32092018-11-09 20:12:25 +0100144 /*
145 * Our own ioctls
146 */
Jens Axboe3d6392c2007-07-09 12:38:05 +0200147 case SG_GET_COMMAND_Q:
Christoph Hellwigccf32092018-11-09 20:12:25 +0100148 return bsg_get_command_q(bd, uarg);
149 case SG_SET_COMMAND_Q:
150 return bsg_set_command_q(bd, uarg);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200151
152 /*
153 * SCSI/sg ioctls
154 */
155 case SG_GET_VERSION_NUM:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200156 return put_user(30527, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200157 case SCSI_IOCTL_GET_IDLUN:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200158 return put_user(0, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200159 case SCSI_IOCTL_GET_BUS_NUMBER:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200160 return put_user(0, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200161 case SG_SET_TIMEOUT:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200162 if (get_user(val, intp))
163 return -EFAULT;
164 q->sg_timeout = clock_t_to_jiffies(val);
165 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200166 case SG_GET_TIMEOUT:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200167 return jiffies_to_clock_t(q->sg_timeout);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200168 case SG_GET_RESERVED_SIZE:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200169 return put_user(min(q->sg_reserved_size, queue_max_bytes(q)),
170 intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200171 case SG_SET_RESERVED_SIZE:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200172 if (get_user(val, intp))
173 return -EFAULT;
174 if (val < 0)
175 return -EINVAL;
176 q->sg_reserved_size =
177 min_t(unsigned int, val, queue_max_bytes(q));
178 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200179 case SG_EMULATED_HOST:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200180 return put_user(1, intp);
Christoph Hellwigccf32092018-11-09 20:12:25 +0100181 case SG_IO:
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200182 return bsg_sg_io(bd, file->f_mode, uarg);
Christoph Hellwigbeec64d2021-07-24 09:20:10 +0200183 case SCSI_IOCTL_SEND_COMMAND:
184 pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
185 current->comm);
186 return -EINVAL;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200187 default:
Jens Axboe3d6392c2007-07-09 12:38:05 +0200188 return -ENOTTY;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200189 }
190}
191
Arjan van de Ven7344be02007-10-15 11:01:53 +0200192static const struct file_operations bsg_fops = {
Jens Axboe3d6392c2007-07-09 12:38:05 +0200193 .open = bsg_open,
194 .release = bsg_release,
Jens Axboe25fd1642007-07-17 08:52:29 +0200195 .unlocked_ioctl = bsg_ioctl,
Arnd Bergmannfe0da4e2019-03-15 17:13:06 +0100196 .compat_ioctl = compat_ptr_ioctl,
Jens Axboe3d6392c2007-07-09 12:38:05 +0200197 .owner = THIS_MODULE,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200198 .llseek = default_llseek,
Jens Axboe3d6392c2007-07-09 12:38:05 +0200199};
200
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200201void bsg_unregister_queue(struct bsg_device *bd)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200202{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200203 if (bd->queue->kobj.sd)
204 sysfs_remove_link(&bd->queue->kobj, "bsg");
205 cdev_device_del(&bd->cdev, &bd->device);
206 ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
207 kfree(bd);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200208}
FUJITA Tomonori4cf07232007-03-30 11:19:39 +0200209EXPORT_SYMBOL_GPL(bsg_unregister_queue);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200210
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200211struct bsg_device *bsg_register_queue(struct request_queue *q,
212 struct device *parent, const char *name,
213 const struct bsg_ops *ops)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200214{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200215 struct bsg_device *bd;
Tejun Heobab998d2013-02-27 17:03:57 -0800216 int ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200217
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200218 bd = kzalloc(sizeof(*bd), GFP_KERNEL);
219 if (!bd)
220 return ERR_PTR(-ENOMEM);
221 bd->max_queue = BSG_DEFAULT_CMDS;
222 bd->queue = q;
223 bd->ops = ops;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200224
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200225 ret = ida_simple_get(&bsg_minor_ida, 0, BSG_MAX_DEVS, GFP_KERNEL);
Tejun Heobab998d2013-02-27 17:03:57 -0800226 if (ret < 0) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200227 if (ret == -ENOSPC)
228 dev_err(parent, "bsg: too many bsg devices\n");
229 goto out_kfree;
FUJITA Tomonori598443a2007-07-23 09:33:26 +0900230 }
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200231 bd->device.devt = MKDEV(bsg_major, ret);
232 bd->device.class = bsg_class;
233 bd->device.parent = parent;
234 dev_set_name(&bd->device, "%s", name);
235 device_initialize(&bd->device);
FUJITA Tomonori598443a2007-07-23 09:33:26 +0900236
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200237 cdev_init(&bd->cdev, &bsg_fops);
238 bd->cdev.owner = THIS_MODULE;
239 ret = cdev_device_add(&bd->cdev, &bd->device);
240 if (ret)
241 goto out_ida_remove;
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200242
Linus Torvaldsabce8912007-07-16 11:18:23 -0700243 if (q->kobj.sd) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200244 ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200245 if (ret)
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200246 goto out_device_del;
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200247 }
248
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200249 return bd;
James Bottomley6826ee42007-07-20 16:50:10 -0500250
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200251out_device_del:
252 cdev_device_del(&bd->cdev, &bd->device);
253out_ida_remove:
254 ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
255out_kfree:
256 kfree(bd);
257 return ERR_PTR(ret);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200258}
Christoph Hellwig78011042021-07-24 09:20:23 +0200259EXPORT_SYMBOL_GPL(bsg_register_queue);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200260
Al Viro2c9ede52011-07-23 20:24:48 -0400261static char *bsg_devnode(struct device *dev, umode_t *mode)
Kay Sievers2bdf9142009-04-30 15:23:42 +0200262{
263 return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
264}
265
Jens Axboe3d6392c2007-07-09 12:38:05 +0200266static int __init bsg_init(void)
267{
Jens Axboe46f6ef42007-07-17 08:56:10 +0200268 dev_t devid;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200269 int ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200270
271 bsg_class = class_create(THIS_MODULE, "bsg");
Christoph Hellwig28519c82018-07-12 10:09:59 +0200272 if (IS_ERR(bsg_class))
273 return PTR_ERR(bsg_class);
Kay Sieverse454cea2009-09-18 23:01:12 +0200274 bsg_class->devnode = bsg_devnode;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200275
Jens Axboe46f6ef42007-07-17 08:56:10 +0200276 ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200277 if (ret)
278 goto destroy_bsg_class;
Jens Axboe46f6ef42007-07-17 08:56:10 +0200279 bsg_major = MAJOR(devid);
280
Jens Axboe5d3a8cd2007-07-17 15:10:09 +0200281 printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
FUJITA Tomonori0ed081c2007-07-17 12:21:35 +0200282 " loaded (major %d)\n", bsg_major);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200283 return 0;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200284
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200285destroy_bsg_class:
286 class_destroy(bsg_class);
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200287 return ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200288}
289
290MODULE_AUTHOR("Jens Axboe");
FUJITA Tomonori0ed081c2007-07-17 12:21:35 +0200291MODULE_DESCRIPTION(BSG_DESCRIPTION);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200292MODULE_LICENSE("GPL");
293
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200294device_initcall(bsg_init);