linux/block/bsg-lib.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  BSG helper library
   4 *
   5 *  Copyright (C) 2008   James Smart, Emulex Corporation
   6 *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
   7 *  Copyright (C) 2011   Mike Christie
   8 */
   9#include <linux/slab.h>
  10#include <linux/blk-mq.h>
  11#include <linux/delay.h>
  12#include <linux/scatterlist.h>
  13#include <linux/bsg-lib.h>
  14#include <linux/export.h>
  15#include <scsi/scsi_cmnd.h>
  16#include <scsi/sg.h>
  17
  18#define uptr64(val) ((void __user *)(uintptr_t)(val))
  19
  20struct bsg_set {
  21        struct blk_mq_tag_set   tag_set;
  22        bsg_job_fn              *job_fn;
  23        bsg_timeout_fn          *timeout_fn;
  24};
  25
  26static int bsg_transport_check_proto(struct sg_io_v4 *hdr)
  27{
  28        if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
  29            hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT)
  30                return -EINVAL;
  31        if (!capable(CAP_SYS_RAWIO))
  32                return -EPERM;
  33        return 0;
  34}
  35
  36static int bsg_transport_fill_hdr(struct request *rq, struct sg_io_v4 *hdr,
  37                fmode_t mode)
  38{
  39        struct bsg_job *job = blk_mq_rq_to_pdu(rq);
  40        int ret;
  41
  42        job->request_len = hdr->request_len;
  43        job->request = memdup_user(uptr64(hdr->request), hdr->request_len);
  44        if (IS_ERR(job->request))
  45                return PTR_ERR(job->request);
  46
  47        if (hdr->dout_xfer_len && hdr->din_xfer_len) {
  48                job->bidi_rq = blk_get_request(rq->q, REQ_OP_DRV_IN, 0);
  49                if (IS_ERR(job->bidi_rq)) {
  50                        ret = PTR_ERR(job->bidi_rq);
  51                        goto out;
  52                }
  53
  54                ret = blk_rq_map_user(rq->q, job->bidi_rq, NULL,
  55                                uptr64(hdr->din_xferp), hdr->din_xfer_len,
  56                                GFP_KERNEL);
  57                if (ret)
  58                        goto out_free_bidi_rq;
  59
  60                job->bidi_bio = job->bidi_rq->bio;
  61        } else {
  62                job->bidi_rq = NULL;
  63                job->bidi_bio = NULL;
  64        }
  65
  66        return 0;
  67
  68out_free_bidi_rq:
  69        if (job->bidi_rq)
  70                blk_put_request(job->bidi_rq);
  71out:
  72        kfree(job->request);
  73        return ret;
  74}
  75
  76static int bsg_transport_complete_rq(struct request *rq, struct sg_io_v4 *hdr)
  77{
  78        struct bsg_job *job = blk_mq_rq_to_pdu(rq);
  79        int ret = 0;
  80
  81        /*
  82         * The assignments below don't make much sense, but are kept for
  83         * bug by bug backwards compatibility:
  84         */
  85        hdr->device_status = job->result & 0xff;
  86        hdr->transport_status = host_byte(job->result);
  87        hdr->driver_status = 0;
  88        hdr->info = 0;
  89        if (hdr->device_status || hdr->transport_status || hdr->driver_status)
  90                hdr->info |= SG_INFO_CHECK;
  91        hdr->response_len = 0;
  92
  93        if (job->result < 0) {
  94                /* we're only returning the result field in the reply */
  95                job->reply_len = sizeof(u32);
  96                ret = job->result;
  97        }
  98
  99        if (job->reply_len && hdr->response) {
 100                int len = min(hdr->max_response_len, job->reply_len);
 101
 102                if (copy_to_user(uptr64(hdr->response), job->reply, len))
 103                        ret = -EFAULT;
 104                else
 105                        hdr->response_len = len;
 106        }
 107
 108        /* we assume all request payload was transferred, residual == 0 */
 109        hdr->dout_resid = 0;
 110
 111        if (job->bidi_rq) {
 112                unsigned int rsp_len = job->reply_payload.payload_len;
 113
 114                if (WARN_ON(job->reply_payload_rcv_len > rsp_len))
 115                        hdr->din_resid = 0;
 116                else
 117                        hdr->din_resid = rsp_len - job->reply_payload_rcv_len;
 118        } else {
 119                hdr->din_resid = 0;
 120        }
 121
 122        return ret;
 123}
 124
 125static void bsg_transport_free_rq(struct request *rq)
 126{
 127        struct bsg_job *job = blk_mq_rq_to_pdu(rq);
 128
 129        if (job->bidi_rq) {
 130                blk_rq_unmap_user(job->bidi_bio);
 131                blk_put_request(job->bidi_rq);
 132        }
 133
 134        kfree(job->request);
 135}
 136
 137static const struct bsg_ops bsg_transport_ops = {
 138        .check_proto            = bsg_transport_check_proto,
 139        .fill_hdr               = bsg_transport_fill_hdr,
 140        .complete_rq            = bsg_transport_complete_rq,
 141        .free_rq                = bsg_transport_free_rq,
 142};
 143
 144/**
 145 * bsg_teardown_job - routine to teardown a bsg job
 146 * @kref: kref inside bsg_job that is to be torn down
 147 */
 148static void bsg_teardown_job(struct kref *kref)
 149{
 150        struct bsg_job *job = container_of(kref, struct bsg_job, kref);
 151        struct request *rq = blk_mq_rq_from_pdu(job);
 152
 153        put_device(job->dev);   /* release reference for the request */
 154
 155        kfree(job->request_payload.sg_list);
 156        kfree(job->reply_payload.sg_list);
 157
 158        blk_mq_end_request(rq, BLK_STS_OK);
 159}
 160
 161void bsg_job_put(struct bsg_job *job)
 162{
 163        kref_put(&job->kref, bsg_teardown_job);
 164}
 165EXPORT_SYMBOL_GPL(bsg_job_put);
 166
 167int bsg_job_get(struct bsg_job *job)
 168{
 169        return kref_get_unless_zero(&job->kref);
 170}
 171EXPORT_SYMBOL_GPL(bsg_job_get);
 172
 173/**
 174 * bsg_job_done - completion routine for bsg requests
 175 * @job: bsg_job that is complete
 176 * @result: job reply result
 177 * @reply_payload_rcv_len: length of payload recvd
 178 *
 179 * The LLD should call this when the bsg job has completed.
 180 */
 181void bsg_job_done(struct bsg_job *job, int result,
 182                  unsigned int reply_payload_rcv_len)
 183{
 184        struct request *rq = blk_mq_rq_from_pdu(job);
 185
 186        job->result = result;
 187        job->reply_payload_rcv_len = reply_payload_rcv_len;
 188        if (likely(!blk_should_fake_timeout(rq->q)))
 189                blk_mq_complete_request(rq);
 190}
 191EXPORT_SYMBOL_GPL(bsg_job_done);
 192
 193/**
 194 * bsg_complete - softirq done routine for destroying the bsg requests
 195 * @rq: BSG request that holds the job to be destroyed
 196 */
 197static void bsg_complete(struct request *rq)
 198{
 199        struct bsg_job *job = blk_mq_rq_to_pdu(rq);
 200
 201        bsg_job_put(job);
 202}
 203
 204static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
 205{
 206        size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
 207
 208        BUG_ON(!req->nr_phys_segments);
 209
 210        buf->sg_list = kmalloc(sz, GFP_KERNEL);
 211        if (!buf->sg_list)
 212                return -ENOMEM;
 213        sg_init_table(buf->sg_list, req->nr_phys_segments);
 214        buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
 215        buf->payload_len = blk_rq_bytes(req);
 216        return 0;
 217}
 218
 219/**
 220 * bsg_prepare_job - create the bsg_job structure for the bsg request
 221 * @dev: device that is being sent the bsg request
 222 * @req: BSG request that needs a job structure
 223 */
 224static bool bsg_prepare_job(struct device *dev, struct request *req)
 225{
 226        struct bsg_job *job = blk_mq_rq_to_pdu(req);
 227        int ret;
 228
 229        job->timeout = req->timeout;
 230
 231        if (req->bio) {
 232                ret = bsg_map_buffer(&job->request_payload, req);
 233                if (ret)
 234                        goto failjob_rls_job;
 235        }
 236        if (job->bidi_rq) {
 237                ret = bsg_map_buffer(&job->reply_payload, job->bidi_rq);
 238                if (ret)
 239                        goto failjob_rls_rqst_payload;
 240        }
 241        job->dev = dev;
 242        /* take a reference for the request */
 243        get_device(job->dev);
 244        kref_init(&job->kref);
 245        return true;
 246
 247failjob_rls_rqst_payload:
 248        kfree(job->request_payload.sg_list);
 249failjob_rls_job:
 250        job->result = -ENOMEM;
 251        return false;
 252}
 253
 254/**
 255 * bsg_queue_rq - generic handler for bsg requests
 256 * @hctx: hardware queue
 257 * @bd: queue data
 258 *
 259 * On error the create_bsg_job function should return a -Exyz error value
 260 * that will be set to ->result.
 261 *
 262 * Drivers/subsys should pass this to the queue init function.
 263 */
 264static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
 265                                 const struct blk_mq_queue_data *bd)
 266{
 267        struct request_queue *q = hctx->queue;
 268        struct device *dev = q->queuedata;
 269        struct request *req = bd->rq;
 270        struct bsg_set *bset =
 271                container_of(q->tag_set, struct bsg_set, tag_set);
 272        blk_status_t sts = BLK_STS_IOERR;
 273        int ret;
 274
 275        blk_mq_start_request(req);
 276
 277        if (!get_device(dev))
 278                return BLK_STS_IOERR;
 279
 280        if (!bsg_prepare_job(dev, req))
 281                goto out;
 282
 283        ret = bset->job_fn(blk_mq_rq_to_pdu(req));
 284        if (!ret)
 285                sts = BLK_STS_OK;
 286
 287out:
 288        put_device(dev);
 289        return sts;
 290}
 291
 292/* called right after the request is allocated for the request_queue */
 293static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
 294                       unsigned int hctx_idx, unsigned int numa_node)
 295{
 296        struct bsg_job *job = blk_mq_rq_to_pdu(req);
 297
 298        job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
 299        if (!job->reply)
 300                return -ENOMEM;
 301        return 0;
 302}
 303
 304/* called right before the request is given to the request_queue user */
 305static void bsg_initialize_rq(struct request *req)
 306{
 307        struct bsg_job *job = blk_mq_rq_to_pdu(req);
 308        void *reply = job->reply;
 309
 310        memset(job, 0, sizeof(*job));
 311        job->reply = reply;
 312        job->reply_len = SCSI_SENSE_BUFFERSIZE;
 313        job->dd_data = job + 1;
 314}
 315
 316static void bsg_exit_rq(struct blk_mq_tag_set *set, struct request *req,
 317                       unsigned int hctx_idx)
 318{
 319        struct bsg_job *job = blk_mq_rq_to_pdu(req);
 320
 321        kfree(job->reply);
 322}
 323
 324void bsg_remove_queue(struct request_queue *q)
 325{
 326        if (q) {
 327                struct bsg_set *bset =
 328                        container_of(q->tag_set, struct bsg_set, tag_set);
 329
 330                bsg_unregister_queue(q);
 331                blk_cleanup_queue(q);
 332                blk_mq_free_tag_set(&bset->tag_set);
 333                kfree(bset);
 334        }
 335}
 336EXPORT_SYMBOL_GPL(bsg_remove_queue);
 337
 338static enum blk_eh_timer_return bsg_timeout(struct request *rq, bool reserved)
 339{
 340        struct bsg_set *bset =
 341                container_of(rq->q->tag_set, struct bsg_set, tag_set);
 342
 343        if (!bset->timeout_fn)
 344                return BLK_EH_DONE;
 345        return bset->timeout_fn(rq);
 346}
 347
 348static const struct blk_mq_ops bsg_mq_ops = {
 349        .queue_rq               = bsg_queue_rq,
 350        .init_request           = bsg_init_rq,
 351        .exit_request           = bsg_exit_rq,
 352        .initialize_rq_fn       = bsg_initialize_rq,
 353        .complete               = bsg_complete,
 354        .timeout                = bsg_timeout,
 355};
 356
 357/**
 358 * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
 359 * @dev: device to attach bsg device to
 360 * @name: device to give bsg device
 361 * @job_fn: bsg job handler
 362 * @timeout: timeout handler function pointer
 363 * @dd_job_size: size of LLD data needed for each job
 364 */
 365struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 366                bsg_job_fn *job_fn, bsg_timeout_fn *timeout, int dd_job_size)
 367{
 368        struct bsg_set *bset;
 369        struct blk_mq_tag_set *set;
 370        struct request_queue *q;
 371        int ret = -ENOMEM;
 372
 373        bset = kzalloc(sizeof(*bset), GFP_KERNEL);
 374        if (!bset)
 375                return ERR_PTR(-ENOMEM);
 376
 377        bset->job_fn = job_fn;
 378        bset->timeout_fn = timeout;
 379
 380        set = &bset->tag_set;
 381        set->ops = &bsg_mq_ops;
 382        set->nr_hw_queues = 1;
 383        set->queue_depth = 128;
 384        set->numa_node = NUMA_NO_NODE;
 385        set->cmd_size = sizeof(struct bsg_job) + dd_job_size;
 386        set->flags = BLK_MQ_F_NO_SCHED | BLK_MQ_F_BLOCKING;
 387        if (blk_mq_alloc_tag_set(set))
 388                goto out_tag_set;
 389
 390        q = blk_mq_init_queue(set);
 391        if (IS_ERR(q)) {
 392                ret = PTR_ERR(q);
 393                goto out_queue;
 394        }
 395
 396        q->queuedata = dev;
 397        blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
 398
 399        ret = bsg_register_queue(q, dev, name, &bsg_transport_ops);
 400        if (ret) {
 401                printk(KERN_ERR "%s: bsg interface failed to "
 402                       "initialize - register queue\n", dev->kobj.name);
 403                goto out_cleanup_queue;
 404        }
 405
 406        return q;
 407out_cleanup_queue:
 408        blk_cleanup_queue(q);
 409out_queue:
 410        blk_mq_free_tag_set(set);
 411out_tag_set:
 412        kfree(bset);
 413        return ERR_PTR(ret);
 414}
 415EXPORT_SYMBOL_GPL(bsg_setup_queue);
 416