The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/block/bsg-lib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  BSG helper library
    3  *
    4  *  Copyright (C) 2008   James Smart, Emulex Corporation
    5  *  Copyright (C) 2011   Red Hat, Inc.  All rights reserved.
    6  *  Copyright (C) 2011   Mike Christie
    7  *
    8  *  This program is free software; you can redistribute it and/or modify
    9  *  it under the terms of the GNU General Public License as published by
   10  *  the Free Software Foundation; either version 2 of the License, or
   11  *  (at your option) any later version.
   12  *
   13  *  This program is distributed in the hope that it will be useful,
   14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  *  GNU General Public License for more details.
   17  *
   18  *  You should have received a copy of the GNU General Public License
   19  *  along with this program; if not, write to the Free Software
   20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21  *
   22  */
   23 #include <linux/slab.h>
   24 #include <linux/blkdev.h>
   25 #include <linux/delay.h>
   26 #include <linux/scatterlist.h>
   27 #include <linux/bsg-lib.h>
   28 #include <linux/export.h>
   29 #include <scsi/scsi_cmnd.h>
   30 
   31 /**
   32  * bsg_destroy_job - routine to teardown/delete a bsg job
   33  * @job: bsg_job that is to be torn down
   34  */
   35 static void bsg_destroy_job(struct bsg_job *job)
   36 {
   37         put_device(job->dev);   /* release reference for the request */
   38 
   39         kfree(job->request_payload.sg_list);
   40         kfree(job->reply_payload.sg_list);
   41         kfree(job);
   42 }
   43 
   44 /**
   45  * bsg_job_done - completion routine for bsg requests
   46  * @job: bsg_job that is complete
   47  * @result: job reply result
   48  * @reply_payload_rcv_len: length of payload recvd
   49  *
   50  * The LLD should call this when the bsg job has completed.
   51  */
   52 void bsg_job_done(struct bsg_job *job, int result,
   53                   unsigned int reply_payload_rcv_len)
   54 {
   55         struct request *req = job->req;
   56         struct request *rsp = req->next_rq;
   57         int err;
   58 
   59         err = job->req->errors = result;
   60         if (err < 0)
   61                 /* we're only returning the result field in the reply */
   62                 job->req->sense_len = sizeof(u32);
   63         else
   64                 job->req->sense_len = job->reply_len;
   65         /* we assume all request payload was transferred, residual == 0 */
   66         req->resid_len = 0;
   67 
   68         if (rsp) {
   69                 WARN_ON(reply_payload_rcv_len > rsp->resid_len);
   70 
   71                 /* set reply (bidi) residual */
   72                 rsp->resid_len -= min(reply_payload_rcv_len, rsp->resid_len);
   73         }
   74         blk_complete_request(req);
   75 }
   76 EXPORT_SYMBOL_GPL(bsg_job_done);
   77 
   78 /**
   79  * bsg_softirq_done - softirq done routine for destroying the bsg requests
   80  * @rq: BSG request that holds the job to be destroyed
   81  */
   82 static void bsg_softirq_done(struct request *rq)
   83 {
   84         struct bsg_job *job = rq->special;
   85 
   86         blk_end_request_all(rq, rq->errors);
   87         bsg_destroy_job(job);
   88 }
   89 
   90 static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
   91 {
   92         size_t sz = (sizeof(struct scatterlist) * req->nr_phys_segments);
   93 
   94         BUG_ON(!req->nr_phys_segments);
   95 
   96         buf->sg_list = kzalloc(sz, GFP_KERNEL);
   97         if (!buf->sg_list)
   98                 return -ENOMEM;
   99         sg_init_table(buf->sg_list, req->nr_phys_segments);
  100         buf->sg_cnt = blk_rq_map_sg(req->q, req, buf->sg_list);
  101         buf->payload_len = blk_rq_bytes(req);
  102         return 0;
  103 }
  104 
  105 /**
  106  * bsg_create_job - create the bsg_job structure for the bsg request
  107  * @dev: device that is being sent the bsg request
  108  * @req: BSG request that needs a job structure
  109  */
  110 static int bsg_create_job(struct device *dev, struct request *req)
  111 {
  112         struct request *rsp = req->next_rq;
  113         struct request_queue *q = req->q;
  114         struct bsg_job *job;
  115         int ret;
  116 
  117         BUG_ON(req->special);
  118 
  119         job = kzalloc(sizeof(struct bsg_job) + q->bsg_job_size, GFP_KERNEL);
  120         if (!job)
  121                 return -ENOMEM;
  122 
  123         req->special = job;
  124         job->req = req;
  125         if (q->bsg_job_size)
  126                 job->dd_data = (void *)&job[1];
  127         job->request = req->cmd;
  128         job->request_len = req->cmd_len;
  129         job->reply = req->sense;
  130         job->reply_len = SCSI_SENSE_BUFFERSIZE; /* Size of sense buffer
  131                                                  * allocated */
  132         if (req->bio) {
  133                 ret = bsg_map_buffer(&job->request_payload, req);
  134                 if (ret)
  135                         goto failjob_rls_job;
  136         }
  137         if (rsp && rsp->bio) {
  138                 ret = bsg_map_buffer(&job->reply_payload, rsp);
  139                 if (ret)
  140                         goto failjob_rls_rqst_payload;
  141         }
  142         job->dev = dev;
  143         /* take a reference for the request */
  144         get_device(job->dev);
  145         return 0;
  146 
  147 failjob_rls_rqst_payload:
  148         kfree(job->request_payload.sg_list);
  149 failjob_rls_job:
  150         kfree(job);
  151         return -ENOMEM;
  152 }
  153 
  154 /**
  155  * bsg_request_fn - generic handler for bsg requests
  156  * @q: request queue to manage
  157  *
  158  * On error the create_bsg_job function should return a -Exyz error value
  159  * that will be set to the req->errors.
  160  *
  161  * Drivers/subsys should pass this to the queue init function.
  162  */
  163 void bsg_request_fn(struct request_queue *q)
  164 {
  165         struct device *dev = q->queuedata;
  166         struct request *req;
  167         struct bsg_job *job;
  168         int ret;
  169 
  170         if (!get_device(dev))
  171                 return;
  172 
  173         while (1) {
  174                 req = blk_fetch_request(q);
  175                 if (!req)
  176                         break;
  177                 spin_unlock_irq(q->queue_lock);
  178 
  179                 ret = bsg_create_job(dev, req);
  180                 if (ret) {
  181                         req->errors = ret;
  182                         blk_end_request_all(req, ret);
  183                         spin_lock_irq(q->queue_lock);
  184                         continue;
  185                 }
  186 
  187                 job = req->special;
  188                 ret = q->bsg_job_fn(job);
  189                 spin_lock_irq(q->queue_lock);
  190                 if (ret)
  191                         break;
  192         }
  193 
  194         spin_unlock_irq(q->queue_lock);
  195         put_device(dev);
  196         spin_lock_irq(q->queue_lock);
  197 }
  198 EXPORT_SYMBOL_GPL(bsg_request_fn);
  199 
  200 /**
  201  * bsg_setup_queue - Create and add the bsg hooks so we can receive requests
  202  * @dev: device to attach bsg device to
  203  * @q: request queue setup by caller
  204  * @name: device to give bsg device
  205  * @job_fn: bsg job handler
  206  * @dd_job_size: size of LLD data needed for each job
  207  *
  208  * The caller should have setup the reuqest queue with bsg_request_fn
  209  * as the request_fn.
  210  */
  211 int bsg_setup_queue(struct device *dev, struct request_queue *q,
  212                     char *name, bsg_job_fn *job_fn, int dd_job_size)
  213 {
  214         int ret;
  215 
  216         q->queuedata = dev;
  217         q->bsg_job_size = dd_job_size;
  218         q->bsg_job_fn = job_fn;
  219         queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
  220         blk_queue_softirq_done(q, bsg_softirq_done);
  221         blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT);
  222 
  223         ret = bsg_register_queue(q, dev, name, NULL);
  224         if (ret) {
  225                 printk(KERN_ERR "%s: bsg interface failed to "
  226                        "initialize - register queue\n", dev->kobj.name);
  227                 return ret;
  228         }
  229 
  230         return 0;
  231 }
  232 EXPORT_SYMBOL_GPL(bsg_setup_queue);

Cache object: 452b7dc65bb42a64f2f19bba46fb150b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.