Remove Giant from CAM. Drivers (SIMs) now register a mutex that CAM will

use to synchornize and protect all data objects that are used for that
SIM.  Drivers that are not yet MPSAFE register Giant and operate as
usual.  RIght now, no drivers are MPSAFE, though a few will be changed
in the coming week as this work settles down.

The driver API has changed, so all CAM drivers will need to be recompiled.
The userland API has not changed, so tools like camcontrol do not need to
be recompiled.
This commit is contained in:
Scott Long 2007-04-15 08:49:19 +00:00
parent 4f450d951a
commit 2b83592fdc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168752
51 changed files with 1280 additions and 1000 deletions

View File

@ -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 */

View File

@ -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,20 +296,68 @@ 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);
}
/*
* Look for the next unit number that is not currently in use for this
* peripheral type starting at "newunit". Also exclude unit numbers that
@ -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.

View File

@ -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);

View File

@ -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 (mtx == NULL)
return (NULL);
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;
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);
}

View File

@ -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)
{

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;
@ -912,22 +913,12 @@ 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;
@ -1177,18 +1178,11 @@ daregister(struct cam_periph *periph, void *arg)
else if (softc->minimum_cmd_size > 12)
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);
}
/*

View File

@ -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) {

View File

@ -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);
cam_periph_lock(periph);
softc = (struct pass_softc *)periph->softc;
if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
return (error);
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.

View File

@ -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;
@ -371,13 +350,6 @@ 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
@ -385,8 +357,6 @@ ptoninvalidate(struct cam_periph *periph)
*/
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;

View File

@ -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;
}
cam_periph_lock(periph);
softc = (struct sa_softc *)periph->softc;
s = splsoftcam();
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,17 +771,11 @@ 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.
*/
@ -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;
@ -1388,13 +1382,6 @@ 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
@ -1402,7 +1389,6 @@ saoninvalidate(struct cam_periph *periph)
*/
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 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
"%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 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
bp->bio_error = EIO;
xpt_print(periph->path, "zero blocksize"
" for FIXED length writes?\n");
splx(s);
biodone(bp);
break;
}
@ -1740,7 +1720,6 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
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;

View File

@ -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);
cam_periph_lock(periph);
softc = (struct ses_softc *)periph->softc;
if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
return (error);
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);

View File

@ -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);
cam_periph_lock(periph);
softc = (struct sg_softc *)periph->softc;
if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
return (error);
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 @@ sgread(struct cdev *dev, struct uio *uio, int ioflag)
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;

View File

@ -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);

View File

@ -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;
bzero(&cdbg, sizeof cdbg);
if (*((int *)addr) != 0)
cdbg.flags = CAM_DEBUG_PERIPH;
else
cdbg.flags = CAM_DEBUG_NONE;
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;
}
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;
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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -3636,6 +3636,7 @@ trm_attach(device_t dev)
"trm",
pACB,
unit,
&Giant,
1,
TRM_MAX_TAGS_CMD_QUEUE,
device_Q);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;