blk_rq_unmap_user(bio);
out_unmap_bidi_rq: if (job->bidi_rq)
blk_rq_unmap_user(job->bidi_bio);
out_free_bidi_rq: if (job->bidi_rq)
blk_mq_free_request(job->bidi_rq);
out_free_job_request:
kfree(job->request);
out_free_rq:
blk_mq_free_request(rq); return ret;
}
/** * bsg_teardown_job - routine to teardown a bsg job * @kref: kref inside bsg_job that is to be torn down
*/ staticvoid bsg_teardown_job(struct kref *kref)
{ struct bsg_job *job = container_of(kref, struct bsg_job, kref); struct request *rq = blk_mq_rq_from_pdu(job);
put_device(job->dev); /* release reference for the request */
int bsg_job_get(struct bsg_job *job)
{ return kref_get_unless_zero(&job->kref);
}
EXPORT_SYMBOL_GPL(bsg_job_get);
/** * bsg_job_done - completion routine for bsg requests * @job: bsg_job that is complete * @result: job reply result * @reply_payload_rcv_len: length of payload recvd * * The LLD should call this when the bsg job has completed.
*/ void bsg_job_done(struct bsg_job *job, int result, unsignedint reply_payload_rcv_len)
{ struct request *rq = blk_mq_rq_from_pdu(job);
/** * 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
*/ staticbool bsg_prepare_job(struct device *dev, struct request *req)
{ struct bsg_job *job = blk_mq_rq_to_pdu(req); int ret;
job->timeout = req->timeout;
if (req->bio) {
ret = bsg_map_buffer(&job->request_payload, req); if (ret) goto failjob_rls_job;
} if (job->bidi_rq) {
ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq); if (ret) goto failjob_rls_rqst_payload;
}
job->dev = dev; /* take a reference for the request */
get_device(job->dev);
kref_init(&job->kref); returntrue;
/** * bsg_queue_rq - generic handler for bsg requests * @hctx: hardware queue * @bd: queue data * * On error the create_bsg_job function should return a -Exyz error value * that will be set to ->result. * * Drivers/subsys should pass this to the queue init function.
*/ static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx, conststruct blk_mq_queue_data *bd)
{ struct request_queue *q = hctx->queue; struct device *dev = q->queuedata; struct request *req = bd->rq; struct bsg_set *bset =
container_of(q->tag_set, struct bsg_set, tag_set);
blk_status_t sts = BLK_STS_IOERR; int ret;
blk_mq_start_request(req);
if (!get_device(dev)) return BLK_STS_IOERR;
if (!bsg_prepare_job(dev, req)) goto out;
ret = bset->job_fn(blk_mq_rq_to_pdu(req)); if (!ret)
sts = BLK_STS_OK;
out:
put_device(dev); return sts;
}
/* called right after the request is allocated for the request_queue */ staticint bsg_init_rq(struct blk_mq_tag_set *set, struct request *req, unsignedint hctx_idx, unsignedint numa_node)
{ struct bsg_job *job = blk_mq_rq_to_pdu(req);
/** * 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 * @lim: queue limits for the bsg queue * @job_fn: bsg job handler * @timeout: timeout handler function pointer * @dd_job_size: size of LLD data needed for each job
*/ struct request_queue *bsg_setup_queue(struct device *dev, constchar *name, struct queue_limits *lim, bsg_job_fn *job_fn,
bsg_timeout_fn *timeout, int dd_job_size)
{ struct bsg_set *bset; struct blk_mq_tag_set *set; struct request_queue *q; int ret = -ENOMEM;
bset = kzalloc(sizeof(*bset), GFP_KERNEL); if (!bset) return ERR_PTR(-ENOMEM);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.