|
@@ -29,26 +29,25 @@
|
|
|
#include <scsi/scsi_cmnd.h>
|
|
|
|
|
|
/**
|
|
|
- * bsg_destroy_job - routine to teardown/delete a bsg job
|
|
|
+ * bsg_teardown_job - routine to teardown a bsg job
|
|
|
* @job: bsg_job that is to be torn down
|
|
|
*/
|
|
|
-static void bsg_destroy_job(struct kref *kref)
|
|
|
+static void bsg_teardown_job(struct kref *kref)
|
|
|
{
|
|
|
struct bsg_job *job = container_of(kref, struct bsg_job, kref);
|
|
|
struct request *rq = job->req;
|
|
|
|
|
|
- blk_end_request_all(rq, BLK_STS_OK);
|
|
|
-
|
|
|
put_device(job->dev); /* release reference for the request */
|
|
|
|
|
|
kfree(job->request_payload.sg_list);
|
|
|
kfree(job->reply_payload.sg_list);
|
|
|
- kfree(job);
|
|
|
+
|
|
|
+ blk_end_request_all(rq, BLK_STS_OK);
|
|
|
}
|
|
|
|
|
|
void bsg_job_put(struct bsg_job *job)
|
|
|
{
|
|
|
- kref_put(&job->kref, bsg_destroy_job);
|
|
|
+ kref_put(&job->kref, bsg_teardown_job);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(bsg_job_put);
|
|
|
|
|
@@ -100,7 +99,7 @@ EXPORT_SYMBOL_GPL(bsg_job_done);
|
|
|
*/
|
|
|
static void bsg_softirq_done(struct request *rq)
|
|
|
{
|
|
|
- struct bsg_job *job = rq->special;
|
|
|
+ struct bsg_job *job = blk_mq_rq_to_pdu(rq);
|
|
|
|
|
|
bsg_job_put(job);
|
|
|
}
|
|
@@ -122,33 +121,20 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * bsg_create_job - create the bsg_job structure for the bsg request
|
|
|
+ * bsg_prepare_job - create the bsg_job structure for the bsg request
|
|
|
* @dev: device that is being sent the bsg request
|
|
|
* @req: BSG request that needs a job structure
|
|
|
*/
|
|
|
-static int bsg_create_job(struct device *dev, struct request *req)
|
|
|
+static int bsg_prepare_job(struct device *dev, struct request *req)
|
|
|
{
|
|
|
struct request *rsp = req->next_rq;
|
|
|
- struct request_queue *q = req->q;
|
|
|
struct scsi_request *rq = scsi_req(req);
|
|
|
- struct bsg_job *job;
|
|
|
+ struct bsg_job *job = blk_mq_rq_to_pdu(req);
|
|
|
int ret;
|
|
|
|
|
|
- BUG_ON(req->special);
|
|
|
-
|
|
|
- job = kzalloc(sizeof(struct bsg_job) + q->bsg_job_size, GFP_KERNEL);
|
|
|
- if (!job)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- req->special = job;
|
|
|
- job->req = req;
|
|
|
- if (q->bsg_job_size)
|
|
|
- job->dd_data = (void *)&job[1];
|
|
|
job->request = rq->cmd;
|
|
|
job->request_len = rq->cmd_len;
|
|
|
- job->reply = rq->sense;
|
|
|
- job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer
|
|
|
- * allocated */
|
|
|
+
|
|
|
if (req->bio) {
|
|
|
ret = bsg_map_buffer(&job->request_payload, req);
|
|
|
if (ret)
|
|
@@ -187,7 +173,6 @@ static void bsg_request_fn(struct request_queue *q)
|
|
|
{
|
|
|
struct device *dev = q->queuedata;
|
|
|
struct request *req;
|
|
|
- struct bsg_job *job;
|
|
|
int ret;
|
|
|
|
|
|
if (!get_device(dev))
|
|
@@ -199,7 +184,7 @@ static void bsg_request_fn(struct request_queue *q)
|
|
|
break;
|
|
|
spin_unlock_irq(q->queue_lock);
|
|
|
|
|
|
- ret = bsg_create_job(dev, req);
|
|
|
+ ret = bsg_prepare_job(dev, req);
|
|
|
if (ret) {
|
|
|
scsi_req(req)->result = ret;
|
|
|
blk_end_request_all(req, BLK_STS_OK);
|
|
@@ -207,8 +192,7 @@ static void bsg_request_fn(struct request_queue *q)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- job = req->special;
|
|
|
- ret = q->bsg_job_fn(job);
|
|
|
+ ret = q->bsg_job_fn(blk_mq_rq_to_pdu(req));
|
|
|
spin_lock_irq(q->queue_lock);
|
|
|
if (ret)
|
|
|
break;
|
|
@@ -219,6 +203,35 @@ static void bsg_request_fn(struct request_queue *q)
|
|
|
spin_lock_irq(q->queue_lock);
|
|
|
}
|
|
|
|
|
|
+static int bsg_init_rq(struct request_queue *q, struct request *req, gfp_t gfp)
|
|
|
+{
|
|
|
+ struct bsg_job *job = blk_mq_rq_to_pdu(req);
|
|
|
+ struct scsi_request *sreq = &job->sreq;
|
|
|
+
|
|
|
+ memset(job, 0, sizeof(*job));
|
|
|
+
|
|
|
+ scsi_req_init(sreq);
|
|
|
+ sreq->sense_len = SCSI_SENSE_BUFFERSIZE;
|
|
|
+ sreq->sense = kzalloc(sreq->sense_len, gfp);
|
|
|
+ if (!sreq->sense)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ job->req = req;
|
|
|
+ job->reply = sreq->sense;
|
|
|
+ job->reply_len = sreq->sense_len;
|
|
|
+ job->dd_data = job + 1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void bsg_exit_rq(struct request_queue *q, struct request *req)
|
|
|
+{
|
|
|
+ struct bsg_job *job = blk_mq_rq_to_pdu(req);
|
|
|
+ struct scsi_request *sreq = &job->sreq;
|
|
|
+
|
|
|
+ kfree(sreq->sense);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* bsg_setup_queue - Create and add the bsg hooks so we can receive requests
|
|
|
* @dev: device to attach bsg device to
|
|
@@ -235,7 +248,9 @@ struct request_queue *bsg_setup_queue(struct device *dev, char *name,
|
|
|
q = blk_alloc_queue(GFP_KERNEL);
|
|
|
if (!q)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
- q->cmd_size = sizeof(struct scsi_request);
|
|
|
+ q->cmd_size = sizeof(struct bsg_job) + dd_job_size;
|
|
|
+ q->init_rq_fn = bsg_init_rq;
|
|
|
+ q->exit_rq_fn = bsg_exit_rq;
|
|
|
q->request_fn = bsg_request_fn;
|
|
|
|
|
|
ret = blk_init_allocated_queue(q);
|
|
@@ -243,7 +258,6 @@ struct request_queue *bsg_setup_queue(struct device *dev, char *name,
|
|
|
goto out_cleanup_queue;
|
|
|
|
|
|
q->queuedata = dev;
|
|
|
- q->bsg_job_size = dd_job_size;
|
|
|
q->bsg_job_fn = job_fn;
|
|
|
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
|
|
|
queue_flag_set_unlocked(QUEUE_FLAG_SCSI_PASSTHROUGH, q);
|