@@ -309,6 +309,25 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
bsg_job_fn *job_fn, int dd_job_size,
void (*release)(struct device *))
{
+ return bsg_setup_queue_ex(dev, name, job_fn, dd_job_size, release,
+ NULL);
+}
+EXPORT_SYMBOL_GPL(bsg_setup_queue);
+
+/**
+ * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
+ * @dev: device to attach bsg device to
+ * @name: device to give bsg device
+ * @job_fn: bsg job handler
+ * @dd_job_size: size of LLD data needed for each job
+ * @release: @dev release function
+ * @dev_module: @dev's module
+ */
+struct request_queue *bsg_setup_queue_ex(struct device *dev, const char *name,
+ bsg_job_fn *job_fn, int dd_job_size,
+ void (*release)(struct device *),
+ struct module *dev_module)
+{
struct request_queue *q;
int ret;
@@ -331,7 +350,8 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
blk_queue_softirq_done(q, bsg_softirq_done);
blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
- ret = bsg_register_queue(q, dev, name, &bsg_transport_ops, release);
+ ret = bsg_register_queue_ex(q, dev, name, &bsg_transport_ops, release,
+ dev_module);
if (ret) {
printk(KERN_ERR "%s: bsg interface failed to "
"initialize - register queue\n", dev->kobj.name);
@@ -343,4 +363,4 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
blk_cleanup_queue(q);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_GPL(bsg_setup_queue);
+EXPORT_SYMBOL_GPL(bsg_setup_queue_ex);
@@ -750,7 +750,8 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
return bd;
}
-static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
+static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file,
+ struct bsg_class_device **pbcd)
{
struct bsg_device *bd;
struct bsg_class_device *bcd;
@@ -766,6 +767,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
if (!bcd)
return ERR_PTR(-ENODEV);
+ *pbcd = bcd;
bd = __bsg_get_device(iminor(inode), bcd->queue);
if (bd)
@@ -781,22 +783,34 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
static int bsg_open(struct inode *inode, struct file *file)
{
struct bsg_device *bd;
+ struct bsg_class_device *bcd;
- bd = bsg_get_device(inode, file);
+ bd = bsg_get_device(inode, file, &bcd);
if (IS_ERR(bd))
return PTR_ERR(bd);
file->private_data = bd;
+ if (bcd->parent_module) {
+ if (!try_module_get(bcd->parent_module)) {
+ bsg_put_device(bd);
+ return -ENODEV;
+ }
+ }
return 0;
}
static int bsg_release(struct inode *inode, struct file *file)
{
+ int ret;
struct bsg_device *bd = file->private_data;
+ struct module *parent_module = bd->queue->bsg_dev.parent_module;
file->private_data = NULL;
- return bsg_put_device(bd);
+ ret = bsg_put_device(bd);
+ if (parent_module)
+ module_put(parent_module);
+ return ret;
}
static __poll_t bsg_poll(struct file *file, poll_table *wait)
@@ -922,6 +936,14 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
const char *name, const struct bsg_ops *ops,
void (*release)(struct device *))
{
+ return bsg_register_queue_ex(q, parent, name, ops, release, NULL);
+}
+
+int bsg_register_queue_ex(struct request_queue *q, struct device *parent,
+ const char *name, const struct bsg_ops *ops,
+ void (*release)(struct device *),
+ struct module *parent_module)
+{
struct bsg_class_device *bcd;
dev_t dev;
int ret;
@@ -958,6 +980,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
bcd->parent = get_device(parent);
bcd->release = release;
bcd->ops = ops;
+ bcd->parent_module = parent_module;
kref_init(&bcd->ref);
dev = MKDEV(bsg_major, bcd->minor);
class_dev = device_create(bsg_class, parent, dev, NULL, "%s", devname);
@@ -3772,17 +3772,21 @@ static int fc_bsg_dispatch(struct bsg_job *job)
struct fc_internal *i = to_fc_internal(shost->transportt);
struct request_queue *q;
char bsg_name[20];
+ struct module *shost_module = NULL;
fc_host->rqst_q = NULL;
if (!i->f->bsg_request)
return -ENOTSUPP;
+ if (shost->hostt)
+ shost_module = shost->hostt->module;
+
snprintf(bsg_name, sizeof(bsg_name),
"fc_host%d", shost->host_no);
- q = bsg_setup_queue(dev, bsg_name, fc_bsg_dispatch, i->f->dd_bsg_size,
- NULL);
+ q = bsg_setup_queue_ex(dev, bsg_name, fc_bsg_dispatch,
+ i->f->dd_bsg_size, NULL, shost_module);
if (IS_ERR(q)) {
dev_err(dev,
"fc_host%d: bsg interface failed to initialize - setup queue\n",
@@ -74,6 +74,10 @@ void bsg_job_done(struct bsg_job *job, int result,
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
bsg_job_fn *job_fn, int dd_job_size,
void (*release)(struct device *));
+struct request_queue *bsg_setup_queue_ex(struct device *dev, const char *name,
+ bsg_job_fn *job_fn, int dd_job_size,
+ void (*release)(struct device *),
+ struct module *dev_module);
void bsg_job_put(struct bsg_job *job);
int __must_check bsg_job_get(struct bsg_job *job);
@@ -23,11 +23,16 @@ struct bsg_class_device {
struct kref ref;
const struct bsg_ops *ops;
void (*release)(struct device *);
+ struct module *parent_module;
};
int bsg_register_queue(struct request_queue *q, struct device *parent,
const char *name, const struct bsg_ops *ops,
void (*release)(struct device *));
+int bsg_register_queue_ex(struct request_queue *q, struct device *parent,
+ const char *name, const struct bsg_ops *ops,
+ void (*release)(struct device *),
+ struct module *parent_module);
int bsg_scsi_register_queue(struct request_queue *q, struct device *parent);
void bsg_unregister_queue(struct request_queue *q);
#else