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/dev/vscsi.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 /*      $OpenBSD: vscsi.c,v 1.61 2022/07/02 08:50:41 visa Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/kernel.h>
   22 #include <sys/malloc.h>
   23 #include <sys/device.h>
   24 #include <sys/conf.h>
   25 #include <sys/queue.h>
   26 #include <sys/rwlock.h>
   27 #include <sys/pool.h>
   28 #include <sys/task.h>
   29 #include <sys/ioctl.h>
   30 #include <sys/selinfo.h>
   31 
   32 #include <scsi/scsi_all.h>
   33 #include <scsi/scsiconf.h>
   34 
   35 #include <dev/vscsivar.h>
   36 
   37 int             vscsi_match(struct device *, void *, void *);
   38 void            vscsi_attach(struct device *, struct device *, void *);
   39 void            vscsi_shutdown(void *);
   40 
   41 struct vscsi_ccb {
   42         TAILQ_ENTRY(vscsi_ccb)  ccb_entry;
   43         int                     ccb_tag;
   44         struct scsi_xfer        *ccb_xs;
   45         size_t                  ccb_datalen;
   46 };
   47 
   48 TAILQ_HEAD(vscsi_ccb_list, vscsi_ccb);
   49 
   50 enum vscsi_state {
   51         VSCSI_S_CLOSED,
   52         VSCSI_S_CONFIG,
   53         VSCSI_S_RUNNING
   54 };
   55 
   56 struct vscsi_softc {
   57         struct device           sc_dev;
   58         struct scsibus_softc    *sc_scsibus;
   59 
   60         struct mutex            sc_state_mtx;
   61         enum vscsi_state        sc_state;
   62         u_int                   sc_ref_count;
   63         struct pool             sc_ccb_pool;
   64 
   65         struct scsi_iopool      sc_iopool;
   66 
   67         struct vscsi_ccb_list   sc_ccb_i2t;
   68         struct vscsi_ccb_list   sc_ccb_t2i;
   69         int                     sc_ccb_tag;
   70         struct mutex            sc_poll_mtx;
   71         struct rwlock           sc_ioc_lock;
   72 
   73         struct selinfo          sc_sel;
   74         struct mutex            sc_sel_mtx;
   75 };
   76 
   77 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
   78 #define DEV2SC(_d) ((struct vscsi_softc *)device_lookup(&vscsi_cd, minor(_d)))
   79 
   80 const struct cfattach vscsi_ca = {
   81         sizeof(struct vscsi_softc),
   82         vscsi_match,
   83         vscsi_attach
   84 };
   85 
   86 struct cfdriver vscsi_cd = {
   87         NULL,
   88         "vscsi",
   89         DV_DULL
   90 };
   91 
   92 void            vscsi_cmd(struct scsi_xfer *);
   93 int             vscsi_probe(struct scsi_link *);
   94 void            vscsi_free(struct scsi_link *);
   95 
   96 const struct scsi_adapter vscsi_switch = {
   97         vscsi_cmd, NULL, vscsi_probe, vscsi_free, NULL
   98 };
   99 
  100 int             vscsi_i2t(struct vscsi_softc *, struct vscsi_ioc_i2t *);
  101 int             vscsi_data(struct vscsi_softc *, struct vscsi_ioc_data *, int);
  102 int             vscsi_t2i(struct vscsi_softc *, struct vscsi_ioc_t2i *);
  103 int             vscsi_devevent(struct vscsi_softc *, u_long,
  104                     struct vscsi_ioc_devevent *);
  105 void            vscsi_devevent_task(void *);
  106 void            vscsi_done(struct vscsi_softc *, struct vscsi_ccb *);
  107 
  108 void *          vscsi_ccb_get(void *);
  109 void            vscsi_ccb_put(void *, void *);
  110 
  111 void            filt_vscsidetach(struct knote *);
  112 int             filt_vscsiread(struct knote *, long);
  113 
  114 const struct filterops vscsi_filtops = {
  115         .f_flags        = FILTEROP_ISFD,
  116         .f_attach       = NULL,
  117         .f_detach       = filt_vscsidetach,
  118         .f_event        = filt_vscsiread,
  119 };
  120 
  121 
  122 int
  123 vscsi_match(struct device *parent, void *match, void *aux)
  124 {
  125         return (1);
  126 }
  127 
  128 void
  129 vscsi_attach(struct device *parent, struct device *self, void *aux)
  130 {
  131         struct vscsi_softc              *sc = (struct vscsi_softc *)self;
  132         struct scsibus_attach_args      saa;
  133 
  134         printf("\n");
  135 
  136         mtx_init(&sc->sc_state_mtx, IPL_BIO);
  137         sc->sc_state = VSCSI_S_CLOSED;
  138 
  139         TAILQ_INIT(&sc->sc_ccb_i2t);
  140         TAILQ_INIT(&sc->sc_ccb_t2i);
  141         mtx_init(&sc->sc_poll_mtx, IPL_BIO);
  142         mtx_init(&sc->sc_sel_mtx, IPL_BIO);
  143         rw_init(&sc->sc_ioc_lock, "vscsiioc");
  144         scsi_iopool_init(&sc->sc_iopool, sc, vscsi_ccb_get, vscsi_ccb_put);
  145 
  146         saa.saa_adapter = &vscsi_switch;
  147         saa.saa_adapter_softc = sc;
  148         saa.saa_adapter_target = SDEV_NO_ADAPTER_TARGET;
  149         saa.saa_adapter_buswidth = 256;
  150         saa.saa_luns = 8;
  151         saa.saa_openings = 16;
  152         saa.saa_pool = &sc->sc_iopool;
  153         saa.saa_quirks = saa.saa_flags = 0;
  154         saa.saa_wwpn = saa.saa_wwnn = 0;
  155 
  156         sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev,
  157             &saa, scsiprint);
  158 }
  159 
  160 void
  161 vscsi_cmd(struct scsi_xfer *xs)
  162 {
  163         struct scsi_link                *link = xs->sc_link;
  164         struct vscsi_softc              *sc = link->bus->sb_adapter_softc;
  165         struct vscsi_ccb                *ccb = xs->io;
  166         int                             polled = ISSET(xs->flags, SCSI_POLL);
  167         int                             running = 0;
  168 
  169         if (ISSET(xs->flags, SCSI_POLL) && ISSET(xs->flags, SCSI_NOSLEEP)) {
  170                 printf("%s: POLL && NOSLEEP for 0x%02x\n", DEVNAME(sc),
  171                     xs->cmd.opcode);
  172                 xs->error = XS_DRIVER_STUFFUP;
  173                 scsi_done(xs);
  174                 return;
  175         }
  176 
  177         ccb->ccb_xs = xs;
  178 
  179         mtx_enter(&sc->sc_state_mtx);
  180         if (sc->sc_state == VSCSI_S_RUNNING) {
  181                 running = 1;
  182                 TAILQ_INSERT_TAIL(&sc->sc_ccb_i2t, ccb, ccb_entry);
  183         }
  184         mtx_leave(&sc->sc_state_mtx);
  185 
  186         if (!running) {
  187                 xs->error = XS_DRIVER_STUFFUP;
  188                 scsi_done(xs);
  189                 return;
  190         }
  191 
  192         selwakeup(&sc->sc_sel);
  193 
  194         if (polled) {
  195                 mtx_enter(&sc->sc_poll_mtx);
  196                 while (ccb->ccb_xs != NULL)
  197                         msleep_nsec(ccb, &sc->sc_poll_mtx, PRIBIO, "vscsipoll",
  198                             INFSLP);
  199                 mtx_leave(&sc->sc_poll_mtx);
  200                 scsi_done(xs);
  201         }
  202 }
  203 
  204 void
  205 vscsi_done(struct vscsi_softc *sc, struct vscsi_ccb *ccb)
  206 {
  207         struct scsi_xfer                *xs = ccb->ccb_xs;
  208 
  209         if (ISSET(xs->flags, SCSI_POLL)) {
  210                 mtx_enter(&sc->sc_poll_mtx);
  211                 ccb->ccb_xs = NULL;
  212                 wakeup(ccb);
  213                 mtx_leave(&sc->sc_poll_mtx);
  214         } else
  215                 scsi_done(xs);
  216 }
  217 
  218 int
  219 vscsi_probe(struct scsi_link *link)
  220 {
  221         struct vscsi_softc              *sc = link->bus->sb_adapter_softc;
  222         int                             rv = 0;
  223 
  224         mtx_enter(&sc->sc_state_mtx);
  225         if (sc->sc_state == VSCSI_S_RUNNING)
  226                 sc->sc_ref_count++;
  227         else
  228                 rv = ENXIO;
  229         mtx_leave(&sc->sc_state_mtx);
  230 
  231         return (rv);
  232 }
  233 
  234 void
  235 vscsi_free(struct scsi_link *link)
  236 {
  237         struct vscsi_softc              *sc = link->bus->sb_adapter_softc;
  238 
  239         mtx_enter(&sc->sc_state_mtx);
  240         sc->sc_ref_count--;
  241         if (sc->sc_state != VSCSI_S_RUNNING && sc->sc_ref_count == 0)
  242                 wakeup(&sc->sc_ref_count);
  243         mtx_leave(&sc->sc_state_mtx);
  244 }
  245 
  246 int
  247 vscsiopen(dev_t dev, int flags, int mode, struct proc *p)
  248 {
  249         struct vscsi_softc              *sc = DEV2SC(dev);
  250         enum vscsi_state                state = VSCSI_S_RUNNING;
  251         int                             rv = 0;
  252 
  253         if (sc == NULL)
  254                 return (ENXIO);
  255 
  256         mtx_enter(&sc->sc_state_mtx);
  257         if (sc->sc_state != VSCSI_S_CLOSED)
  258                 rv = EBUSY;
  259         else
  260                 sc->sc_state = VSCSI_S_CONFIG;
  261         mtx_leave(&sc->sc_state_mtx);
  262 
  263         if (rv != 0) {
  264                 device_unref(&sc->sc_dev);
  265                 return (rv);
  266         }
  267 
  268         pool_init(&sc->sc_ccb_pool, sizeof(struct vscsi_ccb), 0, IPL_BIO, 0,
  269             "vscsiccb", NULL);
  270 
  271         /* we need to guarantee some ccbs will be available for the iopool */
  272         rv = pool_prime(&sc->sc_ccb_pool, 8);
  273         if (rv != 0) {
  274                 pool_destroy(&sc->sc_ccb_pool);
  275                 state = VSCSI_S_CLOSED;
  276         }
  277 
  278         /* commit changes */
  279         mtx_enter(&sc->sc_state_mtx);
  280         sc->sc_state = state;
  281         mtx_leave(&sc->sc_state_mtx);
  282 
  283         device_unref(&sc->sc_dev);
  284         return (rv);
  285 }
  286 
  287 int
  288 vscsiioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
  289 {
  290         struct vscsi_softc              *sc = DEV2SC(dev);
  291         int                             read = 0;
  292         int                             err = 0;
  293 
  294         if (sc == NULL)
  295                 return (ENXIO);
  296 
  297         rw_enter_write(&sc->sc_ioc_lock);
  298 
  299         switch (cmd) {
  300         case VSCSI_I2T:
  301                 err = vscsi_i2t(sc, (struct vscsi_ioc_i2t *)addr);
  302                 break;
  303 
  304         case VSCSI_DATA_READ:
  305                 read = 1;
  306         case VSCSI_DATA_WRITE:
  307                 err = vscsi_data(sc, (struct vscsi_ioc_data *)addr, read);
  308                 break;
  309 
  310         case VSCSI_T2I:
  311                 err = vscsi_t2i(sc, (struct vscsi_ioc_t2i *)addr);
  312                 break;
  313 
  314         case VSCSI_REQPROBE:
  315         case VSCSI_REQDETACH:
  316                 err = vscsi_devevent(sc, cmd,
  317                     (struct vscsi_ioc_devevent *)addr);
  318                 break;
  319 
  320         default:
  321                 err = ENOTTY;
  322                 break;
  323         }
  324 
  325         rw_exit_write(&sc->sc_ioc_lock);
  326 
  327         device_unref(&sc->sc_dev);
  328         return (err);
  329 }
  330 
  331 int
  332 vscsi_i2t(struct vscsi_softc *sc, struct vscsi_ioc_i2t *i2t)
  333 {
  334         struct vscsi_ccb                *ccb;
  335         struct scsi_xfer                *xs;
  336         struct scsi_link                *link;
  337 
  338         mtx_enter(&sc->sc_state_mtx);
  339         ccb = TAILQ_FIRST(&sc->sc_ccb_i2t);
  340         if (ccb != NULL)
  341                 TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry);
  342         mtx_leave(&sc->sc_state_mtx);
  343 
  344         if (ccb == NULL)
  345                 return (EAGAIN);
  346 
  347         xs = ccb->ccb_xs;
  348         link = xs->sc_link;
  349 
  350         i2t->tag = ccb->ccb_tag;
  351         i2t->target = link->target;
  352         i2t->lun = link->lun;
  353         memcpy(&i2t->cmd, &xs->cmd, xs->cmdlen);
  354         i2t->cmdlen = xs->cmdlen;
  355         i2t->datalen = xs->datalen;
  356 
  357         switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  358         case SCSI_DATA_IN:
  359                 i2t->direction = VSCSI_DIR_READ;
  360                 break;
  361         case SCSI_DATA_OUT:
  362                 i2t->direction = VSCSI_DIR_WRITE;
  363                 break;
  364         default:
  365                 i2t->direction = VSCSI_DIR_NONE;
  366                 break;
  367         }
  368 
  369         TAILQ_INSERT_TAIL(&sc->sc_ccb_t2i, ccb, ccb_entry);
  370 
  371         return (0);
  372 }
  373 
  374 int
  375 vscsi_data(struct vscsi_softc *sc, struct vscsi_ioc_data *data, int read)
  376 {
  377         struct vscsi_ccb                *ccb;
  378         struct scsi_xfer                *xs;
  379         int                             xsread;
  380         u_int8_t                        *buf;
  381         int                             rv = EINVAL;
  382 
  383         TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) {
  384                 if (ccb->ccb_tag == data->tag)
  385                         break;
  386         }
  387         if (ccb == NULL)
  388                 return (EFAULT);
  389 
  390         xs = ccb->ccb_xs;
  391 
  392         if (data->datalen > xs->datalen - ccb->ccb_datalen)
  393                 return (ENOMEM);
  394 
  395         switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
  396         case SCSI_DATA_IN:
  397                 xsread = 1;
  398                 break;
  399         case SCSI_DATA_OUT:
  400                 xsread = 0;
  401                 break;
  402         default:
  403                 return (EINVAL);
  404         }
  405 
  406         if (read != xsread)
  407                 return (EINVAL);
  408 
  409         buf = xs->data;
  410         buf += ccb->ccb_datalen;
  411 
  412         if (read)
  413                 rv = copyin(data->data, buf, data->datalen);
  414         else
  415                 rv = copyout(buf, data->data, data->datalen);
  416 
  417         if (rv == 0)
  418                 ccb->ccb_datalen += data->datalen;
  419 
  420         return (rv);
  421 }
  422 
  423 int
  424 vscsi_t2i(struct vscsi_softc *sc, struct vscsi_ioc_t2i *t2i)
  425 {
  426         struct vscsi_ccb                *ccb;
  427         struct scsi_xfer                *xs;
  428         int                             rv = 0;
  429 
  430         TAILQ_FOREACH(ccb, &sc->sc_ccb_t2i, ccb_entry) {
  431                 if (ccb->ccb_tag == t2i->tag)
  432                         break;
  433         }
  434         if (ccb == NULL)
  435                 return (EFAULT);
  436 
  437         TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry);
  438 
  439         xs = ccb->ccb_xs;
  440 
  441         xs->resid = xs->datalen - ccb->ccb_datalen;
  442         xs->status = SCSI_OK;
  443 
  444         switch (t2i->status) {
  445         case VSCSI_STAT_DONE:
  446                 xs->error = XS_NOERROR;
  447                 break;
  448         case VSCSI_STAT_SENSE:
  449                 xs->error = XS_SENSE;
  450                 memcpy(&xs->sense, &t2i->sense, sizeof(xs->sense));
  451                 break;
  452         case VSCSI_STAT_RESET:
  453                 xs->error = XS_RESET;
  454                 break;
  455         case VSCSI_STAT_ERR:
  456         default:
  457                 xs->error = XS_DRIVER_STUFFUP;
  458                 break;
  459         }
  460 
  461         vscsi_done(sc, ccb);
  462 
  463         return (rv);
  464 }
  465 
  466 struct vscsi_devevent_task {
  467         struct vscsi_softc *sc;
  468         struct task t;
  469         struct vscsi_ioc_devevent de;
  470         u_long cmd;
  471 };
  472 
  473 int
  474 vscsi_devevent(struct vscsi_softc *sc, u_long cmd,
  475     struct vscsi_ioc_devevent *de)
  476 {
  477         struct vscsi_devevent_task *dt;
  478 
  479         dt = malloc(sizeof(*dt), M_TEMP, M_WAITOK | M_CANFAIL);
  480         if (dt == NULL)
  481                 return (ENOMEM);
  482 
  483         task_set(&dt->t, vscsi_devevent_task, dt);
  484         dt->sc = sc;
  485         dt->de = *de;
  486         dt->cmd = cmd;
  487 
  488         device_ref(&sc->sc_dev);
  489         task_add(systq, &dt->t);
  490 
  491         return (0);
  492 }
  493 
  494 void
  495 vscsi_devevent_task(void *xdt)
  496 {
  497         struct vscsi_devevent_task *dt = xdt;
  498         struct vscsi_softc *sc = dt->sc;
  499         int state;
  500 
  501         mtx_enter(&sc->sc_state_mtx);
  502         state = sc->sc_state;
  503         mtx_leave(&sc->sc_state_mtx);
  504 
  505         if (state != VSCSI_S_RUNNING)
  506                 goto gone;
  507 
  508         switch (dt->cmd) {
  509         case VSCSI_REQPROBE:
  510                 scsi_probe(sc->sc_scsibus, dt->de.target, dt->de.lun);
  511                 break;
  512         case VSCSI_REQDETACH:
  513                 scsi_detach(sc->sc_scsibus, dt->de.target, dt->de.lun,
  514                     DETACH_FORCE);
  515                 break;
  516 #ifdef DIAGNOSTIC
  517         default:
  518                 panic("unexpected vscsi_devevent cmd");
  519                 /* NOTREACHED */
  520 #endif
  521         }
  522 
  523 gone:
  524         device_unref(&sc->sc_dev);
  525 
  526         free(dt, M_TEMP, sizeof(*dt));
  527 }
  528 
  529 int
  530 vscsikqfilter(dev_t dev, struct knote *kn)
  531 {
  532         struct vscsi_softc *sc = DEV2SC(dev);
  533         struct klist *klist;
  534 
  535         if (sc == NULL)
  536                 return (ENXIO);
  537 
  538         klist = &sc->sc_sel.si_note;
  539 
  540         switch (kn->kn_filter) {
  541         case EVFILT_READ:
  542                 kn->kn_fop = &vscsi_filtops;
  543                 break;
  544         default:
  545                 device_unref(&sc->sc_dev);
  546                 return (EINVAL);
  547         }
  548 
  549         kn->kn_hook = sc;
  550 
  551         mtx_enter(&sc->sc_sel_mtx);
  552         klist_insert_locked(klist, kn);
  553         mtx_leave(&sc->sc_sel_mtx);
  554 
  555         /* device ref is given to the knote in the klist */
  556 
  557         return (0);
  558 }
  559 
  560 void
  561 filt_vscsidetach(struct knote *kn)
  562 {
  563         struct vscsi_softc *sc = kn->kn_hook;
  564         struct klist *klist = &sc->sc_sel.si_note;
  565 
  566         mtx_enter(&sc->sc_sel_mtx);
  567         klist_remove_locked(klist, kn);
  568         mtx_leave(&sc->sc_sel_mtx);
  569 
  570         device_unref(&sc->sc_dev);
  571 }
  572 
  573 int
  574 filt_vscsiread(struct knote *kn, long hint)
  575 {
  576         struct vscsi_softc *sc = kn->kn_hook;
  577         int event = 0;
  578 
  579         mtx_enter(&sc->sc_state_mtx);
  580         if (!TAILQ_EMPTY(&sc->sc_ccb_i2t))
  581                 event = 1;
  582         mtx_leave(&sc->sc_state_mtx);
  583 
  584         return (event);
  585 }
  586 
  587 int
  588 vscsiclose(dev_t dev, int flags, int mode, struct proc *p)
  589 {
  590         struct vscsi_softc              *sc = DEV2SC(dev);
  591         struct vscsi_ccb                *ccb;
  592 
  593         if (sc == NULL)
  594                 return (ENXIO);
  595 
  596         mtx_enter(&sc->sc_state_mtx);
  597         KASSERT(sc->sc_state == VSCSI_S_RUNNING);
  598         sc->sc_state = VSCSI_S_CONFIG;
  599         mtx_leave(&sc->sc_state_mtx);
  600 
  601         scsi_activate(sc->sc_scsibus, -1, -1, DVACT_DEACTIVATE);
  602 
  603         while ((ccb = TAILQ_FIRST(&sc->sc_ccb_t2i)) != NULL) {
  604                 TAILQ_REMOVE(&sc->sc_ccb_t2i, ccb, ccb_entry);
  605                 ccb->ccb_xs->error = XS_RESET;
  606                 vscsi_done(sc, ccb);
  607         }
  608 
  609         while ((ccb = TAILQ_FIRST(&sc->sc_ccb_i2t)) != NULL) {
  610                 TAILQ_REMOVE(&sc->sc_ccb_i2t, ccb, ccb_entry);
  611                 ccb->ccb_xs->error = XS_RESET;
  612                 vscsi_done(sc, ccb);
  613         }
  614 
  615         scsi_req_detach(sc->sc_scsibus, -1, -1, DETACH_FORCE);
  616 
  617         mtx_enter(&sc->sc_state_mtx);
  618         while (sc->sc_ref_count > 0) {
  619                 msleep_nsec(&sc->sc_ref_count, &sc->sc_state_mtx,
  620                     PRIBIO, "vscsiref", INFSLP);
  621         }
  622         mtx_leave(&sc->sc_state_mtx);
  623 
  624         pool_destroy(&sc->sc_ccb_pool);
  625 
  626         mtx_enter(&sc->sc_state_mtx);
  627         sc->sc_state = VSCSI_S_CLOSED;
  628         mtx_leave(&sc->sc_state_mtx);
  629 
  630         device_unref(&sc->sc_dev);
  631         return (0);
  632 }
  633 
  634 void *
  635 vscsi_ccb_get(void *cookie)
  636 {
  637         struct vscsi_softc              *sc = cookie;
  638         struct vscsi_ccb                *ccb = NULL;
  639 
  640         ccb = pool_get(&sc->sc_ccb_pool, PR_NOWAIT);
  641         if (ccb != NULL) {
  642                 ccb->ccb_tag = sc->sc_ccb_tag++;
  643                 ccb->ccb_datalen = 0;
  644         }
  645 
  646         return (ccb);
  647 }
  648 
  649 void
  650 vscsi_ccb_put(void *cookie, void *io)
  651 {
  652         struct vscsi_softc              *sc = cookie;
  653         struct vscsi_ccb                *ccb = io;
  654 
  655         pool_put(&sc->sc_ccb_pool, ccb);
  656 }

Cache object: fdb444f025f86ad9a4badfe747739ac1


[ 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.