summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/cam_ccb.h9
-rw-r--r--sys/cam/cam_periph.c131
-rw-r--r--sys/cam/cam_periph.h6
-rw-r--r--sys/cam/cam_sim.c59
-rw-r--r--sys/cam/cam_sim.h21
-rw-r--r--sys/cam/cam_xpt.c766
-rw-r--r--sys/cam/cam_xpt.h6
-rw-r--r--sys/cam/cam_xpt_periph.h4
-rw-r--r--sys/cam/scsi/scsi_cd.c438
-rw-r--r--sys/cam/scsi/scsi_ch.c69
-rw-r--r--sys/cam/scsi/scsi_da.c183
-rw-r--r--sys/cam/scsi/scsi_low.c4
-rw-r--r--sys/cam/scsi/scsi_pass.c58
-rw-r--r--sys/cam/scsi/scsi_pt.c95
-rw-r--r--sys/cam/scsi/scsi_sa.c118
-rw-r--r--sys/cam/scsi/scsi_ses.c53
-rw-r--r--sys/cam/scsi/scsi_sg.c57
-rw-r--r--sys/cam/scsi/scsi_targ_bh.c10
-rw-r--r--sys/cam/scsi/scsi_target.c80
-rw-r--r--sys/dev/aac/aac_cam.c2
-rw-r--r--sys/dev/advansys/advansys.c2
-rw-r--r--sys/dev/advansys/adwcam.c2
-rw-r--r--sys/dev/aha/aha.c4
-rw-r--r--sys/dev/ahb/ahb.c2
-rw-r--r--sys/dev/aic/aic.c5
-rw-r--r--sys/dev/aic7xxx/aic79xx_osm.c2
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c5
-rw-r--r--sys/dev/amd/amd.c5
-rw-r--r--sys/dev/amr/amr_cam.c1
-rw-r--r--sys/dev/arcmsr/arcmsr.c5
-rw-r--r--sys/dev/asr/asr.c3
-rw-r--r--sys/dev/ata/atapi-cam.c2
-rw-r--r--sys/dev/buslogic/bt.c2
-rw-r--r--sys/dev/ciss/ciss.c4
-rw-r--r--sys/dev/dpt/dpt_scsi.c3
-rw-r--r--sys/dev/esp/ncr53c9x.c2
-rw-r--r--sys/dev/firewire/sbp.c1
-rw-r--r--sys/dev/firewire/sbp_targ.c2
-rw-r--r--sys/dev/hptmv/entry.c3
-rw-r--r--sys/dev/iir/iir.c3
-rw-r--r--sys/dev/isp/isp_freebsd.c7
-rw-r--r--sys/dev/mly/mly.c2
-rw-r--r--sys/dev/mpt/mpt_cam.c12
-rw-r--r--sys/dev/ppbus/vpo.c4
-rw-r--r--sys/dev/rr232x/osm_bsd.c3
-rw-r--r--sys/dev/sym/sym_hipd.c2
-rw-r--r--sys/dev/trm/trm.c1
-rw-r--r--sys/dev/twa/tw_osl_cam.c2
-rw-r--r--sys/dev/usb/umass.c3
-rw-r--r--sys/dev/wds/wd7000.c3
-rw-r--r--sys/pci/ncr.c4
51 files changed, 1275 insertions, 995 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 7b3770d..33799fb 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -242,8 +242,7 @@ typedef union {
typedef union {
void *ptr;
u_long field;
- u_int8_t bytes[sizeof(void *) > sizeof(u_long)
- ? sizeof(void *) : sizeof(u_long)];
+ u_int8_t bytes[sizeof(uintptr_t)];
} ccb_priv_entry;
typedef union {
@@ -274,8 +273,12 @@ struct ccb_hdr {
ccb_ppriv_area periph_priv;
ccb_spriv_area sim_priv;
u_int32_t timeout; /* Timeout value */
+
+ /*
+ * Deprecated, only for use by non-MPSAFE SIMs. All others must
+ * allocate and initialize their own callout storage.
+ */
struct callout_handle timeout_ch;
- /* Callout handle used for timeouts */
};
/* Get Device Information CCB */
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 925e2a7..c0feec6 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_xpt_periph.h>
#include <cam/cam_periph.h>
#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
@@ -122,6 +123,7 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
ac_callback_t *ac_callback, ac_code code, void *arg)
{
struct periph_driver **p_drv;
+ struct cam_sim *sim;
struct cam_periph *periph;
struct cam_periph *cur_periph;
path_id_t path_id;
@@ -163,11 +165,14 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
init_level++;
+ xpt_lock_buses();
for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
if (strcmp((*p_drv)->driver_name, name) == 0)
break;
}
-
+ xpt_unlock_buses();
+
+ sim = xpt_path_sim(path);
path_id = xpt_path_path_id(path);
target_id = xpt_path_target_id(path);
lun_id = xpt_path_lun_id(path);
@@ -181,6 +186,7 @@ cam_periph_alloc(periph_ctor_t *periph_ctor,
periph->unit_number = camperiphunit(*p_drv, path_id, target_id, lun_id);
periph->immediate_priority = CAM_PRIORITY_NONE;
periph->refcount = 0;
+ periph->sim = sim;
SLIST_INIT(&periph->ccb_list);
status = xpt_create_path(&path, periph, path_id, target_id, lun_id);
if (status != CAM_REQ_CMP)
@@ -276,14 +282,13 @@ cam_periph_find(struct cam_path *path, char *name)
cam_status
cam_periph_acquire(struct cam_periph *periph)
{
- int s;
if (periph == NULL)
return(CAM_REQ_CMP_ERR);
- s = splsoftcam();
+ xpt_lock_buses();
periph->refcount++;
- splx(s);
+ xpt_unlock_buses();
return(CAM_REQ_CMP);
}
@@ -291,18 +296,66 @@ cam_periph_acquire(struct cam_periph *periph)
void
cam_periph_release(struct cam_periph *periph)
{
- int s;
if (periph == NULL)
return;
- s = splsoftcam();
+ xpt_lock_buses();
if ((--periph->refcount == 0)
&& (periph->flags & CAM_PERIPH_INVALID)) {
camperiphfree(periph);
}
- splx(s);
+ xpt_unlock_buses();
+
+}
+
+int
+cam_periph_hold(struct cam_periph *periph, int priority)
+{
+ struct mtx *mtx;
+ int error;
+
+ mtx_assert(periph->sim->mtx, MA_OWNED);
+
+ /*
+ * Increment the reference count on the peripheral
+ * while we wait for our lock attempt to succeed
+ * to ensure the peripheral doesn't disappear out
+ * from user us while we sleep.
+ */
+
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return (ENXIO);
+
+ mtx = periph->sim->mtx;
+ if (mtx == &Giant)
+ mtx = NULL;
+
+ while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
+ periph->flags |= CAM_PERIPH_LOCK_WANTED;
+ if ((error = msleep(periph, mtx, priority, "caplck", 0)) != 0) {
+ cam_periph_release(periph);
+ return (error);
+ }
+ }
+
+ periph->flags |= CAM_PERIPH_LOCKED;
+ return (0);
+}
+
+void
+cam_periph_unhold(struct cam_periph *periph)
+{
+
+ mtx_assert(periph->sim->mtx, MA_OWNED);
+
+ periph->flags &= ~CAM_PERIPH_LOCKED;
+ if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) {
+ periph->flags &= ~CAM_PERIPH_LOCK_WANTED;
+ wakeup(periph);
+ }
+ cam_periph_release(periph);
}
/*
@@ -424,9 +477,7 @@ camperiphunit(struct periph_driver *p_drv, path_id_t pathid,
void
cam_periph_invalidate(struct cam_periph *periph)
{
- int s;
- s = splsoftcam();
/*
* We only call this routine the first time a peripheral is
* invalidated. The oninvalidate() routine is always called at
@@ -439,11 +490,12 @@ cam_periph_invalidate(struct cam_periph *periph)
periph->flags |= CAM_PERIPH_INVALID;
periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
+ xpt_lock_buses();
if (periph->refcount == 0)
camperiphfree(periph);
else if (periph->refcount < 0)
printf("cam_invalidate_periph: refcount < 0!!\n");
- splx(s);
+ xpt_unlock_buses();
}
static void
@@ -502,30 +554,11 @@ camperiphfree(struct cam_periph *periph)
/*
* Wait interruptibly for an exclusive lock.
*/
-int
-cam_periph_lock(struct cam_periph *periph, int priority)
+void
+cam_periph_lock(struct cam_periph *periph)
{
- int error;
-
- /*
- * Increment the reference count on the peripheral
- * while we wait for our lock attempt to succeed
- * to ensure the peripheral doesn't disappear out
- * from under us while we sleep.
- */
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- return(ENXIO);
- while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
- periph->flags |= CAM_PERIPH_LOCK_WANTED;
- if ((error = tsleep(periph, priority, "caplck", 0)) != 0) {
- cam_periph_release(periph);
- return error;
- }
- }
-
- periph->flags |= CAM_PERIPH_LOCKED;
- return 0;
+ mtx_lock(periph->sim->mtx);
}
/*
@@ -534,13 +567,8 @@ cam_periph_lock(struct cam_periph *periph, int priority)
void
cam_periph_unlock(struct cam_periph *periph)
{
- periph->flags &= ~CAM_PERIPH_LOCKED;
- if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) {
- periph->flags &= ~CAM_PERIPH_LOCK_WANTED;
- wakeup(periph);
- }
- cam_periph_release(periph);
+ mtx_unlock(periph->sim->mtx);
}
/*
@@ -752,12 +780,11 @@ union ccb *
cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
{
struct ccb_hdr *ccb_h;
- int s;
+ struct mtx *mtx;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n"));
- s = splsoftcam();
-
while (SLIST_FIRST(&periph->ccb_list) == NULL) {
if (periph->immediate_priority > priority)
periph->immediate_priority = priority;
@@ -765,24 +792,35 @@ cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
if ((SLIST_FIRST(&periph->ccb_list) != NULL)
&& (SLIST_FIRST(&periph->ccb_list)->pinfo.priority == priority))
break;
- tsleep(&periph->ccb_list, PRIBIO, "cgticb", 0);
+ mtx_assert(periph->sim->mtx, MA_OWNED);
+ if (periph->sim->mtx == &Giant)
+ mtx = NULL;
+ else
+ mtx = periph->sim->mtx;
+ msleep(&periph->ccb_list, mtx, PRIBIO, "cgticb", 0);
}
ccb_h = SLIST_FIRST(&periph->ccb_list);
SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle);
- splx(s);
return ((union ccb *)ccb_h);
}
void
cam_periph_ccbwait(union ccb *ccb)
{
+ struct mtx *mtx;
+ struct cam_sim *sim;
int s;
s = splsoftcam();
+ sim = xpt_path_sim(ccb->ccb_h.path);
+ if (sim->mtx == &Giant)
+ mtx = NULL;
+ else
+ mtx = sim->mtx;
if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
|| ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
- tsleep(&ccb->ccb_h.cbfcnp, PRIBIO, "cbwait", 0);
+ msleep(&ccb->ccb_h.cbfcnp, mtx, PRIBIO, "cbwait", 0);
splx(s);
}
@@ -857,10 +895,13 @@ cam_periph_runccb(union ccb *ccb,
cam_flags camflags, u_int32_t sense_flags,
struct devstat *ds)
{
+ struct cam_sim *sim;
int error;
error = 0;
-
+ sim = xpt_path_sim(ccb->ccb_h.path);
+ mtx_assert(sim->mtx, MA_OWNED);
+
/*
* If the user has supplied a stats structure, and if we understand
* this particular type of ccb, record the transaction start.
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index c5d02fc..8a6c1eb 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -104,6 +104,7 @@ struct cam_periph {
char *periph_name;
struct cam_path *path; /* Compiled path to device */
void *softc;
+ struct cam_sim *sim;
u_int32_t unit_number;
cam_periph_type type;
u_int32_t flags;
@@ -113,6 +114,7 @@ struct cam_periph {
#define CAM_PERIPH_INVALID 0x08
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
#define CAM_PERIPH_RECOVERY_INPROG 0x20
+#define CAM_PERIPH_POLLED 0x40
u_int32_t immediate_priority;
u_int32_t refcount;
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
@@ -136,10 +138,12 @@ cam_status cam_periph_alloc(periph_ctor_t *periph_ctor,
char *name, cam_periph_type type, struct cam_path *,
ac_callback_t *, ac_code, void *arg);
struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
-int cam_periph_lock(struct cam_periph *periph, int priority);
+void cam_periph_lock(struct cam_periph *periph);
void cam_periph_unlock(struct cam_periph *periph);
cam_status cam_periph_acquire(struct cam_periph *periph);
void cam_periph_release(struct cam_periph *periph);
+int cam_periph_hold(struct cam_periph *periph, int priority);
+void cam_periph_unhold(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
int cam_periph_mapmem(union ccb *ccb,
struct cam_periph_map_info *mapinfo);
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index 322915f..cc8f86d 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -58,39 +60,42 @@ cam_simq_free(struct cam_devq *devq)
struct cam_sim *
cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
const char *sim_name, void *softc, u_int32_t unit,
- int max_dev_transactions,
+ struct mtx *mtx, int max_dev_transactions,
int max_tagged_dev_transactions, struct cam_devq *queue)
{
struct cam_sim *sim;
- /*
- * If this is the xpt layer creating a sim, then it's OK
- * to wait for an allocation.
- *
- * XXX Should we pass in a flag to indicate that wait is OK?
- */
- if (strcmp(sim_name, "xpt") == 0)
- sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
- M_CAMSIM, M_WAITOK);
- else
- sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
- M_CAMSIM, M_NOWAIT);
-
- if (sim != NULL) {
- sim->sim_action = sim_action;
- sim->sim_poll = sim_poll;
- sim->sim_name = sim_name;
- sim->softc = softc;
- sim->path_id = CAM_PATH_ANY;
- sim->unit_number = unit;
- sim->bus_id = 0; /* set in xpt_bus_register */
- sim->max_tagged_dev_openings = max_tagged_dev_transactions;
- sim->max_dev_openings = max_dev_transactions;
- sim->flags = 0;
- callout_handle_init(&sim->c_handle);
- sim->devq = queue;
+ if (mtx == NULL)
+ return (NULL);
+
+ sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
+ M_CAMSIM, M_NOWAIT);
+
+ if (sim == NULL)
+ return (NULL);
+
+ sim->sim_action = sim_action;
+ sim->sim_poll = sim_poll;
+ sim->sim_name = sim_name;
+ sim->softc = softc;
+ sim->path_id = CAM_PATH_ANY;
+ sim->unit_number = unit;
+ sim->bus_id = 0; /* set in xpt_bus_register */
+ sim->max_tagged_dev_openings = max_tagged_dev_transactions;
+ sim->max_dev_openings = max_dev_transactions;
+ sim->flags = 0;
+ sim->devq = queue;
+ sim->mtx = mtx;
+ if (mtx == &Giant) {
+ sim->flags |= 0;
+ callout_init(&sim->callout, 0);
+ } else {
+ sim->flags |= CAM_SIM_MPSAFE;
+ callout_init(&sim->callout, 1);
}
+ SLIST_INIT(&sim->ccb_freeq);
+
return (sim);
}
diff --git a/sys/cam/cam_sim.h b/sys/cam/cam_sim.h
index c4e3910..8976529 100644
--- a/sys/cam/cam_sim.h
+++ b/sys/cam/cam_sim.h
@@ -56,6 +56,7 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action,
const char *sim_name,
void *softc,
u_int32_t unit,
+ struct mtx *mtx,
int max_dev_transactions,
int max_tagged_dev_transactions,
struct cam_devq *queue);
@@ -90,17 +91,33 @@ struct cam_sim {
sim_poll_func sim_poll;
const char *sim_name;
void *softc;
+ struct mtx *mtx;
u_int32_t path_id;/* The Boot device may set this to 0? */
u_int32_t unit_number;
u_int32_t bus_id;
int max_tagged_dev_openings;
int max_dev_openings;
u_int32_t flags;
-#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
- struct callout_handle c_handle;
+#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
+#define CAM_SIM_MPSAFE 0x02
+ struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
+
+ /* "Pool" of inactive ccbs managed by xpt_alloc_ccb and xpt_free_ccb */
+ SLIST_HEAD(,ccb_hdr) ccb_freeq;
+ /*
+ * Maximum size of ccb pool. Modified as devices are added/removed
+ * or have their * opening counts changed.
+ */
+ u_int max_ccbs;
+ /* Current count of allocated ccbs */
+ u_int ccb_count;
+
};
+#define CAM_SIM_LOCK(sim) mtx_lock((sim)->mtx);
+#define CAM_SIM_UNLOCK(sim) mtx_unlock((sim)->mtx);
+
static __inline u_int32_t
cam_sim_path(struct cam_sim *sim)
{
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index c123b5c..d13209e 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/md5.h>
#include <sys/interrupt.h>
#include <sys/sbuf.h>
+#include <sys/taskqueue.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -70,6 +71,12 @@ __FBSDID("$FreeBSD$");
/* Datastructures internal to the xpt layer */
MALLOC_DEFINE(M_CAMXPT, "CAM XPT", "CAM XPT buffers");
+/* Object for defering XPT actions to a taskqueue */
+struct xpt_task {
+ struct task task;
+ void *data;
+};
+
/*
* Definition of an async handler callback block. These are used to add
* SIMs and peripherals to the async callback lists.
@@ -84,7 +91,6 @@ struct async_node {
SLIST_HEAD(async_list, async_node);
SLIST_HEAD(periph_list, cam_periph);
-static STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;
/*
* This is the maximum number of high powered commands (e.g. start unit)
@@ -94,9 +100,6 @@ static STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;
#define CAM_MAX_HIGHPOWER 4
#endif
-/* number of high powered commands that can go through right now */
-static int num_highpower = CAM_MAX_HIGHPOWER;
-
/*
* Structure for queueing a device in a run queue.
* There is one run queue for allocating new ccbs,
@@ -117,6 +120,7 @@ struct cam_ed {
struct cam_ed_qinfo alloc_ccb_entry;
struct cam_ed_qinfo send_ccb_entry;
struct cam_et *target;
+ struct cam_sim *sim;
lun_id_t lun_id;
struct camq drvq; /*
* Queue of type drivers wanting to do
@@ -158,7 +162,7 @@ struct cam_ed {
#define CAM_TAG_DELAY_COUNT 5
u_int32_t tag_saved_openings;
u_int32_t refcount;
- struct callout_handle c_handle;
+ struct callout callout;
};
/*
@@ -242,8 +246,24 @@ typedef enum {
} xpt_flags;
struct xpt_softc {
- xpt_flags flags;
- u_int32_t generation;
+ xpt_flags flags;
+ u_int32_t xpt_generation;
+
+ /* number of high powered commands that can go through right now */
+ STAILQ_HEAD(highpowerlist, ccb_hdr) highpowerq;
+ int num_highpower;
+
+ /* queue for handling async rescan requests. */
+ TAILQ_HEAD(, ccb_hdr) ccb_scanq;
+
+ /* Registered busses */
+ TAILQ_HEAD(,cam_eb) xpt_busses;
+ u_int bus_generation;
+
+ struct intr_config_hook *xpt_config_hook;
+
+ struct mtx xpt_topo_lock;
+ struct mtx xpt_lock;
};
static const char quantum[] = "QUANTUM";
@@ -647,14 +667,8 @@ typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
static cam_isrq_t cam_bioq;
static struct mtx cam_bioq_lock;
-/* "Pool" of inactive ccbs managed by xpt_alloc_ccb and xpt_free_ccb */
-static SLIST_HEAD(,ccb_hdr) ccb_freeq;
-static u_int xpt_max_ccbs; /*
- * Maximum size of ccb pool. Modified as
- * devices are added/removed or have their
- * opening counts changed.
- */
-static u_int xpt_ccb_count; /* Current count of allocated ccbs */
+/* Pointers to software interrupt handlers */
+static void *cambio_ih;
struct cam_periph *xpt_periph;
@@ -684,14 +698,13 @@ static d_ioctl_t xptioctl;
static struct cdevsw xpt_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
.d_open = xptopen,
.d_close = xptclose,
.d_ioctl = xptioctl,
.d_name = "xpt",
};
-static struct intr_config_hook *xpt_config_hook;
static void dead_sim_action(struct cam_sim *sim, union ccb *ccb);
static void dead_sim_poll(struct cam_sim *sim);
@@ -705,9 +718,6 @@ static struct cam_sim cam_dead_sim = {
#define SIM_DEAD(sim) ((sim) == &cam_dead_sim)
-/* Registered busses */
-static TAILQ_HEAD(,cam_eb) xpt_busses;
-static u_int bus_generation;
/* Storage for debugging datastructures */
#ifdef CAMDEBUG
@@ -716,9 +726,6 @@ u_int32_t cam_dflags;
u_int32_t cam_debug_delay;
#endif
-/* Pointers to software interrupt handlers */
-static void *cambio_ih;
-
#if defined(CAM_DEBUG_FLAGS) && !defined(CAMDEBUG)
#error "You must have options CAMDEBUG to use options CAM_DEBUG_FLAGS"
#endif
@@ -750,7 +757,7 @@ static moduledata_t cam_moduledata = {
NULL
};
-static void xpt_init(void *);
+static int xpt_init(void *);
DECLARE_MODULE(cam, cam_moduledata, SI_SUB_CONFIGURE, SI_ORDER_SECOND);
MODULE_VERSION(cam, 1);
@@ -781,7 +788,7 @@ static int xpt_schedule_dev(struct camq *queue, cam_pinfo *dev_pinfo,
static void xpt_run_dev_allocq(struct cam_eb *bus);
static void xpt_run_dev_sendq(struct cam_eb *bus);
static timeout_t xpt_release_devq_timeout;
-static timeout_t xpt_release_simq_timeout;
+static void xpt_release_simq_timeout(void *arg) __unused;
static void xpt_release_bus(struct cam_eb *bus);
static void xpt_release_devq_device(struct cam_ed *dev, u_int count,
int run_queue);
@@ -813,11 +820,6 @@ static void xpt_finishconfig(struct cam_periph *periph, union ccb *ccb);
static void xptaction(struct cam_sim *sim, union ccb *work_ccb);
static void xptpoll(struct cam_sim *sim);
static void camisr(void *);
-#if 0
-static void xptstart(struct cam_periph *periph, union ccb *work_ccb);
-static void xptasync(struct cam_periph *periph,
- u_int32_t code, cam_path *path);
-#endif
static dev_match_ret xptbusmatch(struct dev_match_pattern *patterns,
u_int num_patterns, struct cam_eb *bus);
static dev_match_ret xptdevicematch(struct dev_match_pattern *patterns,
@@ -856,16 +858,8 @@ static xpt_targetfunc_t xptdeftargetfunc;
static xpt_devicefunc_t xptdefdevicefunc;
static xpt_periphfunc_t xptdefperiphfunc;
static int xpt_for_all_busses(xpt_busfunc_t *tr_func, void *arg);
-#ifdef notusedyet
-static int xpt_for_all_targets(xpt_targetfunc_t *tr_func,
- void *arg);
-#endif
static int xpt_for_all_devices(xpt_devicefunc_t *tr_func,
void *arg);
-#ifdef notusedyet
-static int xpt_for_all_periphs(xpt_periphfunc_t *tr_func,
- void *arg);
-#endif
static xpt_devicefunc_t xptsetasyncfunc;
static xpt_busfunc_t xptsetasyncbusfunc;
static cam_status xptregister(struct cam_periph *periph,
@@ -996,9 +990,6 @@ xptdone(struct cam_periph *periph, union ccb *done_ccb)
static int
xptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
- int unit;
-
- unit = minor(dev) & 0xff;
/*
* Only allow read-write access.
@@ -1010,22 +1001,14 @@ xptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
* We don't allow nonblocking access.
*/
if ((flags & O_NONBLOCK) != 0) {
- printf("xpt%d: can't do nonblocking access\n", unit);
+ printf("%s: can't do nonblocking access\n", devtoname(dev));
return(ENODEV);
}
- /*
- * We only have one transport layer right now. If someone accesses
- * us via something other than minor number 1, point out their
- * mistake.
- */
- if (unit != 0) {
- printf("xptopen: got invalid xpt unit %d\n", unit);
- return(ENXIO);
- }
-
/* Mark ourselves open */
+ mtx_lock(&xsoftc.xpt_lock);
xsoftc.flags |= XPT_FLAG_OPEN;
+ mtx_unlock(&xsoftc.xpt_lock);
return(0);
}
@@ -1033,43 +1016,27 @@ xptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
static int
xptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
- int unit;
-
- unit = minor(dev) & 0xff;
-
- /*
- * We only have one transport layer right now. If someone accesses
- * us via something other than minor number 1, point out their
- * mistake.
- */
- if (unit != 0) {
- printf("xptclose: got invalid xpt unit %d\n", unit);
- return(ENXIO);
- }
/* Mark ourselves closed */
+ mtx_lock(&xsoftc.xpt_lock);
xsoftc.flags &= ~XPT_FLAG_OPEN;
+ mtx_unlock(&xsoftc.xpt_lock);
return(0);
}
+/*
+ * Don't automatically grab the xpt softc lock here even though this is going
+ * through the xpt device. The xpt device is really just a back door for
+ * accessing other devices and SIMs, so the right thing to do is to grab
+ * the appropriate SIM lock once the bus/SIM is located.
+ */
static int
xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
- int unit, error;
+ int error;
error = 0;
- unit = minor(dev) & 0xff;
-
- /*
- * We only have one transport layer right now. If someone accesses
- * us via something other than minor number 1, point out their
- * mistake.
- */
- if (unit != 0) {
- printf("xptioctl: got invalid xpt unit %d\n", unit);
- return(ENXIO);
- }
switch(cmd) {
/*
@@ -1081,9 +1048,16 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
case CAMIOCOMMAND: {
union ccb *ccb;
union ccb *inccb;
+ struct cam_eb *bus;
inccb = (union ccb *)addr;
+ bus = xpt_find_bus(inccb->ccb_h.path_id);
+ if (bus == NULL) {
+ error = EINVAL;
+ break;
+ }
+
switch(inccb->ccb_h.func_code) {
case XPT_SCAN_BUS:
case XPT_RESET_BUS:
@@ -1097,7 +1071,9 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
case XPT_ENG_INQ:
case XPT_SCAN_LUN:
- ccb = xpt_alloc_ccb();
+ ccb = xpt_alloc_ccb(bus->sim);
+
+ CAM_SIM_LOCK(bus->sim);
/*
* Create a path using the bus, target, and lun the
@@ -1109,6 +1085,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
inccb->ccb_h.target_lun) !=
CAM_REQ_CMP){
error = EINVAL;
+ CAM_SIM_UNLOCK(bus->sim);
xpt_free_ccb(ccb);
break;
}
@@ -1121,6 +1098,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
bcopy(ccb, inccb, sizeof(union ccb));
xpt_free_path(ccb->ccb_h.path);
xpt_free_ccb(ccb);
+ CAM_SIM_UNLOCK(bus->sim);
break;
case XPT_DEBUG: {
@@ -1131,6 +1109,8 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
* allocate it on the stack.
*/
+ CAM_SIM_LOCK(bus->sim);
+
/*
* Create a path using the bus, target, and lun the
* user passed in.
@@ -1149,6 +1129,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
xpt_merge_ccb(&ccb, inccb);
ccb.ccb_h.cbfcnp = xptdone;
xpt_action(&ccb);
+ CAM_SIM_UNLOCK(bus->sim);
bcopy(&ccb, inccb, sizeof(union ccb));
xpt_free_path(ccb.ccb_h.path);
break;
@@ -1268,7 +1249,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td
/* Keep the list from changing while we traverse it */
s = splcam();
ptstartover:
- cur_generation = xsoftc.generation;
+ cur_generation = xsoftc.xpt_generation;
/* first find our driver in the list of drivers */
for (p_drv = periph_drivers; *p_drv != NULL; p_drv++)
@@ -1301,7 +1282,7 @@ ptstartover:
splx(s);
s = splcam();
splbreaknum = 100;
- if (cur_generation != xsoftc.generation)
+ if (cur_generation != xsoftc.xpt_generation)
goto ptstartover;
}
}
@@ -1402,11 +1383,16 @@ ptstartover:
static int
cam_module_event_handler(module_t mod, int what, void *arg)
{
- if (what == MOD_LOAD) {
- xpt_init(NULL);
- } else if (what == MOD_UNLOAD) {
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ if ((error = xpt_init(NULL)) != 0)
+ return (error);
+ break;
+ case MOD_UNLOAD:
return EBUSY;
- } else {
+ default:
return EOPNOTSUPP;
}
@@ -1414,22 +1400,40 @@ cam_module_event_handler(module_t mod, int what, void *arg)
}
/* thread to handle bus rescans */
-static TAILQ_HEAD(, ccb_hdr) ccb_scanq;
static void
xpt_scanner_thread(void *dummy)
{
- mtx_lock(&Giant);
+ cam_isrq_t queue;
+ union ccb *ccb;
+ struct cam_sim *sim;
+
for (;;) {
- union ccb *ccb;
- tsleep(&ccb_scanq, PRIBIO, "ccb_scanq", 0);
- while ((ccb = (union ccb *)TAILQ_FIRST(&ccb_scanq)) != NULL) {
- TAILQ_REMOVE(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+ /*
+ * Wait for a rescan request to come in. When it does, splice
+ * it onto a queue from local storage so that the xpt lock
+ * doesn't need to be held while the requests are being
+ * processed.
+ */
+ xpt_lock_buses();
+ msleep(&xsoftc.ccb_scanq, &xsoftc.xpt_topo_lock, PRIBIO,
+ "ccb_scanq", 0);
+ TAILQ_INIT(&queue);
+ TAILQ_CONCAT(&queue, &xsoftc.ccb_scanq, sim_links.tqe);
+ xpt_unlock_buses();
+
+ while ((ccb = (union ccb *)TAILQ_FIRST(&queue)) != NULL) {
+ TAILQ_REMOVE(&queue, &ccb->ccb_h, sim_links.tqe);
+
+ sim = ccb->ccb_h.path->bus->sim;
+ mtx_lock(sim->mtx);
+
ccb->ccb_h.func_code = XPT_SCAN_BUS;
ccb->ccb_h.cbfcnp = xptdone;
xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5);
cam_periph_runccb(ccb, NULL, 0, 0, NULL);
xpt_free_path(ccb->ccb_h.path);
xpt_free_ccb(ccb);
+ mtx_unlock(sim->mtx);
}
}
}
@@ -1438,24 +1442,27 @@ void
xpt_rescan(union ccb *ccb)
{
struct ccb_hdr *hdr;
- GIANT_REQUIRED;
+
/*
* Don't make duplicate entries for the same paths.
*/
- TAILQ_FOREACH(hdr, &ccb_scanq, sim_links.tqe) {
+ xpt_lock_buses();
+ TAILQ_FOREACH(hdr, &xsoftc.ccb_scanq, sim_links.tqe) {
if (xpt_path_comp(hdr->path, ccb->ccb_h.path) == 0) {
+ xpt_unlock_buses();
xpt_print(ccb->ccb_h.path, "rescan already queued\n");
xpt_free_path(ccb->ccb_h.path);
xpt_free_ccb(ccb);
return;
}
}
- TAILQ_INSERT_TAIL(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
- wakeup(&ccb_scanq);
+ TAILQ_INSERT_TAIL(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+ wakeup(&xsoftc.ccb_scanq);
+ xpt_unlock_buses();
}
/* Functions accessed by the peripheral drivers */
-static void
+static int
xpt_init(void *dummy)
{
struct cam_sim *xpt_sim;
@@ -1463,13 +1470,15 @@ xpt_init(void *dummy)
struct cam_devq *devq;
cam_status status;
- TAILQ_INIT(&xpt_busses);
+ TAILQ_INIT(&xsoftc.xpt_busses);
TAILQ_INIT(&cam_bioq);
- SLIST_INIT(&ccb_freeq);
- TAILQ_INIT(&ccb_scanq);
- STAILQ_INIT(&highpowerq);
+ TAILQ_INIT(&xsoftc.ccb_scanq);
+ STAILQ_INIT(&xsoftc.highpowerq);
+ xsoftc.num_highpower = CAM_MAX_HIGHPOWER;
mtx_init(&cam_bioq_lock, "CAM BIOQ lock", NULL, MTX_DEF);
+ mtx_init(&xsoftc.xpt_lock, "XPT lock", NULL, MTX_DEF);
+ mtx_init(&xsoftc.xpt_topo_lock, "XPT topology lock", NULL, MTX_DEF);
/*
* The xpt layer is, itself, the equivelent of a SIM.
@@ -1483,15 +1492,20 @@ xpt_init(void *dummy)
"xpt",
/*softc*/NULL,
/*unit*/0,
+ /*mtx*/&xsoftc.xpt_lock,
/*max_dev_transactions*/0,
/*max_tagged_dev_transactions*/0,
devq);
- xpt_max_ccbs = 16;
-
+ if (xpt_sim == NULL)
+ return (ENOMEM);
+
+ xpt_sim->max_ccbs = 16;
+
+ mtx_lock(&xsoftc.xpt_lock);
if ((status = xpt_bus_register(xpt_sim, /*bus #*/0)) != CAM_SUCCESS) {
printf("xpt_init: xpt_bus_register failed with status %#x,"
" failing attach\n", status);
- return;
+ return (EINVAL);
}
/*
@@ -1504,30 +1518,29 @@ xpt_init(void *dummy)
CAM_LUN_WILDCARD)) != CAM_REQ_CMP) {
printf("xpt_init: xpt_create_path failed with status %#x,"
" failing attach\n", status);
- return;
+ return (EINVAL);
}
cam_periph_alloc(xptregister, NULL, NULL, NULL, "xpt", CAM_PERIPH_BIO,
- path, NULL, 0, NULL);
+ path, NULL, 0, xpt_sim);
xpt_free_path(path);
-
- xpt_sim->softc = xpt_periph;
+ mtx_unlock(&xsoftc.xpt_lock);
/*
* Register a callback for when interrupts are enabled.
*/
- xpt_config_hook =
+ xsoftc.xpt_config_hook =
(struct intr_config_hook *)malloc(sizeof(struct intr_config_hook),
M_TEMP, M_NOWAIT | M_ZERO);
- if (xpt_config_hook == NULL) {
+ if (xsoftc.xpt_config_hook == NULL) {
printf("xpt_init: Cannot malloc config hook "
"- failing attach\n");
- return;
+ return (ENOMEM);
}
- xpt_config_hook->ich_func = xpt_config;
- if (config_intrhook_establish(xpt_config_hook) != 0) {
- free (xpt_config_hook, M_TEMP);
+ xsoftc.xpt_config_hook->ich_func = xpt_config;
+ if (config_intrhook_establish(xsoftc.xpt_config_hook) != 0) {
+ free (xsoftc.xpt_config_hook, M_TEMP);
printf("xpt_init: config_intrhook_establish failed "
"- failing attach\n");
}
@@ -1537,20 +1550,25 @@ xpt_init(void *dummy)
printf("xpt_init: failed to create rescan thread\n");
}
/* Install our software interrupt handlers */
- swi_add(NULL, "cambio", camisr, &cam_bioq, SWI_CAMBIO, 0, &cambio_ih);
+ swi_add(NULL, "cambio", camisr, &cam_bioq, SWI_CAMBIO, INTR_MPSAFE, &cambio_ih);
+
+ return (0);
}
static cam_status
xptregister(struct cam_periph *periph, void *arg)
{
+ struct cam_sim *xpt_sim;
+
if (periph == NULL) {
printf("xptregister: periph was NULL!!\n");
return(CAM_REQ_CMP_ERR);
}
- periph->softc = NULL;
-
+ xpt_sim = (struct cam_sim *)arg;
+ xpt_sim->softc = periph;
xpt_periph = periph;
+ periph->softc = NULL;
return(CAM_REQ_CMP);
}
@@ -1562,7 +1580,7 @@ xpt_add_periph(struct cam_periph *periph)
int32_t status;
struct periph_list *periph_head;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
device = periph->path->device;
@@ -1589,7 +1607,7 @@ xpt_add_periph(struct cam_periph *periph)
splx(s);
}
- xsoftc.generation++;
+ atomic_add_int(&xsoftc.xpt_generation, 1);
return (status);
}
@@ -1599,7 +1617,7 @@ xpt_remove_periph(struct cam_periph *periph)
{
struct cam_ed *device;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
device = periph->path->device;
@@ -1620,7 +1638,7 @@ xpt_remove_periph(struct cam_periph *periph)
splx(s);
}
- xsoftc.generation++;
+ atomic_add_int(&xsoftc.xpt_generation, 1);
}
@@ -1636,7 +1654,7 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
u_int mb;
int s;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
path = periph->path;
/*
@@ -2147,7 +2165,7 @@ xptedtbusfunc(struct cam_eb *bus, void *arg)
cdm->pos.cookie.bus = bus;
cdm->pos.generations[CAM_BUS_GENERATION]=
- bus_generation;
+ xsoftc.bus_generation;
cdm->status = CAM_DEV_MATCH_MORE;
return(0);
}
@@ -2279,7 +2297,7 @@ xptedtdevicefunc(struct cam_ed *device, void *arg)
cdm->pos.cookie.bus = device->target->bus;
cdm->pos.generations[CAM_BUS_GENERATION]=
- bus_generation;
+ xsoftc.bus_generation;
cdm->pos.cookie.target = device->target;
cdm->pos.generations[CAM_TARGET_GENERATION] =
device->target->bus->generation;
@@ -2389,7 +2407,7 @@ xptedtperiphfunc(struct cam_periph *periph, void *arg)
cdm->pos.cookie.bus = periph->path->bus;
cdm->pos.generations[CAM_BUS_GENERATION]=
- bus_generation;
+ xsoftc.bus_generation;
cdm->pos.cookie.target = periph->path->target;
cdm->pos.generations[CAM_TARGET_GENERATION] =
periph->path->bus->generation;
@@ -2434,7 +2452,7 @@ xptedtmatch(struct ccb_dev_match *cdm)
*/
if ((cdm->pos.position_type & CAM_DEV_POS_BUS)
&& (cdm->pos.generations[CAM_BUS_GENERATION] != 0)
- && (cdm->pos.generations[CAM_BUS_GENERATION] != bus_generation)) {
+ && (cdm->pos.generations[CAM_BUS_GENERATION] != xsoftc.bus_generation)) {
cdm->status = CAM_DEV_MATCH_LIST_CHANGED;
return(0);
}
@@ -2633,15 +2651,21 @@ xptbustraverse(struct cam_eb *start_bus, xpt_busfunc_t *tr_func, void *arg)
retval = 1;
- for (bus = (start_bus ? start_bus : TAILQ_FIRST(&xpt_busses));
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ for (bus = (start_bus ? start_bus : TAILQ_FIRST(&xsoftc.xpt_busses));
bus != NULL;
bus = next_bus) {
next_bus = TAILQ_NEXT(bus, links);
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ mtx_lock(bus->sim->mtx);
retval = tr_func(bus, arg);
+ mtx_unlock(bus->sim->mtx);
if (retval == 0)
return(retval);
+ mtx_lock(&xsoftc.xpt_topo_lock);
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
return(retval);
}
@@ -2852,23 +2876,6 @@ xpt_for_all_busses(xpt_busfunc_t *tr_func, void *arg)
return(xptbustraverse(NULL, xptdefbusfunc, &tr_config));
}
-#ifdef notusedyet
-/*
- * Execute the given function for every target in the EDT.
- */
-static int
-xpt_for_all_targets(xpt_targetfunc_t *tr_func, void *arg)
-{
- struct xpt_traverse_config tr_config;
-
- tr_config.depth = XPT_DEPTH_TARGET;
- tr_config.tr_func = tr_func;
- tr_config.tr_arg = arg;
-
- return(xptbustraverse(NULL, xptdefbusfunc, &tr_config));
-}
-#endif /* notusedyet */
-
/*
* Execute the given function for every device in the EDT.
*/
@@ -2884,23 +2891,6 @@ xpt_for_all_devices(xpt_devicefunc_t *tr_func, void *arg)
return(xptbustraverse(NULL, xptdefbusfunc, &tr_config));
}
-#ifdef notusedyet
-/*
- * Execute the given function for every peripheral in the EDT.
- */
-static int
-xpt_for_all_periphs(xpt_periphfunc_t *tr_func, void *arg)
-{
- struct xpt_traverse_config tr_config;
-
- tr_config.depth = XPT_DEPTH_PERIPH;
- tr_config.tr_func = tr_func;
- tr_config.tr_arg = arg;
-
- return(xptbustraverse(NULL, xptdefbusfunc, &tr_config));
-}
-#endif /* notusedyet */
-
static int
xptsetasyncfunc(struct cam_ed *device, void *arg)
{
@@ -2959,13 +2949,93 @@ xptsetasyncbusfunc(struct cam_eb *bus, void *arg)
return(1);
}
+static void
+xpt_action_sasync_cb(void *context, int pending)
+{
+ union ccb *start_ccb;
+ struct xpt_task *task;
+ struct ccb_setasync *csa;
+ struct async_node *cur_entry;
+ struct async_list *async_head;
+ u_int32_t added;
+ int s;
+
+ task = (struct xpt_task *)context;
+ start_ccb = (union ccb *)task->data;
+ csa = &start_ccb->csa;
+ added = csa->event_enable;
+ async_head = &csa->ccb_h.path->device->asyncs;
+
+ /*
+ * If there is already an entry for us, simply
+ * update it.
+ */
+ s = splcam();
+ mtx_lock(csa->ccb_h.path->bus->sim->mtx);
+ cur_entry = SLIST_FIRST(async_head);
+ while (cur_entry != NULL) {
+ if ((cur_entry->callback_arg == csa->callback_arg)
+ && (cur_entry->callback == csa->callback))
+ break;
+ cur_entry = SLIST_NEXT(cur_entry, links);
+ }
+
+ if (cur_entry != NULL) {
+ /*
+ * If the request has no flags set,
+ * remove the entry.
+ */
+ added &= ~cur_entry->event_enable;
+ if (csa->event_enable == 0) {
+ SLIST_REMOVE(async_head, cur_entry,
+ async_node, links);
+ csa->ccb_h.path->device->refcount--;
+ free(cur_entry, M_CAMXPT);
+ } else {
+ cur_entry->event_enable = csa->event_enable;
+ }
+ } else {
+ cur_entry = malloc(sizeof(*cur_entry), M_CAMXPT,
+ M_NOWAIT);
+ if (cur_entry == NULL) {
+ splx(s);
+ goto out;
+ }
+ cur_entry->event_enable = csa->event_enable;
+ cur_entry->callback_arg = csa->callback_arg;
+ cur_entry->callback = csa->callback;
+ SLIST_INSERT_HEAD(async_head, cur_entry, links);
+ csa->ccb_h.path->device->refcount++;
+ }
+ mtx_unlock(csa->ccb_h.path->bus->sim->mtx);
+
+ if ((added & AC_FOUND_DEVICE) != 0) {
+ /*
+ * Get this peripheral up to date with all
+ * the currently existing devices.
+ */
+ xpt_for_all_devices(xptsetasyncfunc, cur_entry);
+ }
+ if ((added & AC_PATH_REGISTERED) != 0) {
+ /*
+ * Get this peripheral up to date with all
+ * the currently existing busses.
+ */
+ xpt_for_all_busses(xptsetasyncbusfunc, cur_entry);
+ }
+ splx(s);
+
+out:
+ xpt_free_path(start_ccb->ccb_h.path);
+ xpt_free_ccb(start_ccb);
+ free(task, M_CAMXPT);
+}
+
void
xpt_action(union ccb *start_ccb)
{
int iopl;
- GIANT_REQUIRED;
-
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action\n"));
start_ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -3363,73 +3433,42 @@ xpt_action(union ccb *start_ccb)
}
case XPT_SASYNC_CB:
{
- struct ccb_setasync *csa;
- struct async_node *cur_entry;
- struct async_list *async_head;
- u_int32_t added;
- int s;
-
- csa = &start_ccb->csa;
- added = csa->event_enable;
- async_head = &csa->ccb_h.path->device->asyncs;
+ union ccb *task_ccb;
+ struct xpt_task *task;
/*
- * If there is already an entry for us, simply
- * update it.
+ * Need to decouple this operation via a taqskqueue so that
+ * the locking doesn't become a mess. Clone the ccb so that
+ * we own the memory and can free it later.
*/
- s = splcam();
- cur_entry = SLIST_FIRST(async_head);
- while (cur_entry != NULL) {
- if ((cur_entry->callback_arg == csa->callback_arg)
- && (cur_entry->callback == csa->callback))
- break;
- cur_entry = SLIST_NEXT(cur_entry, links);
+ task_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT);
+ if (task_ccb == NULL) {
+ start_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ break;
}
-
- if (cur_entry != NULL) {
- /*
- * If the request has no flags set,
- * remove the entry.
- */
- added &= ~cur_entry->event_enable;
- if (csa->event_enable == 0) {
- SLIST_REMOVE(async_head, cur_entry,
- async_node, links);
- csa->ccb_h.path->device->refcount--;
- free(cur_entry, M_CAMXPT);
- } else {
- cur_entry->event_enable = csa->event_enable;
- }
- } else {
- cur_entry = malloc(sizeof(*cur_entry), M_CAMXPT,
- M_NOWAIT);
- if (cur_entry == NULL) {
- splx(s);
- csa->ccb_h.status = CAM_RESRC_UNAVAIL;
- break;
- }
- cur_entry->event_enable = csa->event_enable;
- cur_entry->callback_arg = csa->callback_arg;
- cur_entry->callback = csa->callback;
- SLIST_INSERT_HEAD(async_head, cur_entry, links);
- csa->ccb_h.path->device->refcount++;
+ bcopy(start_ccb, task_ccb, sizeof(union ccb));
+ if (xpt_create_path(&task_ccb->ccb_h.path, NULL,
+ start_ccb->ccb_h.path_id,
+ start_ccb->ccb_h.target_id,
+ start_ccb->ccb_h.target_lun) !=
+ CAM_REQ_CMP) {
+ start_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_free_ccb(task_ccb);
+ break;
}
- if ((added & AC_FOUND_DEVICE) != 0) {
- /*
- * Get this peripheral up to date with all
- * the currently existing devices.
- */
- xpt_for_all_devices(xptsetasyncfunc, cur_entry);
- }
- if ((added & AC_PATH_REGISTERED) != 0) {
- /*
- * Get this peripheral up to date with all
- * the currently existing busses.
- */
- xpt_for_all_busses(xptsetasyncbusfunc, cur_entry);
+ task = malloc(sizeof(struct xpt_task), M_CAMXPT, M_NOWAIT);
+ if (task == NULL) {
+ start_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_free_path(task_ccb->ccb_h.path);
+ xpt_free_ccb(task_ccb);
+ break;
}
- splx(s);
+
+ TASK_INIT(&task->task, 0, xpt_action_sasync_cb, task);
+ task->data = task_ccb;
+ taskqueue_enqueue(taskqueue_thread, &task->task);
+
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@@ -3476,17 +3515,15 @@ xpt_action(union ccb *start_ccb)
* is sufficient for releasing the queue.
*/
start_ccb->ccb_h.flags &= ~CAM_DEV_QFREEZE;
- untimeout(xpt_release_devq_timeout,
- dev, dev->c_handle);
+ callout_stop(&dev->callout);
} else {
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
}
- dev->c_handle =
- timeout(xpt_release_devq_timeout,
- dev,
- (crs->release_timeout * hz) / 1000);
+ callout_reset(&dev->callout,
+ (crs->release_timeout * hz) / 1000,
+ xpt_release_devq_timeout, dev);
dev->flags |= CAM_DEV_REL_TIMEOUT_PENDING;
@@ -3601,13 +3638,13 @@ xpt_polled_action(union ccb *start_ccb)
struct cam_devq *devq;
struct cam_ed *dev;
- GIANT_REQUIRED;
timeout = start_ccb->ccb_h.timeout;
sim = start_ccb->ccb_h.path->bus->sim;
devq = sim->devq;
dev = start_ccb->ccb_h.path->device;
+ mtx_assert(sim->mtx, MA_OWNED);
s = splcam();
/*
@@ -3664,7 +3701,7 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
int s;
int runq;
- GIANT_REQUIRED;
+ mtx_assert(perph->sim->mtx, MA_OWNED);
CAM_DEBUG(perph->path, CAM_DEBUG_TRACE, ("xpt_schedule\n"));
device = perph->path->device;
@@ -3885,7 +3922,8 @@ xpt_run_dev_sendq(struct cam_eb *bus)
if ((work_ccb->ccb_h.flags & CAM_HIGH_POWER) != 0) {
- if (num_highpower <= 0) {
+ mtx_lock(&xsoftc.xpt_lock);
+ if (xsoftc.num_highpower <= 0) {
/*
* We got a high power command, but we
* don't have any available slots. Freeze
@@ -3893,7 +3931,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
* available.
*/
device->qfrozen_cnt++;
- STAILQ_INSERT_TAIL(&highpowerq,
+ STAILQ_INSERT_TAIL(&xsoftc.highpowerq,
&work_ccb->ccb_h,
xpt_links.stqe);
@@ -3904,8 +3942,9 @@ xpt_run_dev_sendq(struct cam_eb *bus)
* Consume a high power slot while
* this ccb runs.
*/
- num_highpower--;
+ xsoftc.num_highpower--;
}
+ mtx_unlock(&xsoftc.xpt_lock);
}
devq->active_dev = device;
cam_ccbq_remove_ccb(&device->ccbq, work_ccb);
@@ -3972,7 +4011,6 @@ xpt_run_dev_sendq(struct cam_eb *bus)
void
xpt_merge_ccb(union ccb *master_ccb, union ccb *slave_ccb)
{
- GIANT_REQUIRED;
/*
* Pull fields that are valid for peripheral drivers to set
@@ -3989,7 +4027,6 @@ xpt_merge_ccb(union ccb *master_ccb, union ccb *slave_ccb)
void
xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
{
- GIANT_REQUIRED;
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_setup_ccb\n"));
ccb_h->pinfo.priority = priority;
@@ -4017,8 +4054,6 @@ xpt_create_path(struct cam_path **new_path_ptr, struct cam_periph *perph,
struct cam_path *path;
cam_status status;
- GIANT_REQUIRED;
-
path = (struct cam_path *)malloc(sizeof(*path), M_CAMXPT, M_NOWAIT);
if (path == NULL) {
@@ -4034,6 +4069,36 @@ xpt_create_path(struct cam_path **new_path_ptr, struct cam_periph *perph,
return (status);
}
+cam_status
+xpt_create_path_unlocked(struct cam_path **new_path_ptr,
+ struct cam_periph *periph, path_id_t path_id,
+ target_id_t target_id, lun_id_t lun_id)
+{
+ struct cam_path *path;
+ struct cam_eb *bus = NULL;
+ cam_status status;
+ int need_unlock = 0;
+
+ path = (struct cam_path *)malloc(sizeof(*path), M_CAMXPT, M_WAITOK);
+
+ if (path_id != CAM_BUS_WILDCARD) {
+ bus = xpt_find_bus(path_id);
+ if (bus != NULL) {
+ need_unlock = 1;
+ mtx_lock(bus->sim->mtx);
+ }
+ }
+ status = xpt_compile_path(path, periph, path_id, target_id, lun_id);
+ if (need_unlock)
+ mtx_unlock(bus->sim->mtx);
+ if (status != CAM_REQ_CMP) {
+ free(path, M_CAMXPT);
+ path = NULL;
+ }
+ *new_path_ptr = path;
+ return (status);
+}
+
static cam_status
xpt_compile_path(struct cam_path *new_path, struct cam_periph *perph,
path_id_t path_id, target_id_t target_id, lun_id_t lun_id)
@@ -4129,7 +4194,6 @@ xpt_release_path(struct cam_path *path)
void
xpt_free_path(struct cam_path *path)
{
- GIANT_REQUIRED;
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_free_path\n"));
xpt_release_path(path);
@@ -4144,8 +4208,6 @@ xpt_free_path(struct cam_path *path)
int
xpt_path_comp(struct cam_path *path1, struct cam_path *path2)
{
- GIANT_REQUIRED;
-
int retval = 0;
if (path1->bus != path2->bus) {
@@ -4180,7 +4242,7 @@ xpt_path_comp(struct cam_path *path1, struct cam_path *path2)
void
xpt_print_path(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
if (path == NULL)
printf("(nopath): ");
@@ -4225,7 +4287,7 @@ xpt_path_string(struct cam_path *path, char *str, size_t str_len)
{
struct sbuf sb;
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
sbuf_new(&sb, str, str_len, 0);
@@ -4263,7 +4325,7 @@ xpt_path_string(struct cam_path *path, char *str, size_t str_len)
path_id_t
xpt_path_path_id(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
return(path->bus->path_id);
}
@@ -4271,7 +4333,7 @@ xpt_path_path_id(struct cam_path *path)
target_id_t
xpt_path_target_id(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
if (path->target != NULL)
return (path->target->target_id);
@@ -4282,7 +4344,7 @@ xpt_path_target_id(struct cam_path *path)
lun_id_t
xpt_path_lun_id(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
if (path->device != NULL)
return (path->device->lun_id);
@@ -4293,7 +4355,6 @@ xpt_path_lun_id(struct cam_path *path)
struct cam_sim *
xpt_path_sim(struct cam_path *path)
{
- GIANT_REQUIRED;
return (path->bus->sim);
}
@@ -4301,7 +4362,7 @@ xpt_path_sim(struct cam_path *path)
struct cam_periph*
xpt_path_periph(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
return (path->periph);
}
@@ -4319,34 +4380,38 @@ xpt_release_ccb(union ccb *free_ccb)
struct cam_path *path;
struct cam_ed *device;
struct cam_eb *bus;
-
- GIANT_REQUIRED;
+ struct cam_sim *sim;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_release_ccb\n"));
path = free_ccb->ccb_h.path;
device = path->device;
bus = path->bus;
+ sim = bus->sim;
s = splsoftcam();
+
+ mtx_assert(sim->mtx, MA_OWNED);
+
cam_ccbq_release_opening(&device->ccbq);
- if (xpt_ccb_count > xpt_max_ccbs) {
+ if (sim->ccb_count > sim->max_ccbs) {
xpt_free_ccb(free_ccb);
- xpt_ccb_count--;
+ sim->ccb_count--;
} else {
- SLIST_INSERT_HEAD(&ccb_freeq, &free_ccb->ccb_h, xpt_links.sle);
+ SLIST_INSERT_HEAD(&sim->ccb_freeq, &free_ccb->ccb_h,
+ xpt_links.sle);
}
- if (bus->sim->devq == NULL) {
+ if (sim->devq == NULL) {
splx(s);
return;
}
- bus->sim->devq->alloc_openings++;
- bus->sim->devq->alloc_active--;
+ sim->devq->alloc_openings++;
+ sim->devq->alloc_active--;
/* XXX Turn this into an inline function - xpt_run_device?? */
if ((device_is_alloc_queued(device) == 0)
&& (device->drvq.entries > 0)) {
xpt_schedule_dev_allocq(bus, device);
}
splx(s);
- if (dev_allocq_is_runnable(bus->sim->devq))
+ if (dev_allocq_is_runnable(sim->devq))
xpt_run_dev_allocq(bus);
}
@@ -4369,7 +4434,7 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
struct ccb_pathinq cpi;
int s;
- GIANT_REQUIRED;
+ mtx_assert(sim->mtx, MA_OWNED);
sim->bus_id = bus;
new_bus = (struct cam_eb *)malloc(sizeof(*new_bus),
@@ -4393,15 +4458,17 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
new_bus->refcount = 1; /* Held until a bus_deregister event */
new_bus->generation = 0;
s = splcam();
- old_bus = TAILQ_FIRST(&xpt_busses);
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ old_bus = TAILQ_FIRST(&xsoftc.xpt_busses);
while (old_bus != NULL
&& old_bus->path_id < new_bus->path_id)
old_bus = TAILQ_NEXT(old_bus, links);
if (old_bus != NULL)
TAILQ_INSERT_BEFORE(old_bus, new_bus, links);
else
- TAILQ_INSERT_TAIL(&xpt_busses, new_bus, links);
- bus_generation++;
+ TAILQ_INSERT_TAIL(&xsoftc.xpt_busses, new_bus, links);
+ xsoftc.bus_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
splx(s);
/* Notify interested parties */
@@ -4431,7 +4498,6 @@ xpt_bus_deregister(path_id_t pathid)
union ccb *work_ccb;
cam_status status;
- GIANT_REQUIRED;
status = xpt_compile_path(&bus_path, NULL, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
@@ -4496,7 +4562,8 @@ xptnextfreepathid(void)
const char *strval;
pathid = 0;
- bus = TAILQ_FIRST(&xpt_busses);
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ bus = TAILQ_FIRST(&xsoftc.xpt_busses);
retry:
/* Find an unoccupied pathid */
while (bus != NULL && bus->path_id <= pathid) {
@@ -4504,6 +4571,7 @@ retry:
pathid++;
bus = TAILQ_NEXT(bus, links);
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
/*
* Ensure that this pathid is not reserved for
@@ -4512,6 +4580,7 @@ retry:
if (resource_string_value("scbus", pathid, "at", &strval) == 0) {
++pathid;
/* Start the search over */
+ mtx_lock(&xsoftc.xpt_topo_lock);
goto retry;
}
return (pathid);
@@ -4568,7 +4637,7 @@ xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg)
struct cam_ed *device, *next_device;
int s;
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_async\n"));
@@ -4735,7 +4804,7 @@ xpt_freeze_devq(struct cam_path *path, u_int count)
int s;
struct ccb_hdr *ccbh;
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
s = splcam();
path->device->qfrozen_cnt += count;
@@ -4763,7 +4832,7 @@ xpt_freeze_devq(struct cam_path *path, u_int count)
u_int32_t
xpt_freeze_simq(struct cam_sim *sim, u_int count)
{
- GIANT_REQUIRED;
+ mtx_assert(sim->mtx, MA_OWNED);
sim->devq->send_queue.qfrozen_cnt += count;
if (sim->devq->active_dev != NULL) {
@@ -4790,7 +4859,7 @@ xpt_release_devq_timeout(void *arg)
void
xpt_release_devq(struct cam_path *path, u_int count, int run_queue)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
xpt_release_devq_device(path->device, count, run_queue);
}
@@ -4821,8 +4890,7 @@ xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
* to release this queue.
*/
if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) {
- untimeout(xpt_release_devq_timeout, dev,
- dev->c_handle);
+ callout_stop(&dev->callout);
dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING;
}
@@ -4850,7 +4918,7 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
int s;
struct camq *sendq;
- GIANT_REQUIRED;
+ mtx_assert(sim->mtx, MA_OWNED);
sendq = &(sim->devq->send_queue);
s = splcam();
@@ -4866,8 +4934,7 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
* already at 0.
*/
if ((sim->flags & CAM_SIM_REL_TIMEOUT_PENDING) != 0){
- untimeout(xpt_release_simq_timeout, sim,
- sim->c_handle);
+ callout_stop(&sim->callout);
sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING;
}
bus = xpt_find_bus(sim->path_id);
@@ -4886,6 +4953,9 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
splx(s);
}
+/*
+ * XXX Appears to be unused.
+ */
static void
xpt_release_simq_timeout(void *arg)
{
@@ -4915,7 +4985,9 @@ xpt_done(union ccb *done_ccb)
sim_links.tqe);
done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
mtx_unlock(&cam_bioq_lock);
- swi_sched(cambio_ih, 0);
+ if ((done_ccb->ccb_h.path->periph->flags &
+ CAM_PERIPH_POLLED) == 0)
+ swi_sched(cambio_ih, 0);
break;
default:
panic("unknown periph type %d",
@@ -4926,24 +4998,26 @@ xpt_done(union ccb *done_ccb)
}
union ccb *
-xpt_alloc_ccb()
+xpt_alloc_ccb(struct cam_sim *sim)
{
union ccb *new_ccb;
- GIANT_REQUIRED;
-
new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_WAITOK);
+ if ((sim != NULL) && ((sim->flags & CAM_SIM_MPSAFE) == 0)) {
+ callout_handle_init(&new_ccb->ccb_h.timeout_ch);
+ }
return (new_ccb);
}
union ccb *
-xpt_alloc_ccb_nowait()
+xpt_alloc_ccb_nowait(struct cam_sim *sim)
{
union ccb *new_ccb;
- GIANT_REQUIRED;
-
new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_NOWAIT);
+ if ((sim != NULL) && ((sim->flags & CAM_SIM_MPSAFE) == 0)) {
+ callout_handle_init(&new_ccb->ccb_h.timeout_ch);
+ }
return (new_ccb);
}
@@ -4968,22 +5042,23 @@ static union ccb *
xpt_get_ccb(struct cam_ed *device)
{
union ccb *new_ccb;
+ struct cam_sim *sim;
int s;
s = splsoftcam();
- if ((new_ccb = (union ccb *)SLIST_FIRST(&ccb_freeq)) == NULL) {
- new_ccb = xpt_alloc_ccb_nowait();
+ sim = device->sim;
+ if ((new_ccb = (union ccb *)SLIST_FIRST(&sim->ccb_freeq)) == NULL) {
+ new_ccb = xpt_alloc_ccb_nowait(sim);
if (new_ccb == NULL) {
splx(s);
return (NULL);
}
- callout_handle_init(&new_ccb->ccb_h.timeout_ch);
- SLIST_INSERT_HEAD(&ccb_freeq, &new_ccb->ccb_h,
+ SLIST_INSERT_HEAD(&sim->ccb_freeq, &new_ccb->ccb_h,
xpt_links.sle);
- xpt_ccb_count++;
+ sim->ccb_count++;
}
cam_ccbq_take_opening(&device->ccbq);
- SLIST_REMOVE_HEAD(&ccb_freeq, xpt_links.sle);
+ SLIST_REMOVE_HEAD(&sim->ccb_freeq, xpt_links.sle);
splx(s);
return (new_ccb);
}
@@ -4996,8 +5071,10 @@ xpt_release_bus(struct cam_eb *bus)
s = splcam();
if ((--bus->refcount == 0)
&& (TAILQ_FIRST(&bus->et_entries) == NULL)) {
- TAILQ_REMOVE(&xpt_busses, bus, links);
- bus_generation++;
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
+ xsoftc.bus_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
splx(s);
free(bus, M_CAMXPT);
} else
@@ -5088,6 +5165,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
device->send_ccb_entry.device = device;
device->target = target;
device->lun_id = lun_id;
+ device->sim = bus->sim;
/* Initialize our queues */
if (camq_init(&device->drvq, 0) != 0) {
free(device, M_CAMXPT);
@@ -5118,7 +5196,10 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
device->tag_delay_count = 0;
device->tag_saved_openings = 0;
device->refcount = 1;
- callout_handle_init(&device->c_handle);
+ if (bus->sim->flags & CAM_SIM_MPSAFE)
+ callout_init_mtx(&device->callout, bus->sim->mtx, 0);
+ else
+ callout_init_mtx(&device->callout, &Giant, 0);
/*
* Hold a reference to our parent target so it
@@ -5130,7 +5211,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
* XXX should be limited by number of CCBs this bus can
* do.
*/
- xpt_max_ccbs += device->ccbq.devq_openings;
+ bus->sim->max_ccbs += device->ccbq.devq_openings;
/* Insertion sort into our target's device list */
cur_device = TAILQ_FIRST(&target->ed_entries);
while (cur_device != NULL && cur_device->lun_id < lun_id)
@@ -5170,12 +5251,11 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target,
panic("Removing device while still queued for ccbs");
if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0)
- untimeout(xpt_release_devq_timeout, device,
- device->c_handle);
+ callout_stop(&device->callout);
TAILQ_REMOVE(&target->ed_entries, device,links);
target->generation++;
- xpt_max_ccbs -= device->ccbq.devq_openings;
+ bus->sim->max_ccbs -= device->ccbq.devq_openings;
if (!SIM_DEAD(bus->sim)) {
/* Release our slot in the devq */
devq = bus->sim->devq;
@@ -5210,7 +5290,7 @@ xpt_dev_ccbq_resize(struct cam_path *path, int newopenings)
|| (dev->inq_flags & SID_CmdQue) != 0)
dev->tag_saved_openings = newopenings;
/* Adjust the global limit */
- xpt_max_ccbs += diff;
+ dev->sim->max_ccbs += diff;
splx(s);
return (result);
}
@@ -5220,7 +5300,8 @@ xpt_find_bus(path_id_t path_id)
{
struct cam_eb *bus;
- for (bus = TAILQ_FIRST(&xpt_busses);
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ for (bus = TAILQ_FIRST(&xsoftc.xpt_busses);
bus != NULL;
bus = TAILQ_NEXT(bus, links)) {
if (bus->path_id == path_id) {
@@ -5228,6 +5309,7 @@ xpt_find_bus(path_id_t path_id)
break;
}
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
return (bus);
}
@@ -5290,7 +5372,7 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
u_int initiator_id;
/* Find out the characteristics of the bus */
- work_ccb = xpt_alloc_ccb();
+ work_ccb = xpt_alloc_ccb_nowait(periph->sim);
xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_PATH_INQ;
@@ -5315,7 +5397,7 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
/* Save some state for use while we probe for devices */
scan_info = (xpt_scan_bus_info *)
- malloc(sizeof(xpt_scan_bus_info), M_TEMP, M_WAITOK);
+ malloc(sizeof(xpt_scan_bus_info), M_TEMP, M_NOWAIT);
scan_info->request_ccb = request_ccb;
scan_info->cpi = &work_ccb->cpi;
@@ -5355,7 +5437,7 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
xpt_done(request_ccb);
break;
}
- work_ccb = xpt_alloc_ccb();
+ work_ccb = xpt_alloc_ccb_nowait(periph->sim);
xpt_setup_ccb(&work_ccb->ccb_h, path,
request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
@@ -6870,6 +6952,9 @@ static int busses_to_reset;
static int
xptconfigbuscountfunc(struct cam_eb *bus, void *arg)
{
+
+ mtx_assert(bus->sim->mtx, MA_OWNED);
+
if (bus->path_id != CAM_XPT_PATH_ID) {
struct cam_path path;
struct ccb_pathinq cpi;
@@ -6898,11 +6983,13 @@ xptconfigfunc(struct cam_eb *bus, void *arg)
struct cam_path *path;
union ccb *work_ccb;
+ mtx_assert(bus->sim->mtx, MA_OWNED);
+
if (bus->path_id != CAM_XPT_PATH_ID) {
cam_status status;
int can_negotiate;
- work_ccb = xpt_alloc_ccb();
+ work_ccb = xpt_alloc_ccb_nowait(bus->sim);
if ((status = xpt_create_path(&path, xpt_periph, bus->path_id,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD)) !=CAM_REQ_CMP){
@@ -6962,6 +7049,11 @@ xpt_config(void *arg)
#endif /* CAM_DEBUG_FLAGS */
#ifdef CAM_DEBUG_BUS
if (cam_dflags != CAM_DEBUG_NONE) {
+ /*
+ * Locking is specifically omitted here. No SIMs have
+ * registered yet, so xpt_create_path will only be searching
+ * empty lists of targets and devices.
+ */
if (xpt_create_path(&cam_dpath, xpt_periph,
CAM_DEBUG_BUS, CAM_DEBUG_TARGET,
CAM_DEBUG_LUN) != CAM_REQ_CMP) {
@@ -7017,11 +7109,40 @@ xptpassannouncefunc(struct cam_ed *device, void *arg)
}
static void
-xpt_finishconfig(struct cam_periph *periph, union ccb *done_ccb)
+xpt_finishconfig_task(void *context, int pending)
{
struct periph_driver **p_drv;
int i;
+ if (busses_to_config == 0) {
+ /* Register all the peripheral drivers */
+ /* XXX This will have to change when we have loadable modules */
+ p_drv = periph_drivers;
+ for (i = 0; p_drv[i] != NULL; i++) {
+ (*p_drv[i]->init)();
+ }
+
+ /*
+ * Check for devices with no "standard" peripheral driver
+ * attached. For any devices like that, announce the
+ * passthrough driver so the user will see something.
+ */
+ xpt_for_all_devices(xptpassannouncefunc, NULL);
+
+ /* Release our hook so that the boot can continue. */
+ config_intrhook_disestablish(xsoftc.xpt_config_hook);
+ free(xsoftc.xpt_config_hook, M_TEMP);
+ xsoftc.xpt_config_hook = NULL;
+ }
+
+ free(context, M_CAMXPT);
+}
+
+static void
+xpt_finishconfig(struct cam_periph *periph, union ccb *done_ccb)
+{
+ struct xpt_task *task;
+
if (done_ccb != NULL) {
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("xpt_finishconfig\n"));
@@ -7043,26 +7164,12 @@ xpt_finishconfig(struct cam_periph *periph, union ccb *done_ccb)
}
}
- if (busses_to_config == 0) {
- /* Register all the peripheral drivers */
- /* XXX This will have to change when we have loadable modules */
- p_drv = periph_drivers;
- for (i = 0; p_drv[i] != NULL; i++) {
- (*p_drv[i]->init)();
- }
-
- /*
- * Check for devices with no "standard" peripheral driver
- * attached. For any devices like that, announce the
- * passthrough driver so the user will see something.
- */
- xpt_for_all_devices(xptpassannouncefunc, NULL);
-
- /* Release our hook so that the boot can continue. */
- config_intrhook_disestablish(xpt_config_hook);
- free(xpt_config_hook, M_TEMP);
- xpt_config_hook = NULL;
+ task = malloc(sizeof(struct xpt_task), M_CAMXPT, M_NOWAIT);
+ if (task != NULL) {
+ TASK_INIT(&task->task, 0, xpt_finishconfig_task, task);
+ taskqueue_enqueue(taskqueue_thread, &task->task);
}
+
if (done_ccb != NULL)
xpt_free_ccb(done_ccb);
}
@@ -7117,6 +7224,18 @@ xptpoll(struct cam_sim *sim)
{
}
+void
+xpt_lock_buses(void)
+{
+ mtx_lock(&xsoftc.xpt_topo_lock);
+}
+
+void
+xpt_unlock_buses(void)
+{
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+}
+
static void
camisr(void *V_queue)
{
@@ -7124,6 +7243,7 @@ camisr(void *V_queue)
cam_isrq_t queue;
int s;
struct ccb_hdr *ccb_h;
+ struct cam_sim *sim;
/*
* Transfer the ccb_bioq list to a temporary list so we can operate
@@ -7152,14 +7272,15 @@ camisr(void *V_queue)
struct highpowerlist *hphead;
union ccb *send_ccb;
- hphead = &highpowerq;
+ mtx_lock(&xsoftc.xpt_lock);
+ hphead = &xsoftc.highpowerq;
send_ccb = (union ccb *)STAILQ_FIRST(hphead);
/*
* Increment the count since this command is done.
*/
- num_highpower++;
+ xsoftc.num_highpower++;
/*
* Any high powered commands queued up?
@@ -7167,11 +7288,17 @@ camisr(void *V_queue)
if (send_ccb != NULL) {
STAILQ_REMOVE_HEAD(hphead, xpt_links.stqe);
+ mtx_unlock(&xsoftc.xpt_lock);
xpt_release_devq(send_ccb->ccb_h.path,
/*count*/1, /*runqueue*/TRUE);
- }
+ } else
+ mtx_unlock(&xsoftc.xpt_lock);
}
+
+ sim = ccb_h->path->bus->sim;
+ mtx_lock(sim->mtx);
+
if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) {
struct cam_ed *dev;
@@ -7227,6 +7354,7 @@ camisr(void *V_queue)
(*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h);
/* Raise IPL for while test */
+ mtx_unlock(sim->mtx);
s = splcam();
}
splx(s);
diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h
index f8557f9..deed466 100644
--- a/sys/cam/cam_xpt.h
+++ b/sys/cam/cam_xpt.h
@@ -58,6 +58,10 @@ cam_status xpt_create_path(struct cam_path **new_path_ptr,
struct cam_periph *perph,
path_id_t path_id,
target_id_t target_id, lun_id_t lun_id);
+cam_status xpt_create_path_unlocked(struct cam_path **new_path_ptr,
+ struct cam_periph *perph,
+ path_id_t path_id,
+ target_id_t target_id, lun_id_t lun_id);
void xpt_free_path(struct cam_path *path);
int xpt_path_comp(struct cam_path *path1,
struct cam_path *path2);
@@ -73,6 +77,8 @@ struct cam_periph *xpt_path_periph(struct cam_path *path);
void xpt_async(u_int32_t async_code, struct cam_path *path,
void *async_arg);
void xpt_rescan(union ccb *ccb);
+void xpt_lock_buses(void);
+void xpt_unlock_buses(void);
#endif /* _KERNEL */
#endif /* _CAM_CAM_XPT_H */
diff --git a/sys/cam/cam_xpt_periph.h b/sys/cam/cam_xpt_periph.h
index c6b8cc2..9c4a3bb 100644
--- a/sys/cam/cam_xpt_periph.h
+++ b/sys/cam/cam_xpt_periph.h
@@ -38,8 +38,8 @@
/* Functions accessed by the peripheral drivers */
#ifdef _KERNEL
void xpt_polled_action(union ccb *ccb);
-union ccb *xpt_alloc_ccb(void);
-union ccb *xpt_alloc_ccb_nowait(void);
+union ccb *xpt_alloc_ccb(struct cam_sim *sim);
+union ccb *xpt_alloc_ccb_nowait(struct cam_sim *sim);
void xpt_free_ccb(union ccb *free_ccb);
void xpt_release_ccb(union ccb *released_ccb);
void xpt_schedule(struct cam_periph *perph, u_int32_t new_priority);
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 07782ba..fa85ada 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_queue.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_da.h>
@@ -103,7 +104,8 @@ typedef enum {
CD_FLAG_RETRY_UA = 0x0200,
CD_FLAG_VALID_MEDIA = 0x0400,
CD_FLAG_VALID_TOC = 0x0800,
- CD_FLAG_SCTX_INIT = 0x1000
+ CD_FLAG_SCTX_INIT = 0x1000,
+ CD_FLAG_OPEN = 0x2000
} cd_flags;
typedef enum {
@@ -290,9 +292,6 @@ static struct periph_driver cddriver =
PERIPHDRIVER_DECLARE(cd, cddriver);
-
-static int num_changers;
-
#ifndef CHANGER_MIN_BUSY_SECONDS
#define CHANGER_MIN_BUSY_SECONDS 5
#endif
@@ -319,15 +318,16 @@ struct cdchanger {
struct camq devq;
struct timeval start_time;
struct cd_softc *cur_device;
- struct callout_handle short_handle;
- struct callout_handle long_handle;
+ struct callout short_handle;
+ struct callout long_handle;
volatile cd_changer_flags flags;
STAILQ_ENTRY(cdchanger) changer_links;
STAILQ_HEAD(chdevlist, cd_softc) chluns;
};
+static struct mtx changerq_mtx;
static STAILQ_HEAD(changerlist, cdchanger) changerq;
-
+static int num_changers;
static void
cdinit(void)
@@ -335,6 +335,9 @@ cdinit(void)
cam_status status;
struct cam_path *path;
+ mtx_init(&changerq_mtx, "cdchangerq", "SCSI CD Changer List", MTX_DEF);
+ STAILQ_INIT(&changerq);
+
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
@@ -364,7 +367,6 @@ cdinit(void)
static void
cdoninvalidate(struct cam_periph *periph)
{
- int s;
struct cd_softc *softc;
struct ccb_setasync csa;
@@ -384,19 +386,11 @@ cdoninvalidate(struct cam_periph *periph)
softc->flags |= CD_FLAG_INVALID;
/*
- * Although the oninvalidate() routines are always called at
- * splsoftcam, we need to be at splbio() here to keep the buffer
- * queue from being modified while we traverse it.
- */
- s = splbio();
-
- /*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
bioq_flush(&softc->bio_queue, NULL, ENXIO);
- splx(s);
/*
* If this device is part of a changer, and it was scheduled
@@ -415,7 +409,6 @@ static void
cdcleanup(struct cam_periph *periph)
{
struct cd_softc *softc;
- int s;
softc = (struct cd_softc *)periph->softc;
@@ -426,7 +419,6 @@ cdcleanup(struct cam_periph *periph)
xpt_print(periph->path, "can't remove sysctl context\n");
}
- s = splsoftcam();
/*
* In the queued, non-active case, the device in question
* has already been removed from the changer run queue. Since this
@@ -456,8 +448,7 @@ cdcleanup(struct cam_periph *periph)
* be any bogus pointer references there.
*/
if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) {
- untimeout(cdshorttimeout, softc->changer,
- softc->changer->short_handle);
+ callout_stop(&softc->changer->short_handle);
softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
}
softc->changer->devq.qfrozen_cnt--;
@@ -478,26 +469,25 @@ cdcleanup(struct cam_periph *periph)
* it won't hurt to check and see if there are any left.
*/
if (softc->changer->flags & CHANGER_TIMEOUT_SCHED) {
- untimeout(cdrunchangerqueue, softc->changer,
- softc->changer->long_handle);
+ callout_stop(&softc->changer->long_handle);
softc->changer->flags &= ~CHANGER_TIMEOUT_SCHED;
}
if (softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED) {
- untimeout(cdshorttimeout, softc->changer,
- softc->changer->short_handle);
+ callout_stop(&softc->changer->short_handle);
softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
}
+ mtx_lock(&changerq_mtx);
STAILQ_REMOVE(&changerq, softc->changer, cdchanger,
changer_links);
+ num_changers--;
+ mtx_unlock(&changerq_mtx);
xpt_print(periph->path, "removing changer entry\n");
free(softc->changer, M_DEVBUF);
- num_changers--;
}
disk_destroy(softc->disk);
free(softc, M_DEVBUF);
- splx(s);
}
static void
@@ -544,10 +534,8 @@ cdasync(void *callback_arg, u_int32_t code,
{
struct cd_softc *softc;
struct ccb_hdr *ccbh;
- int s;
softc = (struct cd_softc *)periph->softc;
- s = splsoftcam();
/*
* Don't fail on the expected unit attention
* that will occur.
@@ -555,7 +543,6 @@ cdasync(void *callback_arg, u_int32_t code,
softc->flags |= CD_FLAG_RETRY_UA;
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
ccbh->ccb_state |= CD_CCB_RETRY_UA;
- splx(s);
/* FALLTHROUGH */
}
default:
@@ -572,8 +559,10 @@ cdsysctlinit(void *context, int pending)
char tmpstr[80], tmpstr2[80];
periph = (struct cam_periph *)context;
- softc = (struct cd_softc *)periph->softc;
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return;
+ softc = (struct cd_softc *)periph->softc;
snprintf(tmpstr, sizeof(tmpstr), "CAM CD unit %d", periph->unit_number);
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
@@ -588,6 +577,7 @@ cdsysctlinit(void *context, int pending)
if (softc->sysctl_tree == NULL) {
printf("cdsysctlinit: unable to allocate sysctl tree\n");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
return;
}
@@ -601,6 +591,7 @@ cdsysctlinit(void *context, int pending)
"Minimum CDB size");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
}
/*
@@ -734,6 +725,7 @@ cdregister(struct cam_periph *periph, void *arg)
* WORM peripheral driver. WORM drives will also have the WORM
* driver attached to them.
*/
+ cam_periph_unlock(periph);
softc->disk = disk_alloc();
softc->disk->d_devstat = devstat_new_entry("cd",
periph->unit_number, 0,
@@ -747,8 +739,9 @@ cdregister(struct cam_periph *periph, void *arg)
softc->disk->d_name = "cd";
softc->disk->d_unit = periph->unit_number;
softc->disk->d_drv1 = periph;
- softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
+ softc->disk->d_flags = 0;
disk_create(softc->disk, DISK_VERSION);
+ cam_periph_lock(periph);
/*
* Add an async callback so that we get
@@ -783,13 +776,11 @@ cdregister(struct cam_periph *periph, void *arg)
/* Set the changer flag in the current device's softc */
softc->flags |= CD_FLAG_CHANGER;
- if (num_changers == 0)
- STAILQ_INIT(&changerq);
-
/*
* Now, look around for an existing changer device with the
* same path and target ID as the current device.
*/
+ mtx_lock(&changerq_mtx);
for (found = 0,
nchanger = (struct cdchanger *)STAILQ_FIRST(&changerq);
nchanger != NULL;
@@ -800,6 +791,7 @@ cdregister(struct cam_periph *periph, void *arg)
break;
}
}
+ mtx_unlock(&changerq_mtx);
/*
* If we found a matching entry, just add this device to
@@ -905,8 +897,6 @@ cdregister(struct cam_periph *periph, void *arg)
goto cdregisterexit;
}
- num_changers++;
-
nchanger->path_id = cgd->ccb_h.path_id;
nchanger->target_id = cgd->ccb_h.target_id;
@@ -915,8 +905,16 @@ cdregister(struct cam_periph *periph, void *arg)
STAILQ_INIT(&nchanger->chluns);
+ callout_init_mtx(&nchanger->long_handle,
+ periph->sim->mtx, 0);
+ callout_init_mtx(&nchanger->short_handle,
+ periph->sim->mtx, 0);
+
+ mtx_lock(&changerq_mtx);
+ num_changers++;
STAILQ_INSERT_TAIL(&changerq, nchanger,
changer_links);
+ mtx_unlock(&changerq_mtx);
/*
* Create a path with lun id 0, and see if we can
@@ -978,9 +976,11 @@ cdregister(struct cam_periph *periph, void *arg)
cdregisterexit:
- /* Lock this peripheral until we are setup */
- /* Can't block */
- cam_periph_lock(periph, PRIBIO);
+ /*
+ * Refcount and block open attempts until we are setup
+ * Can't block
+ */
+ (void)cam_periph_hold(periph, PRIBIO);
if ((softc->flags & CD_FLAG_CHANGER) == 0)
xpt_schedule(periph, /*priority*/5);
@@ -996,7 +996,6 @@ cdopen(struct disk *dp)
struct cam_periph *periph;
struct cd_softc *softc;
int error;
- int s;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
@@ -1004,24 +1003,28 @@ cdopen(struct disk *dp)
softc = (struct cd_softc *)periph->softc;
- /*
- * Grab splsoftcam and hold it until we lock the peripheral.
- */
- s = splsoftcam();
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return(ENXIO);
+
+ cam_periph_lock(periph);
+
if (softc->flags & CD_FLAG_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(ENXIO);
}
- if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
- splx(s);
+ if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (error);
}
- splx(s);
-
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- return(ENXIO);
+ /* Closes aren't symmetrical with opens, so fix up the refcounting. */
+ if (softc->flags & CD_FLAG_OPEN)
+ cam_periph_release(periph);
+ else
+ softc->flags |= CD_FLAG_OPEN;
/*
* Check for media, and set the appropriate flags. We don't bail
@@ -1030,11 +1033,11 @@ cdopen(struct disk *dp)
*/
cdcheckmedia(periph);
- cam_periph_unlock(periph);
-
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
+ cam_periph_unhold(periph);
+ cam_periph_unlock(periph);
- return (error);
+ return (0);
}
static int
@@ -1042,7 +1045,6 @@ cdclose(struct disk *dp)
{
struct cam_periph *periph;
struct cd_softc *softc;
- int error;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
@@ -1050,8 +1052,8 @@ cdclose(struct disk *dp)
softc = (struct cd_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return (error);
+ cam_periph_lock(periph);
+ cam_periph_hold(periph, PRIBIO);
if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0)
cdprevent(periph, PR_ALLOW);
@@ -1065,8 +1067,9 @@ cdclose(struct disk *dp)
/*
* We'll check the media and toc again at the next open().
*/
- softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC);
+ softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC|CD_FLAG_OPEN);
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
cam_periph_release(periph);
@@ -1077,9 +1080,6 @@ static void
cdshorttimeout(void *arg)
{
struct cdchanger *changer;
- int s;
-
- s = splsoftcam();
changer = (struct cdchanger *)arg;
@@ -1095,8 +1095,6 @@ cdshorttimeout(void *arg)
changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(changer);
}
-
- splx(s);
}
/*
@@ -1106,9 +1104,6 @@ static void
cdschedule(struct cam_periph *periph, int priority)
{
struct cd_softc *softc;
- int s;
-
- s = splsoftcam();
softc = (struct cd_softc *)periph->softc;
@@ -1147,9 +1142,6 @@ cdschedule(struct cam_periph *periph, int priority)
} else if ((softc->flags & CD_FLAG_ACTIVE)
&& ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0))
xpt_schedule(periph, priority);
-
- splx(s);
-
}
static void
@@ -1158,9 +1150,6 @@ cdrunchangerqueue(void *arg)
struct cd_softc *softc;
struct cdchanger *changer;
int called_from_timeout;
- int s;
-
- s = splsoftcam();
changer = (struct cdchanger *)arg;
@@ -1180,7 +1169,6 @@ cdrunchangerqueue(void *arg)
/* nothing to do if the queue is empty */
if (changer->devq.entries <= 0) {
- splx(s);
return;
}
@@ -1190,29 +1178,28 @@ cdrunchangerqueue(void *arg)
*/
if (changer->devq.qfrozen_cnt > 0) {
+ /*
+ * We always need to reset the frozen count and clear the
+ * active flag.
+ */
+ changer->devq.qfrozen_cnt--;
+ changer->cur_device->flags &= ~CD_FLAG_ACTIVE;
+ changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP;
+
if (changer->cur_device->outstanding_cmds > 0) {
changer->cur_device->flags |= CD_FLAG_SCHED_ON_COMP;
changer->cur_device->bufs_left =
changer->cur_device->outstanding_cmds;
if (called_from_timeout) {
- changer->long_handle =
- timeout(cdrunchangerqueue, changer,
- changer_max_busy_seconds * hz);
+ callout_reset(&changer->long_handle,
+ changer_max_busy_seconds * hz,
+ cdrunchangerqueue, changer);
changer->flags |= CHANGER_TIMEOUT_SCHED;
}
- splx(s);
return;
}
/*
- * We always need to reset the frozen count and clear the
- * active flag.
- */
- changer->devq.qfrozen_cnt--;
- changer->cur_device->flags &= ~CD_FLAG_ACTIVE;
- changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP;
-
- /*
* Check to see whether the current device has any I/O left
* to do. If so, requeue it at the end of the queue. If
* not, there is no need to requeue it.
@@ -1242,12 +1229,12 @@ cdrunchangerqueue(void *arg)
* ones so this device gets its full time quantum.
*/
if (changer->flags & CHANGER_TIMEOUT_SCHED) {
- untimeout(cdrunchangerqueue, changer, changer->long_handle);
+ callout_stop(&changer->long_handle);
changer->flags &= ~CHANGER_TIMEOUT_SCHED;
}
if (changer->flags & CHANGER_SHORT_TMOUT_SCHED) {
- untimeout(cdshorttimeout, changer, changer->short_handle);
+ callout_stop(&changer->short_handle);
changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
}
@@ -1257,17 +1244,12 @@ cdrunchangerqueue(void *arg)
* switch time.
*/
changer->flags |= CHANGER_NEED_TIMEOUT;
-
- splx(s);
}
static void
cdchangerschedule(struct cd_softc *softc)
{
struct cdchanger *changer;
- int s;
-
- s = splsoftcam();
changer = softc->changer;
@@ -1313,18 +1295,18 @@ cdchangerschedule(struct cd_softc *softc)
* and schedule our timeouts.
*/
if ((changer->flags & CHANGER_TIMEOUT_SCHED) == 0) {
- changer->long_handle =
- timeout(cdrunchangerqueue, changer,
- changer_max_busy_seconds * hz);
+ callout_reset(&changer->long_handle,
+ changer_max_busy_seconds * hz,
+ cdrunchangerqueue, changer);
changer->flags |= CHANGER_TIMEOUT_SCHED;
} else
printf("cdchangerschedule: already have a long"
" timeout!\n");
if ((changer->flags & CHANGER_SHORT_TMOUT_SCHED) == 0) {
- changer->short_handle =
- timeout(cdshorttimeout, changer,
- changer_min_busy_seconds * hz);
+ callout_reset(&changer->short_handle,
+ changer_min_busy_seconds * hz,
+ cdshorttimeout, changer);
changer->flags |= CHANGER_SHORT_TMOUT_SCHED;
} else
printf("cdchangerschedule: already have a short "
@@ -1337,7 +1319,6 @@ cdchangerschedule(struct cd_softc *softc)
changer->flags &= ~CHANGER_NEED_TIMEOUT;
}
- splx(s);
}
static int
@@ -1366,14 +1347,10 @@ static union ccb *
cdgetccb(struct cam_periph *periph, u_int32_t priority)
{
struct cd_softc *softc;
- int s;
softc = (struct cd_softc *)periph->softc;
if (softc->flags & CD_FLAG_CHANGER) {
-
- s = splsoftcam();
-
/*
* This should work the first time this device is woken up,
* but just in case it doesn't, we use a while loop.
@@ -1396,9 +1373,9 @@ cdgetccb(struct cam_periph *periph, u_int32_t priority)
softc->changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(softc->changer);
} else
- tsleep(&softc->changer, PRIBIO, "cgticb", 0);
+ msleep(&softc->changer, periph->sim->mtx,
+ PRIBIO, "cgticb", 0);
}
- splx(s);
}
return(cam_periph_getccb(periph, priority));
}
@@ -1414,7 +1391,6 @@ cdstrategy(struct bio *bp)
{
struct cam_periph *periph;
struct cd_softc *softc;
- int s;
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
if (periph == NULL) {
@@ -1422,22 +1398,16 @@ cdstrategy(struct bio *bp)
return;
}
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstrategy\n"));
softc = (struct cd_softc *)periph->softc;
/*
- * Mask interrupts so that the pack cannot be invalidated until
- * after we are in the queue. Otherwise, we might not properly
- * clean up one of the buffers.
- */
- s = splbio();
-
- /*
* If the device has been made invalid, error out
*/
if ((softc->flags & CD_FLAG_INVALID)) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
@@ -1451,7 +1421,7 @@ cdstrategy(struct bio *bp)
error = cdcheckmedia(periph);
if (error != 0) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, error);
return;
}
@@ -1462,8 +1432,6 @@ cdstrategy(struct bio *bp)
*/
bioq_disksort(&softc->bio_queue, bp);
- splx(s);
-
/*
* Schedule ourselves for performing the work. We do things
* differently for changers.
@@ -1473,6 +1441,7 @@ cdstrategy(struct bio *bp)
else
cdschedule(periph, /* priority */ 1);
+ cam_periph_unlock(periph);
return;
}
@@ -1483,7 +1452,6 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
struct bio *bp;
struct ccb_scsiio *csio;
struct scsi_read_capacity_data *rcap;
- int s;
softc = (struct cd_softc *)periph->softc;
@@ -1492,9 +1460,6 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
switch (softc->state) {
case CD_STATE_NORMAL:
{
- int oldspl;
-
- s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
start_ccb->ccb_h.ccb_state = CD_CCB_WAITING;
@@ -1502,10 +1467,8 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else {
bioq_remove(&softc->bio_queue, bp);
@@ -1529,15 +1492,9 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_state = CD_CCB_BUFFER_IO;
- /*
- * Block out any asyncronous callbacks
- * while we touch the pending ccb list.
- */
- oldspl = splcam();
LIST_INSERT_HEAD(&softc->pending_ccbs,
&start_ccb->ccb_h, periph_links.le);
softc->outstanding_cmds++;
- splx(oldspl);
/* We expect a unit attention from this device */
if ((softc->flags & CD_FLAG_RETRY_UA) != 0) {
@@ -1547,7 +1504,6 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1601,7 +1557,6 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
{
struct bio *bp;
int error;
- int oldspl;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
error = 0;
@@ -1625,13 +1580,9 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
}
if (error != 0) {
- int s;
-
xpt_print(periph->path,
"cddone: got error %#x back\n", error);
- s = splbio();
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
bp->bio_resid = bp->bio_bcount;
bp->bio_error = error;
bp->bio_flags |= BIO_ERROR;
@@ -1654,14 +1605,8 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
}
}
- /*
- * Block out any asyncronous callbacks
- * while we touch the pending ccb list.
- */
- oldspl = splcam();
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
softc->outstanding_cmds--;
- splx(oldspl);
if (softc->flags & CD_FLAG_CHANGER)
cdchangerschedule(softc);
@@ -1852,7 +1797,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case CD_CCB_WAITING:
@@ -1905,12 +1850,13 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cam_periph *periph;
struct cd_softc *softc;
- int error, nocopyout;
+ int nocopyout, error = 0;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
return(ENXIO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdioctl\n"));
softc = (struct cd_softc *)periph->softc;
@@ -1918,10 +1864,12 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
("trying to do ioctl %#lx\n", cmd));
- error = cam_periph_lock(periph, PRIBIO | PCATCH);
+ if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
+ }
- if (error != 0)
- return(error);
/*
* If we don't have media loaded, check for it. If still don't
* have media loaded, we can only do a load or eject.
@@ -1936,11 +1884,14 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
&& (cmd != CDIOCEJECT))
&& (IOCGROUP(cmd) == 'c')) {
error = cdcheckmedia(periph);
- if (error != 0) {
- cam_periph_unlock(periph);
- return (error);
- }
}
+ /*
+ * Drop the lock here so later mallocs can use WAITOK. The periph
+ * is essentially locked still with the cam_periph_hold call above.
+ */
+ cam_periph_unlock(periph);
+ if (error != 0)
+ return (error);
nocopyout = 0;
switch (cmd) {
@@ -1956,12 +1907,14 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOCPLAYTRACKS\n"));
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -1970,8 +1923,10 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
- if (error)
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
/*
* This was originally implemented with the PLAY
@@ -2033,6 +1988,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
args->end_track,
args->end_index);
}
+ cam_periph_unlock(periph);
}
break;
case CDIOCPLAYMSF:
@@ -2046,12 +2002,14 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOCPLAYMSF\n"));
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2060,8 +2018,10 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
- if (error)
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
error = cdplaymsf(periph,
args->start_m,
args->start_s,
@@ -2069,6 +2029,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
args->end_m,
args->end_s,
args->end_f);
+ cam_periph_unlock(periph);
}
break;
case CDIOCPLAYBLOCKS:
@@ -2078,16 +2039,19 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCPLAYBLOCKS\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCPLAYBLOCKS\n"));
+
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2096,9 +2060,12 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
- if (error)
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
error = cdplay(periph, args->blk, args->len);
+ cam_periph_unlock(periph);
}
break;
case CDIOCREADSUBCHANNEL_SYSSPACE:
@@ -2111,12 +2078,13 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_sub_channel_info *data;
u_int32_t len = args->data_len;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCREADSUBCHANNEL\n"));
-
data = malloc(sizeof(struct cd_sub_channel_info),
M_TEMP, M_WAITOK);
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCREADSUBCHANNEL\n"));
+
if ((len > sizeof(struct cd_sub_channel_info)) ||
(len < sizeof(struct cd_sub_channel_header))) {
printf(
@@ -2125,6 +2093,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
len);
error = EINVAL;
free(data, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
@@ -2136,6 +2105,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
if (error) {
free(data, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
if (softc->quirks & CD_Q_BCD_TRACKS)
@@ -2144,6 +2114,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
len = min(len, ((data->header.data_len[0] << 8) +
data->header.data_len[1] +
sizeof(struct cd_sub_channel_header)));
+ cam_periph_unlock(periph);
if (nocopyout == 0) {
if (copyout(data, args->data, len) != 0) {
error = EFAULT;
@@ -2159,15 +2130,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
{
struct ioc_toc_header *th;
+ th = malloc(sizeof(struct ioc_toc_header), M_TEMP,
+ M_WAITOK);
+
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOREADTOCHEADER\n"));
- th = malloc(sizeof(struct ioc_toc_header), M_TEMP,
- M_WAITOK);
error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
sizeof (*th), /*sense_flags*/0);
if (error) {
free(th, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
if (softc->quirks & CD_Q_BCD_TRACKS) {
@@ -2181,6 +2155,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
th->len = ntohs(th->len);
bcopy(th, addr, sizeof(*th));
free(th, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOREADTOCENTRYS:
@@ -2193,12 +2168,13 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
u_int32_t len, readlen, idx, num;
u_int32_t starting_track = te->starting_track;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOREADTOCENTRYS\n"));
-
data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
lead = malloc(sizeof(*lead), M_TEMP, M_WAITOK);
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOREADTOCENTRYS\n"));
+
if (te->data_len < sizeof(struct cd_toc_entry)
|| (te->data_len % sizeof(struct cd_toc_entry)) != 0
|| (te->address_format != CD_MSF_FORMAT
@@ -2208,6 +2184,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
"returning EINVAL\n");
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
@@ -2217,6 +2194,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
if (error) {
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
@@ -2239,6 +2217,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
"returning EINVAL\n");
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
error = EINVAL;
break;
}
@@ -2260,6 +2239,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
error = EINVAL;
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
num = len / sizeof(struct cd_toc_entry);
@@ -2273,6 +2253,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
if (error) {
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
}
@@ -2289,6 +2270,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
if (error) {
free(data, M_TEMP);
free(lead, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
data->entries[idx - starting_track] =
@@ -2301,6 +2283,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
}
}
+ cam_periph_unlock(periph);
error = copyout(data->entries, te->data, len);
free(data, M_TEMP);
free(lead, M_TEMP);
@@ -2314,17 +2297,19 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct ioc_toc_header *th;
u_int32_t track;
+ data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
+
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOREADTOCENTRY\n"));
- data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
-
if (te->address_format != CD_MSF_FORMAT
&& te->address_format != CD_LBA_FORMAT) {
printf("error in readtocentry, "
" returning EINVAL\n");
free(data, M_TEMP);
error = EINVAL;
+ cam_periph_unlock(periph);
break;
}
@@ -2333,6 +2318,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
sizeof (*th), /*sense_flags*/0);
if (error) {
free(data, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
@@ -2355,6 +2341,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
" returning EINVAL\n");
free(data, M_TEMP);
error = EINVAL;
+ cam_periph_unlock(periph);
break;
}
@@ -2363,6 +2350,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
/*sense_flags*/0);
if (error) {
free(data, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
@@ -2371,6 +2359,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
bcopy(&data->entry, &te->entry,
sizeof(struct cd_toc_entry));
free(data, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETPATCH:
@@ -2379,15 +2368,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETPATCH\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETPATCH\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2400,6 +2392,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[3].channels = arg->patch[3];
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCGETVOL:
@@ -2408,15 +2401,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCGETVOL\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCGETVOL\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2428,6 +2424,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
arg->vol[2] = page->audio.port[2].volume;
arg->vol[3] = page->audio.port[3].volume;
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETVOL:
@@ -2436,15 +2433,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETVOL\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETVOL\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2458,6 +2458,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[2].volume = arg->vol[2];
page->audio.port[3].volume = arg->vol[3];
error = cdsetmode(periph, &params);
+ cam_periph_unlock(periph);
free(params.mode_buf, M_TEMP);
}
break;
@@ -2466,15 +2467,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETMONO\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETMONO\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2486,6 +2490,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, &params);
+ cam_periph_unlock(periph);
free(params.mode_buf, M_TEMP);
}
break;
@@ -2494,15 +2499,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETSTEREO\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETSTEREO\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2515,6 +2523,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[3].channels = 0;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETMUTE:
@@ -2522,15 +2531,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETMUTE\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETMUTE\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(&params, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2541,6 +2553,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[3].channels = 0;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETLEFT:
@@ -2548,16 +2561,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETLEFT\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
-
+
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETLEFT\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2568,6 +2583,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[3].channels = 0;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETRIGHT:
@@ -2575,16 +2591,18 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cd_mode_params params;
union cd_pages *page;
- CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
- ("trying to do CDIOCSETRIGHT\n"));
-
params.alloc_len = sizeof(union cd_mode_data_6_10);
params.mode_buf = malloc(params.alloc_len, M_TEMP,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETRIGHT\n"));
+
error = cdgetmode(periph, &params, AUDIO_PAGE);
if (error) {
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(&params);
@@ -2595,31 +2613,48 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
page->audio.port[3].channels = 0;
error = cdsetmode(periph, &params);
free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
}
break;
case CDIOCRESUME:
+ cam_periph_lock(periph);
error = cdpause(periph, 1);
+ cam_periph_unlock(periph);
break;
case CDIOCPAUSE:
+ cam_periph_lock(periph);
error = cdpause(periph, 0);
+ cam_periph_unlock(periph);
break;
case CDIOCSTART:
+ cam_periph_lock(periph);
error = cdstartunit(periph, 0);
+ cam_periph_unlock(periph);
break;
case CDIOCCLOSE:
+ cam_periph_lock(periph);
error = cdstartunit(periph, 1);
+ cam_periph_unlock(periph);
break;
case CDIOCSTOP:
+ cam_periph_lock(periph);
error = cdstopunit(periph, 0);
+ cam_periph_unlock(periph);
break;
case CDIOCEJECT:
+ cam_periph_lock(periph);
error = cdstopunit(periph, 1);
+ cam_periph_unlock(periph);
break;
case CDIOCALLOW:
+ cam_periph_lock(periph);
cdprevent(periph, PR_ALLOW);
+ cam_periph_unlock(periph);
break;
case CDIOCPREVENT:
+ cam_periph_lock(periph);
cdprevent(periph, PR_PREVENT);
+ cam_periph_unlock(periph);
break;
case CDIOCSETDEBUG:
/* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */
@@ -2634,10 +2669,14 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
error = ENOTTY;
break;
case CDRIOCREADSPEED:
+ cam_periph_lock(periph);
error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED);
+ cam_periph_unlock(periph);
break;
case CDRIOCWRITESPEED:
+ cam_periph_lock(periph);
error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr);
+ cam_periph_unlock(periph);
break;
case DVDIOCSENDKEY:
case DVDIOCREPORTKEY: {
@@ -2645,10 +2684,12 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
authinfo = (struct dvd_authinfo *)addr;
+ cam_periph_lock(periph);
if (cmd == DVDIOCREPORTKEY)
error = cdreportkey(periph, authinfo);
else
error = cdsendkey(periph, authinfo);
+ cam_periph_unlock(periph);
break;
}
case DVDIOCREADSTRUCTURE: {
@@ -2656,21 +2697,27 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
dvdstruct = (struct dvd_struct *)addr;
+ cam_periph_lock(periph);
error = cdreaddvdstructure(periph, dvdstruct);
+ cam_periph_unlock(periph);
break;
}
default:
+ cam_periph_lock(periph);
error = cam_periph_ioctl(periph, cmd, addr, cderror);
+ cam_periph_unlock(periph);
break;
}
- cam_periph_unlock(periph);
-
+ cam_periph_lock(periph);
+ cam_periph_unhold(periph);
+
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n"));
if (error && bootverbose) {
printf("scsi_cd.c::ioctl cmd=%08lx error=%d\n", cmd, error);
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -2869,8 +2916,11 @@ cdsize(struct cam_periph *periph, u_int32_t *size)
ccb = cdgetccb(periph, /* priority */ 1);
+ /* XXX Should be M_WAITOK */
rcap_buf = malloc(sizeof(struct scsi_read_capacity_data),
- M_TEMP, M_WAITOK);
+ M_TEMP, M_NOWAIT);
+ if (rcap_buf == NULL)
+ return (ENOMEM);
scsi_read_capacity(&ccb->csio,
/*retries*/ 1,
diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c
index 7ca7391..337cea3 100644
--- a/sys/cam/scsi/scsi_ch.c
+++ b/sys/cam/scsi/scsi_ch.c
@@ -173,8 +173,6 @@ struct ch_softc {
int sc_settledelay; /* delay for settle */
};
-#define CHUNIT(x) (minor((x)))
-
static d_open_t chopen;
static d_close_t chclose;
static d_ioctl_t chioctl;
@@ -213,7 +211,7 @@ PERIPHDRIVER_DECLARE(ch, chdriver);
static struct cdevsw ch_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
.d_open = chopen,
.d_close = chclose,
.d_ioctl = chioctl,
@@ -376,9 +374,11 @@ chregister(struct cam_periph *periph, void *arg)
DEVSTAT_PRIORITY_OTHER);
/* Register the device */
+ cam_periph_unlock(periph);
softc->dev = make_dev(&ch_cdevsw, periph->unit_number, UID_ROOT,
GID_OPERATOR, 0600, "%s%d", periph->periph_name,
periph->unit_number);
+ cam_periph_lock(periph);
softc->dev->si_drv1 = periph;
/*
@@ -393,10 +393,10 @@ chregister(struct cam_periph *periph, void *arg)
xpt_action((union ccb *)&csa);
/*
- * Lock this peripheral until we are setup.
+ * Lock this periph until we are setup.
* This first call can't block
*/
- (void)cam_periph_lock(periph, PRIBIO);
+ (void)cam_periph_hold(periph, PRIBIO);
xpt_schedule(periph, /*priority*/5);
return(CAM_REQ_CMP);
@@ -408,31 +408,30 @@ chopen(struct cdev *dev, int flags, int fmt, struct thread *td)
struct cam_periph *periph;
struct ch_softc *softc;
int error;
- int s;
periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL)
- return(ENXIO);
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return (ENXIO);
softc = (struct ch_softc *)periph->softc;
- s = splsoftcam();
+ cam_periph_lock(periph);
+
if (softc->flags & CH_FLAG_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(ENXIO);
}
- if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
- splx(s);
- return (error);
- }
-
- splx(s);
-
- if ((softc->flags & CH_FLAG_OPEN) == 0) {
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- return(ENXIO);
+ if ((softc->flags & CH_FLAG_OPEN) == 0)
softc->flags |= CH_FLAG_OPEN;
+ else
+ cam_periph_release(periph);
+
+ if ((error = cam_periph_hold(periph, PRIBIO | PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
}
/*
@@ -445,6 +444,7 @@ chopen(struct cdev *dev, int flags, int fmt, struct thread *td)
return(error);
}
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return(error);
@@ -465,8 +465,7 @@ chclose(struct cdev *dev, int flag, int fmt, struct thread *td)
softc = (struct ch_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return(error);
+ cam_periph_lock(periph);
softc->flags &= ~CH_FLAG_OPEN;
@@ -480,24 +479,20 @@ static void
chstart(struct cam_periph *periph, union ccb *start_ccb)
{
struct ch_softc *softc;
- int s;
softc = (struct ch_softc *)periph->softc;
switch (softc->state) {
case CH_STATE_NORMAL:
{
- s = splbio();
if (periph->immediate_priority <= periph->pinfo.priority){
start_ccb->ccb_h.ccb_state = CH_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
- } else
- splx(s);
+ }
break;
}
case CH_STATE_PROBE:
@@ -670,7 +665,7 @@ chdone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case CH_CCB_WAITING:
@@ -709,6 +704,7 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
if (periph == NULL)
return(ENXIO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering chioctl\n"));
softc = (struct ch_softc *)periph->softc;
@@ -729,8 +725,10 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
break;
default:
- if ((flag & FWRITE) == 0)
+ if ((flag & FWRITE) == 0) {
+ cam_periph_unlock(periph);
return (EBADF);
+ }
}
switch (cmd) {
@@ -754,8 +752,10 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
int new_picker = *(int *)addr;
- if (new_picker > (softc->sc_counts[CHET_MT] - 1))
- return (EINVAL);
+ if (new_picker > (softc->sc_counts[CHET_MT] - 1)) {
+ error = EINVAL;
+ break;
+ }
softc->sc_picker = softc->sc_firsts[CHET_MT] + new_picker;
break;
}
@@ -794,6 +794,7 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
break;
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -1091,8 +1092,10 @@ chgetelemstatus(struct cam_periph *periph,
* we can allocate enough storage for all of them. We assume
* that the first one can fit into 1k.
*/
+ cam_periph_unlock(periph);
data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK);
+ cam_periph_lock(periph);
ccb = cam_periph_getccb(periph, /*priority*/ 1);
scsi_read_element_status(&ccb->csio,
@@ -1113,6 +1116,7 @@ chgetelemstatus(struct cam_periph *periph,
if (error)
goto done;
+ cam_periph_unlock(periph);
st_hdr = (struct read_element_status_header *)data;
pg_hdr = (struct read_element_status_page_header *)((uintptr_t)st_hdr +
@@ -1130,6 +1134,7 @@ chgetelemstatus(struct cam_periph *periph,
free(data, M_DEVBUF);
data = (caddr_t)malloc(size, M_DEVBUF, M_WAITOK);
+ cam_periph_lock(periph);
scsi_read_element_status(&ccb->csio,
/* retries */ 1,
/* cbfcnp */ chdone,
@@ -1149,6 +1154,7 @@ chgetelemstatus(struct cam_periph *periph,
if (error)
goto done;
+ cam_periph_unlock(periph);
/*
* Fill in the user status array.
@@ -1186,6 +1192,7 @@ chgetelemstatus(struct cam_periph *periph,
error = copyout(user_data,
cesr->cesr_element_status,
avail * sizeof(struct changer_element_status));
+ cam_periph_lock(periph);
done:
xpt_release_ccb(ccb);
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index b4863f6..f799e44 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#endif /* _KERNEL */
#include <sys/devicestat.h>
@@ -61,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_message.h>
@@ -133,6 +136,7 @@ struct da_softc {
struct task sysctl_task;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
+ struct callout sendordered_c;
};
struct da_quirk_entry {
@@ -551,8 +555,6 @@ static struct periph_driver dadriver =
PERIPHDRIVER_DECLARE(da, dadriver);
-static SLIST_HEAD(,da_softc) softc_list;
-
static int
daopen(struct disk *dp)
{
@@ -560,34 +562,35 @@ daopen(struct disk *dp)
struct da_softc *softc;
int unit;
int error;
- int s;
- s = splsoftcam();
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL) {
- splx(s);
return (ENXIO);
}
- unit = periph->unit_number;
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ return(ENXIO);
+ }
+
+ cam_periph_lock(periph);
+ if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
+ }
+
+ unit = periph->unit_number;
softc = (struct da_softc *)periph->softc;
+ softc->flags |= DA_FLAG_OPEN;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
unit));
- if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
- return (error); /* error code from tsleep */
-
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- return(ENXIO);
- softc->flags |= DA_FLAG_OPEN;
-
if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
/* Invalidate our pack information. */
softc->flags &= ~DA_FLAG_PACK_INVALID;
}
- splx(s);
error = dagetcapacity(periph);
@@ -610,6 +613,7 @@ daopen(struct disk *dp)
softc->flags &= ~DA_FLAG_OPEN;
cam_periph_release(periph);
}
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (error);
}
@@ -619,18 +623,21 @@ daclose(struct disk *dp)
{
struct cam_periph *periph;
struct da_softc *softc;
- int error;
+ int error;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
return (ENXIO);
- softc = (struct da_softc *)periph->softc;
-
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
- return (error); /* error code from tsleep */
+ cam_periph_lock(periph);
+ if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
}
+ softc = (struct da_softc *)periph->softc;
+
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
union ccb *ccb;
@@ -692,6 +699,7 @@ daclose(struct disk *dp)
}
softc->flags &= ~DA_FLAG_OPEN;
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
cam_periph_release(periph);
return (0);
@@ -707,7 +715,6 @@ dastrategy(struct bio *bp)
{
struct cam_periph *periph;
struct da_softc *softc;
- int s;
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
if (periph == NULL) {
@@ -715,6 +722,9 @@ dastrategy(struct bio *bp)
return;
}
softc = (struct da_softc *)periph->softc;
+
+ cam_periph_lock(periph);
+
#if 0
/*
* check it's not too big a transfer for our adapter
@@ -727,13 +737,12 @@ dastrategy(struct bio *bp)
* after we are in the queue. Otherwise, we might not properly
* clean up one of the buffers.
*/
- s = splbio();
/*
* If the device has been made invalid, error out
*/
if ((softc->flags & DA_FLAG_PACK_INVALID)) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
@@ -743,12 +752,11 @@ dastrategy(struct bio *bp)
*/
bioq_disksort(&softc->bio_queue, bp);
- splx(s);
-
/*
* Schedule ourselves for performing the work.
*/
xpt_schedule(periph, /* XXX priority */1);
+ cam_periph_unlock(periph);
return;
}
@@ -773,6 +781,7 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng
return (ENXIO);
if (length > 0) {
+ periph->flags |= CAM_PERIPH_POLLED;
xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
csio.ccb_h.ccb_state = DA_CCB_DUMP;
scsi_read_write(&csio,
@@ -798,10 +807,11 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng
else
printf("status == 0x%x, scsi status == 0x%x\n",
csio.ccb_h.status, csio.scsi_status);
+ periph->flags |= CAM_PERIPH_POLLED;
return(EIO);
}
return(0);
- }
+ }
/*
* Sync the disk cache contents to the physical media.
@@ -840,6 +850,7 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng
}
}
}
+ periph->flags &= ~CAM_PERIPH_POLLED;
return (0);
}
@@ -849,8 +860,6 @@ dainit(void)
cam_status status;
struct cam_path *path;
- SLIST_INIT(&softc_list);
-
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
@@ -876,13 +885,6 @@ dainit(void)
"due to status 0x%x!\n", status);
} else if (da_send_ordered) {
- /*
- * Schedule a periodic event to occasionally send an
- * ordered tag to a device.
- */
- timeout(dasendorderedtag, NULL,
- (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
-
/* Register our shutdown event handler */
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
@@ -893,7 +895,6 @@ dainit(void)
static void
daoninvalidate(struct cam_periph *periph)
{
- int s;
struct da_softc *softc;
struct ccb_setasync csa;
@@ -913,21 +914,11 @@ daoninvalidate(struct cam_periph *periph)
softc->flags |= DA_FLAG_PACK_INVALID;
/*
- * Although the oninvalidate() routines are always called at
- * splsoftcam, we need to be at splbio() here to keep the buffer
- * queue from being modified while we traverse it.
- */
- s = splbio();
-
- /*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
bioq_flush(&softc->bio_queue, NULL, ENXIO);
- splx(s);
-
- SLIST_REMOVE(&softc_list, softc, da_softc, links);
disk_gone(softc->disk);
xpt_print(periph->path, "lost device\n");
@@ -949,6 +940,14 @@ dacleanup(struct cam_periph *periph)
xpt_print(periph->path, "can't remove sysctl context\n");
}
disk_destroy(softc->disk);
+
+ /*
+ * XXX Gotta drop the periph lock so that the drain can complete with
+ * deadlocking on the lock. Hopefully dropping here is safe.
+ */
+ cam_periph_unlock(periph);
+ callout_drain(&softc->sendordered_c);
+ cam_periph_lock(periph);
free(softc, M_DEVBUF);
}
@@ -963,6 +962,7 @@ daasync(void *callback_arg, u_int32_t code,
case AC_FOUND_DEVICE:
{
struct ccb_getdev *cgd;
+ struct cam_sim *sim;
cam_status status;
cgd = (struct ccb_getdev *)arg;
@@ -979,6 +979,7 @@ daasync(void *callback_arg, u_int32_t code,
* this device and start the probe
* process.
*/
+ sim = xpt_path_sim(cgd->ccb_h.path);
status = cam_periph_alloc(daregister, daoninvalidate,
dacleanup, dastart,
"da", CAM_PERIPH_BIO,
@@ -996,10 +997,8 @@ daasync(void *callback_arg, u_int32_t code,
{
struct da_softc *softc;
struct ccb_hdr *ccbh;
- int s;
softc = (struct da_softc *)periph->softc;
- s = splsoftcam();
/*
* Don't fail on the expected unit attention
* that will occur.
@@ -1007,7 +1006,6 @@ daasync(void *callback_arg, u_int32_t code,
softc->flags |= DA_FLAG_RETRY_UA;
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
ccbh->ccb_state |= DA_CCB_RETRY_UA;
- splx(s);
/* FALLTHROUGH*/
}
default:
@@ -1024,8 +1022,10 @@ dasysctlinit(void *context, int pending)
char tmpstr[80], tmpstr2[80];
periph = (struct cam_periph *)context;
- softc = (struct da_softc *)periph->softc;
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ return;
+ softc = (struct da_softc *)periph->softc;
snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
@@ -1038,6 +1038,7 @@ dasysctlinit(void *context, int pending)
if (softc->sysctl_tree == NULL) {
printf("dasysctlinit: unable to allocate sysctl tree\n");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
return;
}
@@ -1051,6 +1052,7 @@ dasysctlinit(void *context, int pending)
"Minimum CDB size");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
}
static int
@@ -1088,7 +1090,6 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
static cam_status
daregister(struct cam_periph *periph, void *arg)
{
- int s;
struct da_softc *softc;
struct ccb_setasync csa;
struct ccb_pathinq cpi;
@@ -1178,17 +1179,10 @@ daregister(struct cam_periph *periph, void *arg)
softc->minimum_cmd_size = 16;
/*
- * Block our timeout handler while we
- * add this softc to the dev list.
- */
- s = splsoftclock();
- SLIST_INSERT_HEAD(&softc_list, softc, links);
- splx(s);
-
- /*
* Register this media as a disk
*/
+ mtx_unlock(periph->sim->mtx);
softc->disk = disk_alloc();
softc->disk->d_open = daopen;
softc->disk->d_close = daclose;
@@ -1198,10 +1192,11 @@ daregister(struct cam_periph *periph, void *arg)
softc->disk->d_drv1 = periph;
softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
softc->disk->d_unit = periph->unit_number;
- softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
+ softc->disk->d_flags = 0;
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
disk_create(softc->disk, DISK_VERSION);
+ mtx_lock(periph->sim->mtx);
/*
* Add async callbacks for bus reset and
@@ -1217,13 +1212,24 @@ daregister(struct cam_periph *periph, void *arg)
csa.callback = daasync;
csa.callback_arg = periph;
xpt_action((union ccb *)&csa);
+
/*
- * Lock this peripheral until we are setup.
- * This first call can't block
+ * Take an exclusive refcount on the periph while dastart is called
+ * to finish the probe. The reference will be dropped in dadone at
+ * the end of probe.
*/
- (void)cam_periph_lock(periph, PRIBIO);
+ (void)cam_periph_hold(periph, PRIBIO);
xpt_schedule(periph, /*priority*/5);
+ /*
+ * Schedule a periodic event to occasionally send an
+ * ordered tag to a device.
+ */
+ callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
+ callout_reset(&softc->sendordered_c,
+ (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
+ dasendorderedtag, softc);
+
return(CAM_REQ_CMP);
}
@@ -1234,18 +1240,15 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
softc = (struct da_softc *)periph->softc;
-
switch (softc->state) {
case DA_STATE_NORMAL:
{
/* Pull a buffer from the queue and get going on it */
struct bio *bp;
- int s;
/*
* See if there is a buf with work for us to do..
*/
- s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
@@ -1254,13 +1257,10 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else {
- int oldspl;
u_int8_t tag_code;
bioq_remove(&softc->bio_queue, bp);
@@ -1307,11 +1307,9 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
* Block out any asyncronous callbacks
* while we touch the pending ccb list.
*/
- oldspl = splcam();
LIST_INSERT_HEAD(&softc->pending_ccbs,
&start_ccb->ccb_h, periph_links.le);
softc->outstanding_cmds++;
- splx(oldspl);
/* We expect a unit attention from this device */
if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
@@ -1321,7 +1319,6 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1446,12 +1443,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
case DA_CCB_BUFFER_IO:
{
struct bio *bp;
- int oldspl;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
int error;
- int s;
int sf;
if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
@@ -1469,8 +1464,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
}
if (error != 0) {
- s = splbio();
-
if (error == ENXIO) {
/*
* Catastrophic error. Mark our pack as
@@ -1491,7 +1484,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* proper order should it attempt to recover.
*/
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
bp->bio_error = error;
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
@@ -1519,12 +1511,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* Block out any asyncronous callbacks
* while we touch the pending ccb list.
*/
- oldspl = splcam();
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
softc->outstanding_cmds--;
if (softc->outstanding_cmds == 0)
softc->flags |= DA_FLAG_WENT_IDLE;
- splx(oldspl);
biodone(bp);
break;
@@ -1710,7 +1700,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case DA_CCB_WAITING:
@@ -1833,7 +1823,9 @@ dagetcapacity(struct cam_periph *periph)
/* Do a read capacity */
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
M_TEMP,
- M_WAITOK);
+ M_NOWAIT);
+ if (rcap == NULL)
+ return (ENOMEM);
ccb = cam_periph_getccb(periph, /*priority*/1);
scsi_read_capacity(&ccb->csio,
@@ -1959,27 +1951,22 @@ dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector)
static void
dasendorderedtag(void *arg)
{
- struct da_softc *softc;
- int s;
- if (da_send_ordered) {
- for (softc = SLIST_FIRST(&softc_list);
- softc != NULL;
- softc = SLIST_NEXT(softc, links)) {
- s = splsoftcam();
- if ((softc->ordered_tag_count == 0)
- && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
- softc->flags |= DA_FLAG_NEED_OTAG;
- }
- if (softc->outstanding_cmds > 0)
- softc->flags &= ~DA_FLAG_WENT_IDLE;
+ struct da_softc *softc = arg;
- softc->ordered_tag_count = 0;
- splx(s);
+ if (da_send_ordered) {
+ if ((softc->ordered_tag_count == 0)
+ && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
+ softc->flags |= DA_FLAG_NEED_OTAG;
}
- /* Queue us up again */
- timeout(dasendorderedtag, NULL,
- (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
+ if (softc->outstanding_cmds > 0)
+ softc->flags &= ~DA_FLAG_WENT_IDLE;
+
+ softc->ordered_tag_count = 0;
}
+ /* Queue us up again */
+ callout_reset(&softc->sendordered_c,
+ (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
+ dasendorderedtag, softc);
}
/*
diff --git a/sys/cam/scsi/scsi_low.c b/sys/cam/scsi/scsi_low.c
index 73aa505..296af9b 100644
--- a/sys/cam/scsi/scsi_low.c
+++ b/sys/cam/scsi/scsi_low.c
@@ -966,7 +966,7 @@ scsi_low_rescan_bus_cam(slp)
struct scsi_low_softc *slp;
{
struct cam_path *path;
- union ccb *ccb = xpt_alloc_ccb();
+ union ccb *ccb = xpt_alloc_ccb(NULL);
cam_status status;
bzero(ccb, sizeof(union ccb));
@@ -1343,7 +1343,7 @@ scsi_low_attach_cam(slp)
slp->sl_si.sim = cam_sim_alloc(scsi_low_scsi_action_cam,
scsi_low_poll_cam,
DEVPORT_DEVNAME(slp->sl_dev), slp,
- DEVPORT_DEVUNIT(slp->sl_dev),
+ DEVPORT_DEVUNIT(slp->sl_dev), &Giant,
slp->sl_openings, tagged_openings, devq);
if (slp->sl_si.sim == NULL) {
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index f08a7ed..62aaccf 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_queue.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_pass.h>
@@ -106,7 +107,7 @@ PERIPHDRIVER_DECLARE(pass, passdriver);
static struct cdevsw pass_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
.d_open = passopen,
.d_close = passclose,
.d_ioctl = passioctl,
@@ -201,6 +202,7 @@ passasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg)
{
struct cam_periph *periph;
+ struct cam_sim *sim;
periph = (struct cam_periph *)callback_arg;
@@ -219,6 +221,7 @@ passasync(void *callback_arg, u_int32_t code,
* 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,
@@ -293,9 +296,11 @@ passregister(struct cam_periph *periph, void *arg)
DEVSTAT_PRIORITY_PASS);
/* Register the device */
+ mtx_unlock(periph->sim->mtx);
softc->dev = make_dev(&pass_cdevsw, unit2minor(periph->unit_number),
UID_ROOT, GID_OPERATOR, 0600, "%s%d",
periph->periph_name, periph->unit_number);
+ mtx_lock(periph->sim->mtx);
softc->dev->si_drv1 = periph;
/*
@@ -321,19 +326,20 @@ passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
struct cam_periph *periph;
struct pass_softc *softc;
int error;
- int s;
error = 0; /* default to no error */
periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL)
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
return (ENXIO);
+ cam_periph_lock(periph);
+
softc = (struct pass_softc *)periph->softc;
- s = splsoftcam();
if (softc->flags & PASS_FLAG_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(ENXIO);
}
@@ -342,7 +348,8 @@ passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
*/
error = securelevel_gt(td->td_ucred, 1);
if (error) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(error);
}
@@ -350,7 +357,8 @@ passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
* Only allow read-write access.
*/
if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(EPERM);
}
@@ -359,21 +367,16 @@ passopen(struct cdev *dev, int flags, int fmt, struct thread *td)
*/
if ((flags & O_NONBLOCK) != 0) {
xpt_print(periph->path, "can't do nonblocking access\n");
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(EINVAL);
}
- if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
- splx(s);
- return (error);
- }
-
- splx(s);
-
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);
@@ -386,17 +389,14 @@ passclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_periph *periph;
struct pass_softc *softc;
- int error;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
- softc = (struct pass_softc *)periph->softc;
-
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return (error);
+ cam_periph_lock(periph);
+ softc = (struct pass_softc *)periph->softc;
softc->flags &= ~PASS_FLAG_OPEN;
cam_periph_unlock(periph);
@@ -409,18 +409,15 @@ static void
passstart(struct cam_periph *periph, union ccb *start_ccb)
{
struct pass_softc *softc;
- int s;
softc = (struct pass_softc *)periph->softc;
switch (softc->state) {
case PASS_STATE_NORMAL:
- s = splbio();
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;
- splx(s);
wakeup(&periph->ccb_list);
break;
}
@@ -454,6 +451,7 @@ passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
if (periph == NULL)
return(ENXIO);
+ cam_periph_lock(periph);
softc = (struct pass_softc *)periph->softc;
error = 0;
@@ -492,7 +490,7 @@ passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
inccb->ccb_h.pinfo.priority);
ccb_malloced = 0;
} else {
- ccb = xpt_alloc_ccb();
+ ccb = xpt_alloc_ccb_nowait(periph->sim);
if (ccb != NULL)
xpt_setup_ccb(&ccb->ccb_h, periph->path,
@@ -520,6 +518,7 @@ passioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
break;
}
+ cam_periph_unlock(periph);
return(error);
}
@@ -568,7 +567,14 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
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.
diff --git a/sys/cam/scsi/scsi_pt.c b/sys/cam/scsi/scsi_pt.c
index 752ddbd..9f474d9 100644
--- a/sys/cam/scsi/scsi_pt.c
+++ b/sys/cam/scsi/scsi_pt.c
@@ -119,7 +119,7 @@ PERIPHDRIVER_DECLARE(pt, ptdriver);
static struct cdevsw pt_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
.d_open = ptopen,
.d_close = ptclose,
.d_read = physread,
@@ -138,40 +138,30 @@ ptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct cam_periph *periph;
struct pt_softc *softc;
- int unit;
- int error;
- int s;
+ int error = 0;
- unit = minor(dev);
periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL)
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP)
return (ENXIO);
softc = (struct pt_softc *)periph->softc;
- s = splsoftcam();
+ cam_periph_lock(periph);
if (softc->flags & PT_FLAG_DEVICE_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(ENXIO);
}
- CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
- ("ptopen: dev=%s (unit %d)\n", devtoname(dev), unit));
-
- if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
- splx(s);
- return (error); /* error code from tsleep */
+ if ((softc->flags & PT_FLAG_OPEN) == 0)
+ softc->flags |= PT_FLAG_OPEN;
+ else {
+ error = EBUSY;
+ cam_periph_release(periph);
}
- splx(s);
-
- if ((softc->flags & PT_FLAG_OPEN) == 0) {
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- error = ENXIO;
- else
- softc->flags |= PT_FLAG_OPEN;
- } else
- error = EBUSY;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
+ ("ptopen: dev=%s\n", devtoname(dev)));
cam_periph_unlock(periph);
return (error);
@@ -182,7 +172,6 @@ ptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_periph *periph;
struct pt_softc *softc;
- int error;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
@@ -190,8 +179,7 @@ ptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
softc = (struct pt_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return (error); /* error code from tsleep */
+ cam_periph_lock(periph);
softc->flags &= ~PT_FLAG_OPEN;
cam_periph_unlock(periph);
@@ -209,7 +197,6 @@ ptstrategy(struct bio *bp)
{
struct cam_periph *periph;
struct pt_softc *softc;
- int s;
periph = (struct cam_periph *)bp->bio_dev->si_drv1;
bp->bio_resid = bp->bio_bcount;
@@ -217,20 +204,14 @@ ptstrategy(struct bio *bp)
biofinish(bp, NULL, ENXIO);
return;
}
+ cam_periph_lock(periph);
softc = (struct pt_softc *)periph->softc;
/*
- * Mask interrupts so that the pack cannot be invalidated until
- * after we are in the queue. Otherwise, we might not properly
- * clean up one of the buffers.
- */
- s = splbio();
-
- /*
* If the device has been made invalid, error out
*/
if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
@@ -240,12 +221,11 @@ ptstrategy(struct bio *bp)
*/
bioq_insert_tail(&softc->bio_queue, bp);
- splx(s);
-
/*
* Schedule ourselves for performing the work.
*/
xpt_schedule(periph, /* XXX priority */1);
+ cam_periph_unlock(periph);
return;
}
@@ -352,7 +332,6 @@ ptctor(struct cam_periph *periph, void *arg)
static void
ptoninvalidate(struct cam_periph *periph)
{
- int s;
struct pt_softc *softc;
struct ccb_setasync csa;
@@ -372,21 +351,12 @@ ptoninvalidate(struct cam_periph *periph)
softc->flags |= PT_FLAG_DEVICE_INVALID;
/*
- * Although the oninvalidate() routines are always called at
- * splsoftcam, we need to be at splbio() here to keep the buffer
- * queue from being modified while we traverse it.
- */
- s = splbio();
-
- /*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
bioq_flush(&softc->bio_queue, NULL, ENXIO);
- splx(s);
-
xpt_print(periph->path, "lost device\n");
}
@@ -445,10 +415,8 @@ ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
{
struct pt_softc *softc;
struct ccb_hdr *ccbh;
- int s;
softc = (struct pt_softc *)periph->softc;
- s = splsoftcam();
/*
* Don't fail on the expected unit attention
* that will occur.
@@ -456,7 +424,6 @@ ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
softc->flags |= PT_FLAG_RETRY_UA;
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
ccbh->ccb_state |= PT_CCB_RETRY_UA;
- splx(s);
}
/* FALLTHROUGH */
default:
@@ -470,14 +437,12 @@ ptstart(struct cam_periph *periph, union ccb *start_ccb)
{
struct pt_softc *softc;
struct bio *bp;
- int s;
softc = (struct pt_softc *)periph->softc;
/*
* See if there is a buf with work for us to do..
*/
- s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
@@ -486,14 +451,10 @@ ptstart(struct cam_periph *periph, union ccb *start_ccb)
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else {
- int oldspl;
-
bioq_remove(&softc->bio_queue, bp);
devstat_start_transaction_bio(softc->device_stats, bp);
@@ -515,14 +476,11 @@ ptstart(struct cam_periph *periph, union ccb *start_ccb)
* Block out any asyncronous callbacks
* while we touch the pending ccb list.
*/
- oldspl = splcam();
LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h,
periph_links.le);
- splx(oldspl);
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
@@ -546,12 +504,10 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
case PT_CCB_BUFFER_IO_UA:
{
struct bio *bp;
- int oldspl;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
int error;
- int s;
int sf;
if ((csio->ccb_h.ccb_state & PT_CCB_RETRY_UA) != 0)
@@ -568,8 +524,6 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
return;
}
if (error != 0) {
- s = splbio();
-
if (error == ENXIO) {
/*
* Catastrophic error. Mark our device
@@ -586,7 +540,6 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
* proper order should it attempt to recover.
*/
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
bp->bio_error = error;
bp->bio_resid = bp->bio_bcount;
bp->bio_flags |= BIO_ERROR;
@@ -614,9 +567,7 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
* Block out any asyncronous callbacks
* while we touch the pending ccb list.
*/
- oldspl = splcam();
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
- splx(oldspl);
biofinish(bp, softc->device_stats, 0);
break;
@@ -647,7 +598,7 @@ ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
{
struct cam_periph *periph;
struct pt_softc *softc;
- int error;
+ int error = 0;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
@@ -655,9 +606,7 @@ ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
softc = (struct pt_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
- return (error); /* error code from tsleep */
- }
+ cam_periph_lock(periph);
switch(cmd) {
case PTIOCGETTIMEOUT:
@@ -667,20 +616,14 @@ ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
*(int *)addr = 0;
break;
case PTIOCSETTIMEOUT:
- {
- int s;
-
if (*(int *)addr < 1) {
error = EINVAL;
break;
}
- s = splsoftcam();
softc->io_timeout = *(int *)addr * 1000;
- splx(s);
break;
- }
default:
error = cam_periph_ioctl(periph, cmd, addr, pterror);
break;
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index 013e421..170d35c 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -447,37 +447,33 @@ saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
struct sa_softc *softc;
int unit;
int error;
- int s;
unit = SAUNIT(dev);
- s = splsoftcam();
periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL) {
- (void) splx(s);
- return (ENXIO);
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ return (ENXIO);
}
+
+ cam_periph_lock(periph);
+
softc = (struct sa_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
- splx(s);
- return (error);
- }
- splx(s);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
- if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
- cam_periph_unlock(periph);
- return (ENXIO);
- }
-
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 1;
cam_periph_unlock(periph);
return (0);
}
+ if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
+ }
+
if (softc->flags & SA_FLAG_OPEN) {
error = EBUSY;
} else if (softc->flags & SA_FLAG_INVALID) {
@@ -499,17 +495,23 @@ saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
if (error && (flags & O_NONBLOCK)) {
softc->flags |= SA_FLAG_OPEN;
softc->open_pending_mount = 1;
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (0);
}
}
if (error) {
+ cam_periph_unhold(periph);
+ cam_periph_unlock(periph);
cam_periph_release(periph);
- } else {
- saprevent(periph, PR_PREVENT);
- softc->flags |= SA_FLAG_OPEN;
+ return (error);
}
+
+ saprevent(periph, PR_PREVENT);
+ softc->flags |= SA_FLAG_OPEN;
+
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (error);
}
@@ -528,32 +530,35 @@ saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
+
softc = (struct sa_softc *)periph->softc;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
- return (error);
- }
-
softc->open_rdonly = 0;
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 0;
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
if (softc->open_pending_mount) {
softc->flags &= ~SA_FLAG_OPEN;
softc->open_pending_mount = 0;
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
+ if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
+ cam_periph_unlock(periph);
+ return (error);
+ }
+
/*
* Were we writing the tape?
*/
@@ -661,6 +666,7 @@ saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
sareservereleaseunit(periph, FALSE);
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
cam_periph_release(periph);
@@ -677,7 +683,6 @@ sastrategy(struct bio *bp)
{
struct cam_periph *periph;
struct sa_softc *softc;
- int s;
bp->bio_resid = bp->bio_bcount;
if (SA_IS_CTRL(bp->bio_dev)) {
@@ -689,18 +694,18 @@ sastrategy(struct bio *bp)
biofinish(bp, NULL, ENXIO);
return;
}
- softc = (struct sa_softc *)periph->softc;
+ cam_periph_lock(periph);
- s = splsoftcam();
+ softc = (struct sa_softc *)periph->softc;
if (softc->flags & SA_FLAG_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
if (softc->flags & SA_FLAG_TAPE_FROZEN) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EPERM);
return;
}
@@ -711,16 +716,15 @@ sastrategy(struct bio *bp)
* file descriptor.
*/
if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EBADF);
return;
}
- splx(s);
-
if (softc->open_pending_mount) {
int error = samount(periph, 0, bp->bio_dev);
if (error) {
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
@@ -733,6 +737,7 @@ sastrategy(struct bio *bp)
* If it's a null transfer, return immediately
*/
if (bp->bio_bcount == 0) {
+ cam_periph_unlock(periph);
biodone(bp);
return;
}
@@ -750,6 +755,7 @@ sastrategy(struct bio *bp)
xpt_print(periph->path, "Invalid request. Fixed block "
"device requests must be a multiple of %d bytes\n",
softc->min_blk);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EINVAL);
return;
}
@@ -765,18 +771,12 @@ sastrategy(struct bio *bp)
}
printf("between %d and %d bytes\n", softc->min_blk,
softc->max_blk);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EINVAL);
return;
}
/*
- * Mask interrupts so that the device cannot be invalidated until
- * after we are in the queue. Otherwise, we might not properly
- * clean up one of the buffers.
- */
- s = splbio();
-
- /*
* Place it at the end of the queue.
*/
bioq_insert_tail(&softc->bio_queue, bp);
@@ -791,12 +791,12 @@ sastrategy(struct bio *bp)
CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
("sastrategy: queue count now %d\n", softc->queue_count));
}
- splx(s);
/*
* Schedule ourselves for performing the work.
*/
xpt_schedule(periph, 1);
+ cam_periph_unlock(periph);
return;
}
@@ -819,7 +819,6 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
struct sa_softc *softc;
scsi_space_code spaceop;
int didlockperiph = 0;
- int s;
int mode;
int error = 0;
@@ -831,6 +830,7 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
softc = (struct sa_softc *)periph->softc;
/*
@@ -856,13 +856,10 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
* other thread that has this device open to do
* an MTIOCERRSTAT that would clear latched status.
*/
- s = splsoftcam();
if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
- error = cam_periph_lock(periph, PRIBIO|PCATCH);
- if (error != 0) {
- splx(s);
+ error = cam_periph_hold(periph, PRIBIO|PCATCH);
+ if (error != 0)
return (error);
- }
didlockperiph = 1;
}
break;
@@ -895,12 +892,9 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
* than at open time because we are sharing writable
* access to data structures.
*/
- s = splsoftcam();
- error = cam_periph_lock(periph, PRIBIO|PCATCH);
- if (error != 0) {
- splx(s);
+ error = cam_periph_hold(periph, PRIBIO|PCATCH);
+ if (error != 0)
return (error);
- }
didlockperiph = 1;
break;
@@ -1327,8 +1321,9 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
}
}
if (didlockperiph) {
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -1371,7 +1366,6 @@ saoninvalidate(struct cam_periph *periph)
{
struct sa_softc *softc;
struct ccb_setasync csa;
- int s;
softc = (struct sa_softc *)periph->softc;
@@ -1389,20 +1383,12 @@ saoninvalidate(struct cam_periph *periph)
softc->flags |= SA_FLAG_INVALID;
/*
- * Although the oninvalidate() routines are always called at
- * splsoftcam, we need to be at splbio() here to keep the buffer
- * queue from being modified while we traverse it.
- */
- s = splbio();
-
- /*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
bioq_flush(&softc->bio_queue, NULL, ENXIO);
softc->queue_count = 0;
- splx(s);
xpt_print(periph->path, "lost device\n");
@@ -1609,12 +1595,10 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
{
/* Pull a buffer from the queue and get going on it */
struct bio *bp;
- int s;
/*
* See if there is a buf with work for us to do..
*/
- s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
@@ -1623,10 +1607,8 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) {
struct bio *done_bp;
@@ -1669,7 +1651,6 @@ again:
"%d more buffers queued up\n",
(softc->flags & SA_FLAG_ERR_PENDING),
(bp != NULL)? "not " : " ", softc->queue_count));
- splx(s);
xpt_release_ccb(start_ccb);
biodone(done_bp);
} else {
@@ -1689,7 +1670,6 @@ again:
bp->bio_error = EIO;
xpt_print(periph->path, "zero blocksize"
" for FIXED length writes?\n");
- splx(s);
biodone(bp);
break;
}
@@ -1740,7 +1720,6 @@ again:
Set_CCB_Type(start_ccb, SA_CCB_BUFFER_IO);
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1785,7 +1764,6 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
}
if (error == EIO) {
- int s;
/*
* Catastrophic error. Mark the tape as frozen
@@ -1798,10 +1776,8 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
*
*/
- s = splbio();
softc->flags |= SA_FLAG_TAPE_FROZEN;
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
}
if (error != 0) {
bp->bio_resid = bp->bio_bcount;
diff --git a/sys/cam/scsi/scsi_ses.c b/sys/cam/scsi/scsi_ses.c
index 2af83ce..8e0b572 100644
--- a/sys/cam/scsi/scsi_ses.c
+++ b/sys/cam/scsi/scsi_ses.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
@@ -182,7 +183,7 @@ static struct cdevsw ses_cdevsw = {
.d_close = sesclose,
.d_ioctl = sesioctl,
.d_name = "ses",
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
};
static void
@@ -363,9 +364,11 @@ sesregister(struct cam_periph *periph, void *arg)
return (CAM_REQ_CMP_ERR);
}
+ cam_periph_unlock(periph);
softc->ses_dev = make_dev(&ses_cdevsw, unit2minor(periph->unit_number),
UID_ROOT, GID_OPERATOR, 0600, "%s%d",
periph->periph_name, periph->unit_number);
+ cam_periph_lock(periph);
softc->ses_dev->si_drv1 = periph;
/*
@@ -409,25 +412,20 @@ sesopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct cam_periph *periph;
struct ses_softc *softc;
- int error, s;
+ int error = 0;
- s = splsoftcam();
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL) {
- splx(s);
return (ENXIO);
}
- if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
- splx(s);
- return (error);
- }
- splx(s);
if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
cam_periph_unlock(periph);
return (ENXIO);
}
+ cam_periph_lock(periph);
+
softc = (struct ses_softc *)periph->softc;
if (softc->ses_flags & SES_FLAG_INVALID) {
@@ -453,10 +451,10 @@ sesopen(struct cdev *dev, int flags, int fmt, struct thread *td)
}
out:
+ cam_periph_unlock(periph);
if (error) {
cam_periph_release(periph);
}
- cam_periph_unlock(periph);
return (error);
}
@@ -473,11 +471,9 @@ sesclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if (periph == NULL)
return (ENXIO);
- softc = (struct ses_softc *)periph->softc;
-
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return (error);
+ cam_periph_lock(periph);
+ softc = (struct ses_softc *)periph->softc;
softc->ses_flags &= ~SES_FLAG_OPEN;
cam_periph_unlock(periph);
@@ -489,13 +485,11 @@ sesclose(struct cdev *dev, int flag, int fmt, struct thread *td)
static void
sesstart(struct cam_periph *p, union ccb *sccb)
{
- int s = splbio();
if (p->immediate_priority <= p->pinfo.priority) {
SLIST_INSERT_HEAD(&p->ccb_list, &sccb->ccb_h, periph_links.sle);
p->immediate_priority = CAM_PRIORITY_NONE;
wakeup(&p->ccb_list);
}
- splx(s);
}
static void
@@ -539,14 +533,17 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering sesioctl\n"));
+ cam_periph_lock(periph);
ssc = (struct ses_softc *)periph->softc;
/*
* Now check to see whether we're initialized or not.
*/
if ((ssc->ses_flags & SES_FLAG_INITIALIZED) == 0) {
+ cam_periph_unlock(periph);
return (ENXIO);
}
+ cam_periph_lock(periph);
error = 0;
@@ -576,22 +573,34 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
break;
case SESIOC_GETOBJMAP:
+ /*
+ * XXX Dropping the lock while copying multiple segments is
+ * bogus.
+ */
+ cam_periph_lock(periph);
for (uobj = addr, i = 0; i != ssc->ses_nobjects; i++, uobj++) {
obj.obj_id = i;
obj.subencid = ssc->ses_objmap[i].subenclosure;
obj.object_type = ssc->ses_objmap[i].enctype;
+ cam_periph_lock(periph);
error = copyout(&obj, uobj, sizeof (ses_object));
+ cam_periph_lock(periph);
if (error) {
break;
}
}
+ cam_periph_lock(periph);
break;
case SESIOC_GETENCSTAT:
+ cam_periph_lock(periph);
error = (*ssc->ses_vec.get_encstat)(ssc, 1);
- if (error)
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
tmp = ssc->ses_encstat & ~ENCI_SVALID;
+ cam_periph_unlock(periph);
error = copyout(&tmp, addr, sizeof (ses_encstat));
ssc->ses_encstat = tmp;
break;
@@ -600,7 +609,9 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
error = copyin(addr, &tmp, sizeof (ses_encstat));
if (error)
break;
+ cam_periph_lock(periph);
error = (*ssc->ses_vec.set_encstat)(ssc, tmp, 1);
+ cam_periph_unlock(periph);
break;
case SESIOC_GETOBJSTAT:
@@ -611,7 +622,9 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
error = EINVAL;
break;
}
+ cam_periph_lock(periph);
error = (*ssc->ses_vec.get_objstat)(ssc, &objs, 1);
+ cam_periph_unlock(periph);
if (error)
break;
error = copyout(&objs, addr, sizeof (ses_objstat));
@@ -630,7 +643,9 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
error = EINVAL;
break;
}
+ cam_periph_lock(periph);
error = (*ssc->ses_vec.set_objstat)(ssc, &objs, 1);
+ cam_periph_unlock(periph);
/*
* Always (for now) invalidate entry.
@@ -640,11 +655,15 @@ sesioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag, struct thread
case SESIOC_INIT:
+ cam_periph_lock(periph);
error = (*ssc->ses_vec.init_enc)(ssc);
+ cam_periph_unlock(periph);
break;
default:
+ cam_periph_lock(periph);
error = cam_periph_ioctl(periph, cmd, arg_addr, seserror);
+ cam_periph_unlock(periph);
break;
}
return (error);
diff --git a/sys/cam/scsi/scsi_sg.c b/sys/cam/scsi/scsi_sg.c
index 38942eb..7645abd 100644
--- a/sys/cam/scsi/scsi_sg.c
+++ b/sys/cam/scsi/scsi_sg.c
@@ -319,11 +319,13 @@ sgregister(struct cam_periph *periph, void *arg)
DEVSTAT_PRIORITY_PASS);
/* Register the device */
+ cam_periph_unlock(periph);
softc->dev = make_dev(&sg_cdevsw, unit2minor(periph->unit_number),
UID_ROOT, GID_OPERATOR, 0600, "%s%d",
periph->periph_name, periph->unit_number);
softc->devalias = make_dev_alias(softc->dev, "sg%c",
'a' + periph->unit_number);
+ cam_periph_lock(periph);
softc->dev->si_drv1 = periph;
/*
@@ -410,10 +412,6 @@ sgopen(struct cdev *dev, int flags, int fmt, struct thread *td)
if (periph == NULL)
return (ENXIO);
- softc = (struct sg_softc *)periph->softc;
- if (softc->flags & SG_FLAG_INVALID)
- return (ENXIO);
-
/*
* Don't allow access when we're running at a high securelevel.
*/
@@ -421,13 +419,19 @@ sgopen(struct cdev *dev, int flags, int fmt, struct thread *td)
if (error)
return (error);
- if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0)
- return (error);
+ cam_periph_lock(periph);
+
+ softc = (struct sg_softc *)periph->softc;
+ if (softc->flags & SG_FLAG_INVALID) {
+ cam_periph_unlock(periph);
+ return (ENXIO);
+ }
if ((softc->flags & SG_FLAG_OPEN) == 0) {
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
- return (ENXIO);
softc->flags |= SG_FLAG_OPEN;
+ } else {
+ /* Device closes aren't symmetrical, fix up the refcount. */
+ cam_periph_release(periph);
}
cam_periph_unlock(periph);
@@ -440,17 +444,14 @@ sgclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct cam_periph *periph;
struct sg_softc *softc;
- int error;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
return (ENXIO);
- softc = (struct sg_softc *)periph->softc;
-
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
- return (error);
+ cam_periph_lock(periph);
+ softc = (struct sg_softc *)periph->softc;
softc->flags &= ~SG_FLAG_OPEN;
cam_periph_unlock(periph);
@@ -473,6 +474,8 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
+
softc = (struct sg_softc *)periph->softc;
error = 0;
@@ -669,6 +672,7 @@ sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
break;
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -686,7 +690,6 @@ sgwrite(struct cdev *dev, struct uio *uio, int ioflag)
int error = 0, cdb_len, buf_len, dir;
periph = dev->si_drv1;
- sc = periph->softc;
rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO);
hdr = &rdwr->hdr.hdr;
@@ -699,12 +702,11 @@ sgwrite(struct cdev *dev, struct uio *uio, int ioflag)
if (error)
goto out_hdr;
- ccb = xpt_alloc_ccb();
+ ccb = xpt_alloc_ccb(periph->sim);
if (ccb == NULL) {
error = ENOMEM;
goto out_hdr;
}
- xpt_setup_ccb(&ccb->ccb_h, periph->path, /*priority*/5);
csio = &ccb->csio;
/*
@@ -751,6 +753,9 @@ sgwrite(struct cdev *dev, struct uio *uio, int ioflag)
dir = CAM_DIR_NONE;
}
+ cam_periph_lock(periph);
+ sc = periph->softc;
+ xpt_setup_ccb(&ccb->ccb_h, periph->path, /*priority*/5);
cam_fill_csio(csio,
/*retries*/1,
sgdone,
@@ -774,7 +779,9 @@ sgwrite(struct cdev *dev, struct uio *uio, int ioflag)
ccb->ccb_h.ccb_rdwr = rdwr;
ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO;
TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link);
- return (sgsendrdwr(periph, ccb));
+ error = sgsendrdwr(periph, ccb);
+ cam_periph_unlock(periph);
+ return (error);
out_buf:
free(buf, M_DEVBUF);
@@ -797,7 +804,6 @@ sgread(struct cdev *dev, struct uio *uio, int ioflag)
int error, pack_len, reply_len, pack_id;
periph = dev->si_drv1;
- sc = periph->softc;
/* XXX The pack len field needs to be updated and written out instead
* of discarded. Not sure how to do that.
@@ -811,17 +817,20 @@ sgread(struct cdev *dev, struct uio *uio, int ioflag)
return (error);
uio->uio_rw = UIO_READ;
+ cam_periph_lock(periph);
+ sc = periph->softc;
search:
TAILQ_FOREACH(rdwr, &sc->rdwr_done, rdwr_link) {
if (rdwr->tag == pack_id)
break;
}
if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) {
- if (tsleep(rdwr, PCATCH, "sgread", 0) == ERESTART)
+ if (msleep(rdwr, periph->sim->mtx, PCATCH, "sgread", 0) == ERESTART)
return (EAGAIN);
goto search;
}
TAILQ_REMOVE(&sc->rdwr_done, rdwr, rdwr_link);
+ cam_periph_unlock(periph);
hdr = &rdwr->hdr.hdr;
csio = &rdwr->ccb->csio;
@@ -865,7 +874,9 @@ search:
if ((error == 0) && (hdr->result == 0))
error = uiomove(rdwr->buf, rdwr->buf_len, uio);
+ cam_periph_lock(periph);
xpt_free_ccb(rdwr->ccb);
+ cam_periph_unlock(periph);
free(rdwr->buf, M_DEVBUF);
free(rdwr, M_DEVBUF);
return (error);
@@ -882,7 +893,15 @@ sgsendccb(struct cam_periph *periph, union ccb *ccb)
if (((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
&& (ccb->csio.data_ptr != NULL)) {
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);
if (error)
return (error);
need_unmap = 1;
diff --git a/sys/cam/scsi/scsi_targ_bh.c b/sys/cam/scsi/scsi_targ_bh.c
index b61152e..984baf4 100644
--- a/sys/cam/scsi/scsi_targ_bh.c
+++ b/sys/cam/scsi/scsi_targ_bh.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_queue.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
@@ -447,7 +448,7 @@ targbhdtor(struct cam_periph *periph)
/* FALLTHROUGH */
default:
/* XXX Wait for callback of targbhdislun() */
- tsleep(softc, PRIBIO, "targbh", hz/2);
+ msleep(softc, periph->sim->mtx, PRIBIO, "targbh", hz/2);
free(softc, M_SCSIBH);
break;
}
@@ -462,27 +463,22 @@ targbhstart(struct cam_periph *periph, union ccb *start_ccb)
struct targbh_cmd_desc *desc;
struct ccb_scsiio *csio;
ccb_flags flags;
- int s;
softc = (struct targbh_softc *)periph->softc;
- s = splbio();
ccbh = TAILQ_FIRST(&softc->work_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
start_ccb->ccb_h.ccb_type = TARGBH_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (ccbh == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else {
TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);
TAILQ_INSERT_HEAD(&softc->pending_queue, ccbh,
periph_links.tqe);
- splx(s);
atio = (struct ccb_accept_tio*)ccbh;
desc = (struct targbh_cmd_desc *)atio->ccb_h.ccb_descr;
@@ -543,9 +539,7 @@ targbhstart(struct cam_periph *periph, union ccb *start_ccb)
/*getcount_only*/0);
atio->ccb_h.status &= ~CAM_DEV_QFRZN;
}
- s = splbio();
ccbh = TAILQ_FIRST(&softc->work_queue);
- splx(s);
}
if (ccbh != NULL)
xpt_schedule(periph, /*priority*/1);
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c
index 670fb0e..c6086f9 100644
--- a/sys/cam/scsi/scsi_target.c
+++ b/sys/cam/scsi/scsi_target.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
+#include <cam/cam_sim.h>
#include <cam/scsi/scsi_targetio.h>
/* Transaction information attached to each CCB sent by the user */
@@ -160,7 +161,11 @@ PERIPHDRIVER_DECLARE(targ, targdriver);
static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
-/* Create softc and initialize it. Only one proc can open each targ device. */
+/*
+ * Create softc and initialize it. Only one proc can open each targ device.
+ * There is no locking here because a periph doesn't get created until an
+ * ioctl is issued to do so, and that can't happen until this method returns.
+ */
static int
targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
@@ -199,9 +204,24 @@ static int
targclose(struct cdev *dev, int flag, int fmt, struct thread *td)
{
struct targ_softc *softc;
+ struct cam_periph *periph;
int error;
softc = (struct targ_softc *)dev->si_drv1;
+ if ((softc->periph == NULL) ||
+ (softc->state & TARG_STATE_LUN_ENABLED) == 0) {
+ destroy_dev(dev);
+ FREE(softc, M_TARG);
+ return (0);
+ }
+
+ /*
+ * Acquire a hold on the periph so that it doesn't go away before
+ * we are ready at the end of the function.
+ */
+ periph = softc->periph;
+ cam_periph_acquire(periph);
+ cam_periph_lock(periph);
error = targdisable(softc);
if (error == CAM_REQ_CMP) {
dev->si_drv1 = 0;
@@ -212,6 +232,9 @@ targclose(struct cdev *dev, int flag, int fmt, struct thread *td)
destroy_dev(dev);
FREE(softc, M_TARG);
}
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+
return (error);
}
@@ -229,44 +252,56 @@ targioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t
{
struct ioc_enable_lun *new_lun;
struct cam_path *path;
+ struct cam_sim *sim;
new_lun = (struct ioc_enable_lun *)addr;
- status = xpt_create_path(&path, /*periph*/NULL,
- new_lun->path_id,
- new_lun->target_id,
- new_lun->lun_id);
+ status = xpt_create_path_unlocked(&path, /*periph*/NULL,
+ new_lun->path_id,
+ new_lun->target_id,
+ new_lun->lun_id);
if (status != CAM_REQ_CMP) {
printf("Couldn't create path, status %#x\n", status);
break;
}
+ sim = xpt_path_sim(path);
+ mtx_lock(sim->mtx);
status = targenable(softc, path, new_lun->grp6_len,
new_lun->grp7_len);
xpt_free_path(path);
+ mtx_unlock(sim->mtx);
break;
}
case TARGIOCDISABLE:
+ if (softc->periph == NULL) {
+ status = CAM_DEV_NOT_THERE;
+ break;
+ }
+ cam_periph_lock(softc->periph);
status = targdisable(softc);
+ cam_periph_unlock(softc->periph);
break;
case TARGIOCDEBUG:
{
#ifdef CAMDEBUG
struct ccb_debug cdbg;
+ /* If no periph available, disallow debugging changes */
+ if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
+ status = CAM_DEV_NOT_THERE;
+ break;
+ }
bzero(&cdbg, sizeof cdbg);
if (*((int *)addr) != 0)
cdbg.flags = CAM_DEBUG_PERIPH;
else
cdbg.flags = CAM_DEBUG_NONE;
+ cam_periph_lock(softc->periph);
xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
cdbg.ccb_h.func_code = XPT_DEBUG;
cdbg.ccb_h.cbfcnp = targdone;
- /* If no periph available, disallow debugging changes */
- if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
- status = CAM_DEV_NOT_THERE;
- break;
- }
xpt_action((union ccb *)&cdbg);
+ cam_periph_unlock(softc->periph);
status = cdbg.ccb_h.status & CAM_STATUS_MASK;
#else
status = CAM_FUNC_NOTAVAIL;
@@ -294,10 +329,12 @@ targpoll(struct cdev *dev, int poll_events, struct thread *td)
revents = poll_events & (POLLOUT | POLLWRNORM);
if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
/* Poll for read() depends on user and abort queues. */
+ cam_periph_lock(softc->periph);
if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
!TAILQ_EMPTY(&softc->abort_queue)) {
revents |= poll_events & (POLLIN | POLLRDNORM);
}
+ cam_periph_unlock(softc->periph);
/* Only sleep if the user didn't poll for write. */
if (revents == 0)
selrecord(td, &softc->read_select);
@@ -335,8 +372,10 @@ targreadfilt(struct knote *kn, long hint)
int retval;
softc = (struct targ_softc *)kn->kn_hook;
+ cam_periph_lock(softc->periph);
retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
!TAILQ_EMPTY(&softc->abort_queue);
+ cam_periph_unlock(softc->periph);
return (retval);
}
@@ -532,6 +571,7 @@ targwrite(struct cdev *dev, struct uio *uio, int ioflag)
switch (func_code) {
case XPT_ACCEPT_TARGET_IO:
case XPT_IMMED_NOTIFY:
+ cam_periph_lock(softc->periph);
ccb = targgetccb(softc, func_code, priority);
descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
descr->user_ccb = user_ccb;
@@ -542,8 +582,10 @@ targwrite(struct cdev *dev, struct uio *uio, int ioflag)
TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
&ccb->ccb_h,
periph_links.tqe);
+ cam_periph_unlock(softc->periph);
break;
default:
+ cam_periph_lock(softc->periph);
if ((func_code & XPT_FC_QUEUED) != 0) {
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("Sending queued ccb %#x (%p)\n",
@@ -569,6 +611,7 @@ targwrite(struct cdev *dev, struct uio *uio, int ioflag)
targsendccb(softc, ccb, descr);
targreturnccb(softc, ccb);
}
+ cam_periph_unlock(softc->periph);
break;
}
write_len += sizeof(user_ccb);
@@ -796,8 +839,6 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
union ccb *user_ccb;
int read_len, error;
- mtx_lock(&Giant);
-
error = 0;
read_len = 0;
softc = (struct targ_softc *)dev->si_drv1;
@@ -806,11 +847,12 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
/* If no data is available, wait or return immediately */
+ cam_periph_lock(softc->periph);
ccb_h = TAILQ_FIRST(user_queue);
user_descr = TAILQ_FIRST(abort_queue);
while (ccb_h == NULL && user_descr == NULL) {
if ((ioflag & IO_NDELAY) == 0) {
- error = tsleep(user_queue,
+ error = msleep(user_queue, softc->periph->sim->mtx,
PRIBIO | PCATCH, "targrd", 0);
ccb_h = TAILQ_FIRST(user_queue);
user_descr = TAILQ_FIRST(abort_queue);
@@ -822,7 +864,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
}
}
} else {
- mtx_unlock(&Giant);
+ cam_periph_unlock(softc->periph);
return (EAGAIN);
}
}
@@ -841,7 +883,9 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
error = targreturnccb(softc, (union ccb *)ccb_h);
if (error != 0)
goto read_fail;
+ cam_periph_unlock(softc->periph);
error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
+ cam_periph_lock(softc->periph);
if (error != 0)
goto read_fail;
read_len += sizeof(user_ccb);
@@ -859,7 +903,9 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
("targread aborted descr %p (%p)\n",
user_descr, user_ccb));
suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
+ cam_periph_unlock(softc->periph);
error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
+ cam_periph_lock(softc->periph);
if (error != 0)
goto read_fail;
read_len += sizeof(user_ccb);
@@ -876,7 +922,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
error = ENOSPC;
read_fail:
- mtx_unlock(&Giant);
+ cam_periph_unlock(softc->periph);
return (error);
}
@@ -1005,6 +1051,7 @@ abort_all_pending(struct targ_softc *softc)
struct targ_cmd_descr *descr;
struct ccb_abort cab;
struct ccb_hdr *ccb_h;
+ struct cam_sim *sim;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("abort_all_pending\n"));
@@ -1037,7 +1084,8 @@ abort_all_pending(struct targ_softc *softc)
/* If we aborted at least one pending CCB ok, wait for it. */
if (cab.ccb_h.status == CAM_REQ_CMP) {
- tsleep(&softc->pending_ccb_queue,
+ sim = xpt_path_sim(softc->path);
+ msleep(&softc->pending_ccb_queue, sim->mtx,
PRIBIO | PCATCH, "tgabrt", 0);
}
diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c
index 1b5690a..88112b5 100644
--- a/sys/dev/aac/aac_cam.c
+++ b/sys/dev/aac/aac_cam.c
@@ -171,7 +171,7 @@ aac_cam_attach(device_t dev)
return (EIO);
sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc,
- device_get_unit(dev), 1, 1, devq);
+ device_get_unit(dev), &Giant, 1, 1, devq);
if (sim == NULL) {
cam_simq_free(devq);
return (EIO);
diff --git a/sys/dev/advansys/advansys.c b/sys/dev/advansys/advansys.c
index 5a37af7..79c1f06 100644
--- a/sys/dev/advansys/advansys.c
+++ b/sys/dev/advansys/advansys.c
@@ -1414,7 +1414,7 @@ adv_attach(adv)
* Construct our SIM entry.
*/
adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv, adv->unit,
- 1, adv->max_openings, devq);
+ &Giant, 1, adv->max_openings, devq);
if (adv->sim == NULL)
return (ENOMEM);
diff --git a/sys/dev/advansys/adwcam.c b/sys/dev/advansys/adwcam.c
index 78b8fdd..2ba42da 100644
--- a/sys/dev/advansys/adwcam.c
+++ b/sys/dev/advansys/adwcam.c
@@ -1234,7 +1234,7 @@ adw_attach(struct adw_softc *adw)
* Construct our SIM entry.
*/
adw->sim = cam_sim_alloc(adw_action, adw_poll, "adw", adw, adw->unit,
- 1, adw->max_acbs, devq);
+ &Giant, 1, adw->max_acbs, devq);
if (adw->sim == NULL) {
error = ENOMEM;
goto fail;
diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c
index 714c1bb..b52b201 100644
--- a/sys/dev/aha/aha.c
+++ b/sys/dev/aha/aha.c
@@ -605,8 +605,8 @@ aha_attach(struct aha_softc *aha)
/*
* Construct our SIM entry
*/
- aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit, 2,
- tagged_dev_openings, devq);
+ aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit,
+ &Giant, 2, tagged_dev_openings, devq);
if (aha->sim == NULL) {
cam_simq_free(devq);
return (ENOMEM);
diff --git a/sys/dev/ahb/ahb.c b/sys/dev/ahb/ahb.c
index 8887c80..3f4a588 100644
--- a/sys/dev/ahb/ahb.c
+++ b/sys/dev/ahb/ahb.c
@@ -553,7 +553,7 @@ ahbxptattach(struct ahb_softc *ahb)
* Construct our SIM entry
*/
ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, ahb->unit,
- 2, ahb->num_ecbs, devq);
+ &Giant, 2, ahb->num_ecbs, devq);
if (ahb->sim == NULL) {
cam_simq_free(devq);
return (ENOMEM);
diff --git a/sys/dev/aic/aic.c b/sys/dev/aic/aic.c
index cd9fabc..b647cd4 100644
--- a/sys/dev/aic/aic.c
+++ b/sys/dev/aic/aic.c
@@ -30,6 +30,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/malloc.h>
#include <sys/bus.h>
#include <machine/bus.h>
@@ -1540,7 +1543,7 @@ aic_attach(struct aic_softc *aic)
* Construct our SIM entry
*/
aic->sim = cam_sim_alloc(aic_action, aic_poll, "aic", aic,
- aic->unit, 2, 256, devq);
+ aic->unit, &Giant, 2, 256, devq);
if (aic->sim == NULL) {
cam_simq_free(devq);
return (ENOMEM);
diff --git a/sys/dev/aic7xxx/aic79xx_osm.c b/sys/dev/aic7xxx/aic79xx_osm.c
index e16b421..aef520d 100644
--- a/sys/dev/aic7xxx/aic79xx_osm.c
+++ b/sys/dev/aic7xxx/aic79xx_osm.c
@@ -143,7 +143,7 @@ ahd_attach(struct ahd_softc *ahd)
*/
sim = cam_sim_alloc(ahd_action, ahd_poll, "ahd", ahd,
device_get_unit(ahd->dev_softc),
- 1, /*XXX*/256, devq);
+ &Giant, 1, /*XXX*/256, devq);
if (sim == NULL) {
cam_simq_free(devq);
goto fail;
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index f3b106c..b53f96a 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -196,7 +196,7 @@ ahc_attach(struct ahc_softc *ahc)
*/
sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc,
device_get_unit(ahc->dev_softc),
- 1, AHC_MAX_QUEUE, devq);
+ &Giant, 1, AHC_MAX_QUEUE, devq);
if (sim == NULL) {
cam_simq_free(devq);
goto fail;
@@ -227,7 +227,8 @@ ahc_attach(struct ahc_softc *ahc)
if (ahc->features & AHC_TWIN) {
sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc",
- ahc, device_get_unit(ahc->dev_softc), 1,
+ ahc, device_get_unit(ahc->dev_softc),
+ &Giant, 1,
AHC_MAX_QUEUE, devq);
if (sim2 == NULL) {
diff --git a/sys/dev/amd/amd.c b/sys/dev/amd/amd.c
index 4c8ed41..7e5c4df 100644
--- a/sys/dev/amd/amd.c
+++ b/sys/dev/amd/amd.c
@@ -58,6 +58,7 @@
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -2481,8 +2482,8 @@ amd_attach(device_t dev)
}
amd->psim = cam_sim_alloc(amd_action, amd_poll, "amd",
- amd, amd->unit, 1, MAX_TAGS_CMD_QUEUE,
- devq);
+ amd, amd->unit, &Giant,
+ 1, MAX_TAGS_CMD_QUEUE, devq);
if (amd->psim == NULL) {
cam_simq_free(devq);
if (bootverbose)
diff --git a/sys/dev/amr/amr_cam.c b/sys/dev/amr/amr_cam.c
index 3553d43..78cd4ec 100644
--- a/sys/dev/amr/amr_cam.c
+++ b/sys/dev/amr/amr_cam.c
@@ -148,6 +148,7 @@ amr_cam_attach(struct amr_softc *sc)
"amr",
sc,
device_get_unit(sc->amr_dev),
+ &Giant,
1,
AMR_MAX_SCSI_CMDS,
devq)) == NULL) {
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index e6441b2..f4e79b5 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -2145,8 +2145,9 @@ static u_int32_t arcmsr_attach(device_t dev)
printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
return ENXIO;
}
- acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll
- , "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
+ acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll,
+ "arcmsr", acb, unit, &Giant, 1,
+ ARCMSR_MAX_OUTSTANDING_CMD, devq);
if(acb->psim == NULL) {
arcmsr_free_resource(acb);
bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
diff --git a/sys/dev/asr/asr.c b/sys/dev/asr/asr.c
index 1de0bfd..260cbbd 100644
--- a/sys/dev/asr/asr.c
+++ b/sys/dev/asr/asr.c
@@ -2651,7 +2651,8 @@ asr_attach(device_t dev)
* Construct our first channel SIM entry
*/
sc->ha_sim[bus] = cam_sim_alloc(asr_action, asr_poll, "asr", sc,
- unit, 1, QueueSize, devq);
+ unit, &Giant,
+ 1, QueueSize, devq);
if (sc->ha_sim[bus] == NULL) {
continue;
}
diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c
index ebabf03..4f2bd34 100644
--- a/sys/dev/ata/atapi-cam.c
+++ b/sys/dev/ata/atapi-cam.c
@@ -210,7 +210,7 @@ atapi_cam_attach(device_t dev)
}
if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "ata",
- (void *)scp, unit, 1, 1, devq)) == NULL) {
+ (void *)scp, unit, &Giant, 1, 1, devq)) == NULL) {
error = ENOMEM;
goto out;
}
diff --git a/sys/dev/buslogic/bt.c b/sys/dev/buslogic/bt.c
index 7eee35b..21579ea 100644
--- a/sys/dev/buslogic/bt.c
+++ b/sys/dev/buslogic/bt.c
@@ -874,7 +874,7 @@ bt_attach(device_t dev)
* Construct our SIM entry
*/
bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit,
- 2, tagged_dev_openings, devq);
+ &Giant, 2, tagged_dev_openings, devq);
if (bt->sim == NULL) {
cam_simq_free(devq);
return (ENOMEM);
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index f23017b..6d71334 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -2476,8 +2476,8 @@ ciss_cam_init(struct ciss_softc *sc)
if ((sc->ciss_cam_sim[i] = cam_sim_alloc(ciss_cam_action, ciss_cam_poll,
"ciss", sc,
device_get_unit(sc->ciss_dev),
+ &Giant, 1,
sc->ciss_max_requests - 2,
- 1,
sc->ciss_cam_devq)) == NULL) {
ciss_printf(sc, "can't allocate CAM SIM for controller %d\n", i);
return(ENOMEM);
@@ -2499,8 +2499,8 @@ ciss_cam_init(struct ciss_softc *sc)
if ((sc->ciss_cam_sim[i] = cam_sim_alloc(ciss_cam_action, ciss_cam_poll,
"ciss", sc,
device_get_unit(sc->ciss_dev),
+ &Giant, 1,
sc->ciss_max_requests - 2,
- 1,
sc->ciss_cam_devq)) == NULL) {
ciss_printf(sc, "can't allocate CAM SIM for controller %d\n", i);
return (ENOMEM);
diff --git a/sys/dev/dpt/dpt_scsi.c b/sys/dev/dpt/dpt_scsi.c
index 9238292..276f0c9 100644
--- a/sys/dev/dpt/dpt_scsi.c
+++ b/sys/dev/dpt/dpt_scsi.c
@@ -1566,7 +1566,8 @@ dpt_attach(dpt_softc_t *dpt)
* Construct our SIM entry
*/
dpt->sims[i] = cam_sim_alloc(dpt_action, dpt_poll, "dpt",
- dpt, dpt->unit, /*untagged*/2,
+ dpt, dpt->unit, &Giant,
+ /*untagged*/2,
/*tagged*/dpt->max_dccbs, devq);
if (dpt->sims[i] == NULL) {
if (i == 0)
diff --git a/sys/dev/esp/ncr53c9x.c b/sys/dev/esp/ncr53c9x.c
index 50c6295..cba58d5 100644
--- a/sys/dev/esp/ncr53c9x.c
+++ b/sys/dev/esp/ncr53c9x.c
@@ -325,7 +325,7 @@ ncr53c9x_attach(struct ncr53c9x_softc *sc)
}
sim = cam_sim_alloc(ncr53c9x_action, ncr53c9x_poll, "esp", sc,
- device_get_unit(sc->sc_dev), 1,
+ device_get_unit(sc->sc_dev), &Giant, 1,
NCR_TAG_DEPTH, devq);
if (sim == NULL) {
device_printf(sc->sc_dev, "cannot allocate SIM entry\n");
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c
index c796d68..fb88553 100644
--- a/sys/dev/firewire/sbp.c
+++ b/sys/dev/firewire/sbp.c
@@ -1964,6 +1964,7 @@ END_DEBUG
sbp->sim = cam_sim_alloc(sbp_action, sbp_poll, "sbp", sbp,
device_get_unit(dev),
+ &Giant,
/*untagged*/ 1,
/*tagged*/ SBP_QUEUE_LEN - 1,
devq);
diff --git a/sys/dev/firewire/sbp_targ.c b/sys/dev/firewire/sbp_targ.c
index eb23412..f943772 100644
--- a/sys/dev/firewire/sbp_targ.c
+++ b/sys/dev/firewire/sbp_targ.c
@@ -1626,7 +1626,7 @@ sbp_targ_attach(device_t dev)
return (ENXIO);
sc->sim = cam_sim_alloc(sbp_targ_action, sbp_targ_poll,
- "sbp_targ", sc, device_get_unit(dev),
+ "sbp_targ", sc, device_get_unit(dev), &Giant,
/*untagged*/ 1, /*tagged*/ 1, devq);
if (sc->sim == NULL) {
cam_simq_free(devq);
diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c
index bab49a8..f58329d 100644
--- a/sys/dev/hptmv/entry.c
+++ b/sys/dev/hptmv/entry.c
@@ -1960,7 +1960,8 @@ hpt_attach(device_t dev)
* Construct our SIM entry
*/
if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
- pAdapter, device_get_unit(pAdapter->hpt_dev), /*untagged*/1, /*tagged*/8, devq)) == NULL) {
+ pAdapter, device_get_unit(pAdapter->hpt_dev),
+ &Giant, /*untagged*/1, /*tagged*/8, devq)) == NULL) {
cam_simq_free(devq);
return ENOMEM;
}
diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c
index 51a636c..b58306b 100644
--- a/sys/dev/iir/iir.c
+++ b/sys/dev/iir/iir.c
@@ -502,7 +502,8 @@ iir_attach(struct gdt_softc *gdt)
* Construct our SIM entry
*/
gdt->sims[i] = cam_sim_alloc(iir_action, iir_poll, "iir",
- gdt, gdt->sc_hanum, /*untagged*/1,
+ gdt, gdt->sc_hanum, &Giant,
+ /*untagged*/1,
/*tagged*/GDT_MAXCMDS, devq);
if (xpt_bus_register(gdt->sims[i], i) != CAM_SUCCESS) {
cam_sim_free(gdt->sims[i], /*free_devq*/i == 0);
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index f422659..6c4fd06 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -137,7 +137,7 @@ isp_attach(ispsoftc_t *isp)
*/
ISPLOCK_2_CAMLOCK(isp);
sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
+ device_get_unit(isp->isp_dev), &Giant, 1, isp->isp_maxcmds, devq);
if (sim == NULL) {
cam_simq_free(devq);
CAMLOCK_2_ISPLOCK(isp);
@@ -224,7 +224,8 @@ isp_attach(ispsoftc_t *isp)
if (IS_DUALBUS(isp)) {
ISPLOCK_2_CAMLOCK(isp);
sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
+ device_get_unit(isp->isp_dev), &Giant, 1,
+ isp->isp_maxcmds, devq);
if (sim == NULL) {
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
xpt_free_path(isp->isp_path);
@@ -2147,7 +2148,7 @@ isp_make_here(ispsoftc_t *isp, int tgt)
* Allocate a CCB, create a wildcard path for this bus,
* and schedule a rescan.
*/
- ccb = xpt_alloc_ccb_nowait();
+ ccb = xpt_alloc_ccb_nowait(isp->isp_osinfo.sim);
if (ccb == NULL) {
isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
CAMLOCK_2_ISPLOCK(mpt);
diff --git a/sys/dev/mly/mly.c b/sys/dev/mly/mly.c
index 62052b0..f9ca34b 100644
--- a/sys/dev/mly/mly.c
+++ b/sys/dev/mly/mly.c
@@ -1945,6 +1945,7 @@ mly_cam_attach(struct mly_softc *sc)
if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
device_get_unit(sc->mly_dev),
+ &Giant,
sc->mly_controllerinfo->maximum_parallel_commands,
1, devq)) == NULL) {
return(ENOMEM);
@@ -1964,6 +1965,7 @@ mly_cam_attach(struct mly_softc *sc)
for (i = 0; i < sc->mly_controllerinfo->virtual_channels_present; i++, chn++) {
if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
device_get_unit(sc->mly_dev),
+ &Giant,
sc->mly_controllerinfo->maximum_parallel_commands,
0, devq)) == NULL) {
return(ENOMEM);
diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c
index ac5dffa..5d7c5a5 100644
--- a/sys/dev/mpt/mpt_cam.c
+++ b/sys/dev/mpt/mpt_cam.c
@@ -311,7 +311,7 @@ mpt_cam_attach(struct mpt_softc *mpt)
* Construct our SIM entry.
*/
mpt->sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt,
- mpt->unit, 1, maxq, devq);
+ mpt->unit, &Giant, 1, maxq, devq);
if (mpt->sim == NULL) {
mpt_prt(mpt, "Unable to allocate CAM SIM!\n");
cam_simq_free(devq);
@@ -348,7 +348,7 @@ mpt_cam_attach(struct mpt_softc *mpt)
* Create a "bus" to export all hidden disks to CAM.
*/
mpt->phydisk_sim = cam_sim_alloc(mpt_action, mpt_poll, "mpt", mpt,
- mpt->unit, 1, maxq, devq);
+ mpt->unit, &Giant, 1, maxq, devq);
if (mpt->phydisk_sim == NULL) {
mpt_prt(mpt, "Unable to allocate Physical Disk CAM SIM!\n");
error = ENOMEM;
@@ -2087,6 +2087,7 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
{
union ccb *ccb;
uint32_t pathid;
+ struct cam_sim *sim;
/*
* In general this means a device has been added to the loop.
*/
@@ -2095,16 +2096,17 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
break;
}
if (mpt->phydisk_sim) {
- pathid = cam_sim_path(mpt->phydisk_sim);;
+ sim = mpt->phydisk_sim;
} else {
- pathid = cam_sim_path(mpt->sim);
+ sim = mpt->sim;
}
+ pathid = cam_sim_path(sim);
MPTLOCK_2_CAMLOCK(mpt);
/*
* Allocate a CCB, create a wildcard path for this bus,
* and schedule a rescan.
*/
- ccb = xpt_alloc_ccb_nowait();
+ ccb = xpt_alloc_ccb_nowait(sim);
if (ccb == NULL) {
mpt_prt(mpt, "unable to alloc CCB for rescan\n");
CAMLOCK_2_MPTLOCK(mpt);
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index abb2ef8..c9510b2 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/malloc.h>
#include <cam/cam.h>
@@ -160,7 +162,7 @@ vpo_attach(device_t dev)
return (ENXIO);
vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo,
- device_get_unit(dev),
+ device_get_unit(dev), &Giant,
/*untagged*/1, /*tagged*/0, devq);
if (vpo->sim == NULL) {
cam_simq_free(devq);
diff --git a/sys/dev/rr232x/osm_bsd.c b/sys/dev/rr232x/osm_bsd.c
index 1e77fbf..ae394f4 100644
--- a/sys/dev/rr232x/osm_bsd.c
+++ b/sys/dev/rr232x/osm_bsd.c
@@ -1088,7 +1088,8 @@ static void hpt_final_init(void *dummy)
}
vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name,
- vbus_ext, 0, os_max_queue_comm, /*tagged*/8, devq);
+ vbus_ext, 0, &Giant,
+ os_max_queue_comm, /*tagged*/8, devq);
if (!vbus_ext->sim) {
os_printk("cam_sim_alloc failed");
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c
index e4357b1..679b98b 100644
--- a/sys/dev/sym/sym_hipd.c
+++ b/sys/dev/sym/sym_hipd.c
@@ -8973,7 +8973,7 @@ static int sym_cam_attach(hcb_p np)
* Construct our SIM entry.
*/
sim = cam_sim_alloc(sym_action, sym_poll, "sym", np, np->unit,
- 1, SYM_SETUP_MAX_TAG, devq);
+ &Giant, 1, SYM_SETUP_MAX_TAG, devq);
if (!sim)
goto fail;
devq = 0;
diff --git a/sys/dev/trm/trm.c b/sys/dev/trm/trm.c
index 31cad43..b3690ac 100644
--- a/sys/dev/trm/trm.c
+++ b/sys/dev/trm/trm.c
@@ -3636,6 +3636,7 @@ trm_attach(device_t dev)
"trm",
pACB,
unit,
+ &Giant,
1,
TRM_MAX_TAGS_CMD_QUEUE,
device_Q);
diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c
index 6b6afeb..e5a1143 100644
--- a/sys/dev/twa/tw_osl_cam.c
+++ b/sys/dev/twa/tw_osl_cam.c
@@ -102,7 +102,7 @@ tw_osli_cam_attach(struct twa_softc *sc)
*/
tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
- device_get_unit(sc->bus_dev),
+ device_get_unit(sc->bus_dev), &Giant,
TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
if (sc->sim == NULL) {
cam_simq_free(devq);
diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index de15d47..5c071b3 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -110,6 +110,8 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <sys/sysctl.h>
@@ -2257,6 +2259,7 @@ umass_cam_attach_sim(struct umass_softc *sc)
DEVNAME_SIM,
sc /*priv*/,
device_get_unit(sc->sc_dev) /*unit number*/,
+ &Giant,
1 /*maximum device openings*/,
0 /*maximum tagged device openings*/,
devq);
diff --git a/sys/dev/wds/wd7000.c b/sys/dev/wds/wd7000.c
index 8c91f75..05695c7 100644
--- a/sys/dev/wds/wd7000.c
+++ b/sys/dev/wds/wd7000.c
@@ -132,6 +132,7 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/assym.h>
+#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
@@ -606,7 +607,7 @@ wds_attach(device_t dev)
goto bad;
sim = cam_sim_alloc(wds_action, wds_poll, "wds", (void *) wp,
- wp->unit, 1, 1, devq);
+ wp->unit, &Giant, 1, 1, devq);
if (sim == NULL) {
cam_simq_free(devq);
goto bad;
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c
index 21f7f85..bcd200c 100644
--- a/sys/pci/ncr.c
+++ b/sys/pci/ncr.c
@@ -184,6 +184,8 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <machine/md_var.h>
#include <machine/bus.h>
@@ -3781,7 +3783,7 @@ ncr_attach (device_t dev)
** about our bus.
*/
np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, np->unit,
- 1, MAX_TAGS, devq);
+ &Giant, 1, MAX_TAGS, devq);
if (np->sim == NULL) {
cam_simq_free(devq);
return ENOMEM;
OpenPOWER on IntegriCloud