--- src/sys/bus/cam/scsi/scsi_pass.c 2007/12/02 04:24:11 1.26 +++ src/sys/bus/cam/scsi/scsi_pass.c 2008/05/18 20:30:20 1.27 @@ -49,6 +49,7 @@ #include "../cam_queue.h" #include "../cam_xpt_periph.h" #include "../cam_debug.h" +#include "../cam_sim.h" #include "scsi_all.h" #include "scsi_message.h" @@ -125,7 +126,6 @@ static void passinit(void) { cam_status status; - struct cam_path *path; /* * Create our extend array for storing the devices we attach to. @@ -140,21 +140,7 @@ passinit(void) * Install a global async callback. This callback will * receive async callbacks like "new device found". */ - status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, - CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); - - if (status == CAM_REQ_CMP) { - struct ccb_setasync csa; - - xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_FOUND_DEVICE; - csa.callback = passasync; - csa.callback_arg = NULL; - xpt_action((union ccb *)&csa); - status = csa.ccb_h.status; - xpt_free_path(path); - } + status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL); if (status != CAM_REQ_CMP) { kprintf("pass: Failed to attach master async callback " @@ -167,26 +153,18 @@ static void passoninvalidate(struct cam_periph *periph) { struct pass_softc *softc; - struct ccb_setasync csa; softc = (struct pass_softc *)periph->softc; /* * De-register any async callbacks. */ - xpt_setup_ccb(&csa.ccb_h, periph->path, - /* priority */ 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = 0; - csa.callback = passasync; - csa.callback_arg = periph; - xpt_action((union ccb *)&csa); + xpt_register_async(0, passasync, periph, periph->path); softc->flags |= PASS_FLAG_INVALID; if (bootverbose) { - xpt_print_path(periph->path); - kprintf("lost device\n"); + xpt_print(periph->path, "lost device\n"); } } @@ -203,8 +181,7 @@ passcleanup(struct cam_periph *periph) cam_extend_release(passperiphs, periph->unit_number); if (bootverbose) { - xpt_print_path(periph->path); - kprintf("removing device entry\n"); + xpt_print(periph->path, "removing device entry\n"); } dev_ops_remove(&pass_ops, -1, periph->unit_number); kfree(softc, M_DEVBUF); @@ -215,6 +192,7 @@ passasync(void *callback_arg, u_int32_t struct cam_path *path, void *arg) { struct cam_periph *periph; + struct cam_sim *sim; periph = (struct cam_periph *)callback_arg; @@ -233,6 +211,7 @@ passasync(void *callback_arg, u_int32_t * this device and start the probe * process. */ + sim = xpt_path_sim(cgd->ccb_h.path); status = cam_periph_alloc(passregister, passoninvalidate, passcleanup, passstart, "pass", CAM_PERIPH_BIO, cgd->ccb_h.path, @@ -261,7 +240,6 @@ static cam_status passregister(struct cam_periph *periph, void *arg) { struct pass_softc *softc; - struct ccb_setasync csa; struct ccb_getdev *cgd; int no_tags; @@ -288,6 +266,7 @@ passregister(struct cam_periph *periph, * know what the blocksize of this device is, if * it even has a blocksize. */ + CAM_SIM_UNLOCK(periph->sim); no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; devstat_add_entry(&softc->device_stats, "pass", periph->unit_number, 0, DEVSTAT_NO_BLOCKSIZE @@ -302,17 +281,12 @@ passregister(struct cam_periph *periph, make_dev(&pass_ops, periph->unit_number, UID_ROOT, GID_OPERATOR, 0600, "%s%d", periph->periph_name, periph->unit_number); - + CAM_SIM_LOCK(periph->sim); /* * Add an async callback so that we get * notified if this device goes away. */ - xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_LOST_DEVICE; - csa.callback = passasync; - csa.callback_arg = periph; - xpt_action((union ccb *)&csa); + xpt_register_async(AC_LOST_DEVICE, passasync, periph, periph->path); if (bootverbose) xpt_announce_periph(periph, NULL); @@ -336,14 +310,16 @@ passopen(struct dev_open_args *ap) periph = cam_extend_get(passperiphs, unit); - if (periph == NULL) + if (cam_periph_acquire(periph) != CAM_REQ_CMP) return (ENXIO); + cam_periph_lock(periph); + softc = (struct pass_softc *)periph->softc; - crit_enter(); if (softc->flags & PASS_FLAG_INVALID) { - crit_exit(); + cam_periph_unlock(periph); + cam_periph_release(periph); return(ENXIO); } @@ -351,7 +327,8 @@ passopen(struct dev_open_args *ap) * Don't allow access when we're running at a high securelevel. */ if (securelevel > 1) { - crit_exit(); + cam_periph_unlock(periph); + cam_periph_release(periph); return(EPERM); } @@ -359,7 +336,8 @@ passopen(struct dev_open_args *ap) * Only allow read-write access. */ if (((ap->a_oflags & FWRITE) == 0) || ((ap->a_oflags & FREAD) == 0)) { - crit_exit(); + cam_periph_unlock(periph); + cam_periph_release(periph); return(EPERM); } @@ -367,23 +345,17 @@ passopen(struct dev_open_args *ap) * We don't allow nonblocking access. */ if ((ap->a_oflags & O_NONBLOCK) != 0) { - xpt_print_path(periph->path); - kprintf("can't do nonblocking access\n"); - crit_exit(); + xpt_print(periph->path, "can't do nonblocking access\n"); + cam_periph_unlock(periph); + cam_periph_release(periph); return(EINVAL); } - if ((error = cam_periph_lock(periph, PCATCH)) != 0) { - crit_exit(); - return (error); - } - - crit_exit(); - if ((softc->flags & PASS_FLAG_OPEN) == 0) { - if (cam_periph_acquire(periph) != CAM_REQ_CMP) - return(ENXIO); softc->flags |= PASS_FLAG_OPEN; + } else { + /* Device closes aren't symmertical, so fix up the refcount */ + cam_periph_release(periph); } cam_periph_unlock(periph); @@ -397,7 +369,7 @@ passclose(struct dev_close_args *ap) cdev_t dev = ap->a_head.a_dev; struct cam_periph *periph; struct pass_softc *softc; - int unit, error; + int unit; /* unit = dkunit(dev); */ /* XXX KDM fix this */ @@ -407,11 +379,9 @@ passclose(struct dev_close_args *ap) if (periph == NULL) return (ENXIO); - softc = (struct pass_softc *)periph->softc; - - if ((error = cam_periph_lock(periph, 0)) != 0) - return (error); + cam_periph_lock(periph); + softc = (struct pass_softc *)periph->softc; softc->flags &= ~PASS_FLAG_OPEN; cam_periph_unlock(periph); @@ -429,12 +399,10 @@ passstart(struct cam_periph *periph, uni switch (softc->state) { case PASS_STATE_NORMAL: - crit_enter(); start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING; SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, periph_links.sle); periph->immediate_priority = CAM_PRIORITY_NONE; - crit_exit(); wakeup(&periph->ccb_list); break; } @@ -477,6 +445,7 @@ passioctl(struct dev_ioctl_args *ap) if (periph == NULL) return(ENXIO); + cam_periph_lock(periph); softc = (struct pass_softc *)periph->softc; error = 0; @@ -496,9 +465,9 @@ passioctl(struct dev_ioctl_args *ap) * through the transport layer device. */ if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) { - xpt_print_path(periph->path); - kprintf("CCB function code %#x is restricted to the " - "XPT device\n", inccb->ccb_h.func_code); + xpt_print(periph->path, "CCB function code %#x is " + "restricted to the XPT device\n", + inccb->ccb_h.func_code); error = ENODEV; break; } @@ -524,8 +493,7 @@ passioctl(struct dev_ioctl_args *ap) } if (ccb == NULL) { - xpt_print_path(periph->path); - kprintf("unable to allocate CCB\n"); + xpt_print(periph->path, "unable to allocate CCB\n"); error = ENOMEM; break; } @@ -544,6 +512,7 @@ passioctl(struct dev_ioctl_args *ap) break; } + cam_periph_unlock(periph); return(error); } @@ -592,7 +561,14 @@ passsendccb(struct cam_periph *periph, u bzero(&mapinfo, sizeof(mapinfo)); + /* + * cam_periph_mapmem calls into proc and vm functions that can + * sleep as well as trigger I/O, so we can't hold the lock. + * Dropping it here is reasonably safe. + */ + cam_periph_unlock(periph); error = cam_periph_mapmem(ccb, &mapinfo); + cam_periph_lock(periph); /* * cam_periph_mapmem returned an error, we can't continue.