mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
scsi: bsg-lib: handle bidi requests without block layer help
We can just stash away the second request in struct bsg_job instead of using the block layer req->next_rq field, allowing for the eventual removal of the latter. Signed-off-by: Christoph Hellwig <[email protected]> Acked-by: Jens Axboe <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
This commit is contained in:
parent
ccf3209f00
commit
972248e911
4 changed files with 56 additions and 61 deletions
|
|
@ -51,11 +51,40 @@ static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
|
|||
fmode_t mode)
|
||||
{
|
||||
struct bsg_job *job = blk_mq_rq_to_pdu(rq);
|
||||
int ret;
|
||||
|
||||
job->request_len = hdr->request_len;
|
||||
job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
|
||||
if (IS_ERR(job->request))
|
||||
return PTR_ERR(job->request);
|
||||
|
||||
return PTR_ERR_OR_ZERO(job->request);
|
||||
if (hdr->dout_xfer_len && hdr->din_xfer_len) {
|
||||
job->bidi_rq = blk_get_request(rq->q, REQ_OP_SCSI_IN, 0);
|
||||
if (IS_ERR(job->bidi_rq)) {
|
||||
ret = PTR_ERR(job->bidi_rq);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
|
||||
uptr64(hdr->din_xferp), hdr->din_xfer_len,
|
||||
GFP_KERNEL);
|
||||
if (ret)
|
||||
goto out_free_bidi_rq;
|
||||
|
||||
job->bidi_bio = job->bidi_rq->bio;
|
||||
} else {
|
||||
job->bidi_rq = NULL;
|
||||
job->bidi_bio = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_bidi_rq:
|
||||
if (job->bidi_rq)
|
||||
blk_put_request(job->bidi_rq);
|
||||
out:
|
||||
kfree(job->request);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
|
||||
|
|
@ -93,7 +122,7 @@ static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
|
|||
/* we assume all request payload was transferred, residual == 0 */
|
||||
hdr->dout_resid = 0;
|
||||
|
||||
if (rq->next_rq) {
|
||||
if (job->bidi_rq) {
|
||||
unsigned int rsp_len = job->reply_payload.payload_len;
|
||||
|
||||
if (WARN_ON(job->reply_payload_rcv_len > rsp_len))
|
||||
|
|
@ -111,6 +140,11 @@ static void bsg_transport_free_rq(struct request *rq)
|
|||
{
|
||||
struct bsg_job *job = blk_mq_rq_to_pdu(rq);
|
||||
|
||||
if (job->bidi_rq) {
|
||||
blk_rq_unmap_user(job->bidi_bio);
|
||||
blk_put_request(job->bidi_rq);
|
||||
}
|
||||
|
||||
kfree(job->request);
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +234,6 @@ static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
|
|||
*/
|
||||
static bool bsg_prepare_job(struct device *dev, struct request *req)
|
||||
{
|
||||
struct request *rsp = req->next_rq;
|
||||
struct bsg_job *job = blk_mq_rq_to_pdu(req);
|
||||
int ret;
|
||||
|
||||
|
|
@ -211,8 +244,8 @@ static bool bsg_prepare_job(struct device *dev, struct request *req)
|
|||
if (ret)
|
||||
goto failjob_rls_job;
|
||||
}
|
||||
if (rsp && rsp->bio) {
|
||||
ret = bsg_map_buffer(&job->reply_payload, rsp);
|
||||
if (job->bidi_rq) {
|
||||
ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq);
|
||||
if (ret)
|
||||
goto failjob_rls_rqst_payload;
|
||||
}
|
||||
|
|
@ -369,7 +402,6 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
|
|||
}
|
||||
|
||||
q->queuedata = dev;
|
||||
blk_queue_flag_set(QUEUE_FLAG_BIDI, q);
|
||||
blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
|
||||
|
||||
ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);
|
||||
|
|
|
|||
Loading…
Reference in a new issue