blob: 882f56bff14f830234ee38d1ddfbe6aebf81ce91 [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 struct device device;
26 struct cdev cdev;
Jens Axboe3d6392c2007-07-09 12:38:05 +020027 int max_queue;
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +020028 unsigned int timeout;
29 unsigned int reserved_size;
Christoph Hellwig75ca5642021-07-29 08:48:45 +020030 bsg_sg_io_fn *sg_io_fn;
Jens Axboe3d6392c2007-07-09 12:38:05 +020031};
32
Christoph Hellwigead09dd2021-07-29 08:48:42 +020033static inline struct bsg_device *to_bsg_device(struct inode *inode)
34{
35 return container_of(inode->i_cdev, struct bsg_device, cdev);
36}
37
Jens Axboe5309cb32007-01-23 16:24:41 +010038#define BSG_DEFAULT_CMDS 64
FUJITA Tomonori292b7f22007-03-28 13:29:58 +020039#define BSG_MAX_DEVS 32768
Jens Axboe3d6392c2007-07-09 12:38:05 +020040
Christoph Hellwigead09dd2021-07-29 08:48:42 +020041static DEFINE_IDA(bsg_minor_ida);
Jens Axboe3d6392c2007-07-09 12:38:05 +020042static struct class *bsg_class;
Jens Axboe46f6ef42007-07-17 08:56:10 +020043static int bsg_major;
Jens Axboe3d6392c2007-07-09 12:38:05 +020044
Christoph Hellwig75ca5642021-07-29 08:48:45 +020045static unsigned int bsg_timeout(struct bsg_device *bd, struct sg_io_v4 *hdr)
46{
47 unsigned int timeout = BLK_DEFAULT_SG_TIMEOUT;
48
49 if (hdr->timeout)
50 timeout = msecs_to_jiffies(hdr->timeout);
51 else if (bd->timeout)
52 timeout = bd->timeout;
53
54 return max_t(unsigned int, timeout, BLK_MIN_SG_TIMEOUT);
55}
Christoph Hellwig82ed4db2017-01-27 09:46:29 +010056
Christoph Hellwigead09dd2021-07-29 08:48:42 +020057static int bsg_sg_io(struct bsg_device *bd, fmode_t mode, void __user *uarg)
Christoph Hellwig17cb9602018-03-13 17:28:41 +010058{
Christoph Hellwigccf32092018-11-09 20:12:25 +010059 struct sg_io_v4 hdr;
Christoph Hellwig17cb9602018-03-13 17:28:41 +010060 int ret;
61
Christoph Hellwigccf32092018-11-09 20:12:25 +010062 if (copy_from_user(&hdr, uarg, sizeof(hdr)))
63 return -EFAULT;
Christoph Hellwigccf32092018-11-09 20:12:25 +010064 if (hdr.guard != 'Q')
65 return -EINVAL;
Christoph Hellwig75ca5642021-07-29 08:48:45 +020066 ret = bd->sg_io_fn(bd->queue, &hdr, mode, bsg_timeout(bd, &hdr));
Christoph Hellwig972248e2019-01-29 09:32:03 +010067 if (!ret && copy_to_user(uarg, &hdr, sizeof(hdr)))
Christoph Hellwigccf32092018-11-09 20:12:25 +010068 return -EFAULT;
69 return ret;
FUJITA Tomonori70e36ec2006-12-20 11:20:15 +010070}
71
Jens Axboe3d6392c2007-07-09 12:38:05 +020072static int bsg_open(struct inode *inode, struct file *file)
73{
Christoph Hellwigead09dd2021-07-29 08:48:42 +020074 if (!blk_get_queue(to_bsg_device(inode)->queue))
75 return -ENXIO;
Jens Axboe3d6392c2007-07-09 12:38:05 +020076 return 0;
77}
78
79static int bsg_release(struct inode *inode, struct file *file)
80{
Christoph Hellwigead09dd2021-07-29 08:48:42 +020081 blk_put_queue(to_bsg_device(inode)->queue);
82 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +020083}
84
Christoph Hellwigccf32092018-11-09 20:12:25 +010085static int bsg_get_command_q(struct bsg_device *bd, int __user *uarg)
86{
Christoph Hellwigead09dd2021-07-29 08:48:42 +020087 return put_user(READ_ONCE(bd->max_queue), uarg);
Christoph Hellwigccf32092018-11-09 20:12:25 +010088}
89
90static int bsg_set_command_q(struct bsg_device *bd, int __user *uarg)
91{
Christoph Hellwigead09dd2021-07-29 08:48:42 +020092 int max_queue;
Christoph Hellwigccf32092018-11-09 20:12:25 +010093
Christoph Hellwigead09dd2021-07-29 08:48:42 +020094 if (get_user(max_queue, uarg))
Christoph Hellwigccf32092018-11-09 20:12:25 +010095 return -EFAULT;
Christoph Hellwigead09dd2021-07-29 08:48:42 +020096 if (max_queue < 1)
Christoph Hellwigccf32092018-11-09 20:12:25 +010097 return -EINVAL;
Christoph Hellwigead09dd2021-07-29 08:48:42 +020098 WRITE_ONCE(bd->max_queue, max_queue);
Christoph Hellwigccf32092018-11-09 20:12:25 +010099 return 0;
100}
101
Jens Axboe25fd1642007-07-17 08:52:29 +0200102static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200103{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200104 struct bsg_device *bd = to_bsg_device(file_inode(file));
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200105 struct request_queue *q = bd->queue;
Christoph Hellwigccf32092018-11-09 20:12:25 +0100106 void __user *uarg = (void __user *) arg;
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200107 int __user *intp = uarg;
108 int val;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200109
Jens Axboe3d6392c2007-07-09 12:38:05 +0200110 switch (cmd) {
Christoph Hellwigccf32092018-11-09 20:12:25 +0100111 /*
112 * Our own ioctls
113 */
Jens Axboe3d6392c2007-07-09 12:38:05 +0200114 case SG_GET_COMMAND_Q:
Christoph Hellwigccf32092018-11-09 20:12:25 +0100115 return bsg_get_command_q(bd, uarg);
116 case SG_SET_COMMAND_Q:
117 return bsg_set_command_q(bd, uarg);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200118
119 /*
120 * SCSI/sg ioctls
121 */
122 case SG_GET_VERSION_NUM:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200123 return put_user(30527, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200124 case SCSI_IOCTL_GET_IDLUN:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200125 return put_user(0, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200126 case SCSI_IOCTL_GET_BUS_NUMBER:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200127 return put_user(0, intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200128 case SG_SET_TIMEOUT:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200129 if (get_user(val, intp))
130 return -EFAULT;
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +0200131 bd->timeout = clock_t_to_jiffies(val);
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200132 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200133 case SG_GET_TIMEOUT:
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +0200134 return jiffies_to_clock_t(bd->timeout);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200135 case SG_GET_RESERVED_SIZE:
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +0200136 return put_user(min(bd->reserved_size, queue_max_bytes(q)),
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200137 intp);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200138 case SG_SET_RESERVED_SIZE:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200139 if (get_user(val, intp))
140 return -EFAULT;
141 if (val < 0)
142 return -EINVAL;
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +0200143 bd->reserved_size =
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200144 min_t(unsigned int, val, queue_max_bytes(q));
145 return 0;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200146 case SG_EMULATED_HOST:
Christoph Hellwigd52fe8f2021-07-24 09:20:22 +0200147 return put_user(1, intp);
Christoph Hellwigccf32092018-11-09 20:12:25 +0100148 case SG_IO:
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200149 return bsg_sg_io(bd, file->f_mode, uarg);
Christoph Hellwigbeec64d2021-07-24 09:20:10 +0200150 case SCSI_IOCTL_SEND_COMMAND:
151 pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
152 current->comm);
153 return -EINVAL;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200154 default:
Jens Axboe3d6392c2007-07-09 12:38:05 +0200155 return -ENOTTY;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200156 }
157}
158
Arjan van de Ven7344be02007-10-15 11:01:53 +0200159static const struct file_operations bsg_fops = {
Jens Axboe3d6392c2007-07-09 12:38:05 +0200160 .open = bsg_open,
161 .release = bsg_release,
Jens Axboe25fd1642007-07-17 08:52:29 +0200162 .unlocked_ioctl = bsg_ioctl,
Arnd Bergmannfe0da4e2019-03-15 17:13:06 +0100163 .compat_ioctl = compat_ptr_ioctl,
Jens Axboe3d6392c2007-07-09 12:38:05 +0200164 .owner = THIS_MODULE,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200165 .llseek = default_llseek,
Jens Axboe3d6392c2007-07-09 12:38:05 +0200166};
167
Zenghui Yu1a0db772021-09-11 18:53:06 +0800168static void bsg_device_release(struct device *dev)
169{
170 struct bsg_device *bd = container_of(dev, struct bsg_device, device);
171
172 ida_simple_remove(&bsg_minor_ida, MINOR(bd->device.devt));
173 kfree(bd);
174}
175
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200176void bsg_unregister_queue(struct bsg_device *bd)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200177{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200178 if (bd->queue->kobj.sd)
179 sysfs_remove_link(&bd->queue->kobj, "bsg");
180 cdev_device_del(&bd->cdev, &bd->device);
Zenghui Yu1a0db772021-09-11 18:53:06 +0800181 put_device(&bd->device);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200182}
FUJITA Tomonori4cf07232007-03-30 11:19:39 +0200183EXPORT_SYMBOL_GPL(bsg_unregister_queue);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200184
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200185struct bsg_device *bsg_register_queue(struct request_queue *q,
Christoph Hellwig75ca5642021-07-29 08:48:45 +0200186 struct device *parent, const char *name, bsg_sg_io_fn *sg_io_fn)
Jens Axboe3d6392c2007-07-09 12:38:05 +0200187{
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200188 struct bsg_device *bd;
Tejun Heobab998d2013-02-27 17:03:57 -0800189 int ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200190
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200191 bd = kzalloc(sizeof(*bd), GFP_KERNEL);
192 if (!bd)
193 return ERR_PTR(-ENOMEM);
194 bd->max_queue = BSG_DEFAULT_CMDS;
Christoph Hellwig1e61c1a2021-07-29 08:48:44 +0200195 bd->reserved_size = INT_MAX;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200196 bd->queue = q;
Christoph Hellwig75ca5642021-07-29 08:48:45 +0200197 bd->sg_io_fn = sg_io_fn;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200198
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200199 ret = ida_simple_get(&bsg_minor_ida, 0, BSG_MAX_DEVS, GFP_KERNEL);
Tejun Heobab998d2013-02-27 17:03:57 -0800200 if (ret < 0) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200201 if (ret == -ENOSPC)
202 dev_err(parent, "bsg: too many bsg devices\n");
Zenghui Yu1a0db772021-09-11 18:53:06 +0800203 kfree(bd);
204 return ERR_PTR(ret);
FUJITA Tomonori598443a2007-07-23 09:33:26 +0900205 }
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200206 bd->device.devt = MKDEV(bsg_major, ret);
207 bd->device.class = bsg_class;
208 bd->device.parent = parent;
Zenghui Yu1a0db772021-09-11 18:53:06 +0800209 bd->device.release = bsg_device_release;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200210 dev_set_name(&bd->device, "%s", name);
211 device_initialize(&bd->device);
FUJITA Tomonori598443a2007-07-23 09:33:26 +0900212
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200213 cdev_init(&bd->cdev, &bsg_fops);
214 bd->cdev.owner = THIS_MODULE;
215 ret = cdev_device_add(&bd->cdev, &bd->device);
216 if (ret)
Zenghui Yu1a0db772021-09-11 18:53:06 +0800217 goto out_put_device;
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200218
Linus Torvaldsabce8912007-07-16 11:18:23 -0700219 if (q->kobj.sd) {
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200220 ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200221 if (ret)
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200222 goto out_device_del;
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200223 }
224
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200225 return bd;
James Bottomley6826ee42007-07-20 16:50:10 -0500226
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200227out_device_del:
228 cdev_device_del(&bd->cdev, &bd->device);
Zenghui Yu1a0db772021-09-11 18:53:06 +0800229out_put_device:
230 put_device(&bd->device);
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200231 return ERR_PTR(ret);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200232}
Christoph Hellwig78011042021-07-24 09:20:23 +0200233EXPORT_SYMBOL_GPL(bsg_register_queue);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200234
Al Viro2c9ede52011-07-23 20:24:48 -0400235static char *bsg_devnode(struct device *dev, umode_t *mode)
Kay Sievers2bdf9142009-04-30 15:23:42 +0200236{
237 return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
238}
239
Jens Axboe3d6392c2007-07-09 12:38:05 +0200240static int __init bsg_init(void)
241{
Jens Axboe46f6ef42007-07-17 08:56:10 +0200242 dev_t devid;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200243 int ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200244
245 bsg_class = class_create(THIS_MODULE, "bsg");
Christoph Hellwig28519c82018-07-12 10:09:59 +0200246 if (IS_ERR(bsg_class))
247 return PTR_ERR(bsg_class);
Kay Sieverse454cea2009-09-18 23:01:12 +0200248 bsg_class->devnode = bsg_devnode;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200249
Jens Axboe46f6ef42007-07-17 08:56:10 +0200250 ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200251 if (ret)
252 goto destroy_bsg_class;
Jens Axboe46f6ef42007-07-17 08:56:10 +0200253 bsg_major = MAJOR(devid);
254
Jens Axboe5d3a8cd2007-07-17 15:10:09 +0200255 printk(KERN_INFO BSG_DESCRIPTION " version " BSG_VERSION
FUJITA Tomonori0ed081c2007-07-17 12:21:35 +0200256 " loaded (major %d)\n", bsg_major);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200257 return 0;
Christoph Hellwigead09dd2021-07-29 08:48:42 +0200258
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200259destroy_bsg_class:
260 class_destroy(bsg_class);
FUJITA Tomonori9b9f7702007-07-17 12:20:46 +0200261 return ret;
Jens Axboe3d6392c2007-07-09 12:38:05 +0200262}
263
264MODULE_AUTHOR("Jens Axboe");
FUJITA Tomonori0ed081c2007-07-17 12:21:35 +0200265MODULE_DESCRIPTION(BSG_DESCRIPTION);
Jens Axboe3d6392c2007-07-09 12:38:05 +0200266MODULE_LICENSE("GPL");
267
FUJITA Tomonori4e2872d2007-03-28 13:29:24 +0200268device_initcall(bsg_init);