[Midnightbsd-cvs] src: sys/cam: sync changes with FreeBSD 7
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Mon Sep 15 20:27:06 EDT 2008
Log Message:
-----------
sync changes with FreeBSD 7
Modified Files:
--------------
src/sys/cam:
cam.c (r1.1.1.1 -> r1.2)
cam_ccb.h (r1.2 -> r1.3)
cam_debug.h (r1.1.1.1 -> r1.2)
cam_periph.c (r1.2 -> r1.3)
cam_periph.h (r1.1.1.1 -> r1.2)
cam_sim.c (r1.1.1.1 -> r1.2)
cam_sim.h (r1.1.1.1 -> r1.2)
cam_xpt.c (r1.2 -> r1.3)
cam_xpt.h (r1.1.1.1 -> r1.2)
cam_xpt_periph.h (r1.1.1.1 -> r1.2)
cam_xpt_sim.h (r1.1.1.1 -> r1.2)
src/sys/cam/scsi:
scsi_all.c (r1.2 -> r1.3)
scsi_all.h (r1.2 -> r1.3)
scsi_cd.c (r1.2 -> r1.3)
scsi_ch.c (r1.1.1.1 -> r1.2)
scsi_da.c (r1.2 -> r1.3)
scsi_low.c (r1.1.1.1 -> r1.2)
scsi_pass.c (r1.2 -> r1.3)
scsi_pt.c (r1.1.1.1 -> r1.2)
scsi_sa.c (r1.1.1.2 -> r1.2)
scsi_ses.c (r1.1.1.1 -> r1.2)
scsi_ses.h (r1.2 -> r1.3)
scsi_targ_bh.c (r1.1.1.1 -> r1.2)
scsi_target.c (r1.1.1.1 -> r1.2)
Added Files:
-----------
src/sys/cam/scsi:
scsi_sg.c (r1.1)
scsi_sg.h (r1.1)
-------------- next part --------------
Index: cam_xpt.c
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_xpt.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/cam_xpt.c -L sys/cam/cam_xpt.c -u -r1.2 -r1.3
--- sys/cam/cam_xpt.c
+++ sys/cam/cam_xpt.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_xpt.c,v 1.155.2.8 2006/09/23 18:42:08 mjacob Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_xpt.c,v 1.190.4.1 2008/01/31 14:19:06 brueffer Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -42,10 +42,12 @@
#include <sys/md5.h>
#include <sys/interrupt.h>
#include <sys/sbuf.h>
+#include <sys/taskqueue.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
+#include <sys/kthread.h>
#ifdef PC98
#include <pc98/pc98/pc98_machdep.h> /* geometry translation */
@@ -63,11 +65,19 @@
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
+#include <machine/stdarg.h> /* for xpt_print below */
#include "opt_cam.h"
/* 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 *data1;
+ uintptr_t data2;
+};
+
/*
* Definition of an async handler callback block. These are used to add
* SIMs and peripherals to the async callback lists.
@@ -82,7 +92,6 @@
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)
@@ -92,9 +101,6 @@
#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,
@@ -115,6 +121,7 @@
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
@@ -127,12 +134,10 @@
struct cam_periph *owner; /* Peripheral driver's ownership tag */
struct xpt_quirk_entry *quirk; /* Oddities about this device */
/* Storage for the inquiry data */
-#ifdef CAM_NEW_TRAN_CODE
cam_proto protocol;
u_int protocol_version;
cam_xport transport;
u_int transport_version;
-#endif /* CAM_NEW_TRAN_CODE */
struct scsi_inquiry_data inq_data;
u_int8_t inq_flags; /*
* Current settings for inquiry flags.
@@ -152,11 +157,13 @@
#define CAM_DEV_RESIZE_QUEUE_NEEDED 0x10
#define CAM_DEV_TAG_AFTER_COUNT 0x20
#define CAM_DEV_INQUIRY_DATA_VALID 0x40
+#define CAM_DEV_IN_DV 0x80
+#define CAM_DEV_DV_HIT_BOTTOM 0x100
u_int32_t tag_delay_count;
#define CAM_TAG_DELAY_COUNT 5
u_int32_t tag_saved_openings;
u_int32_t refcount;
- struct callout_handle c_handle;
+ struct callout callout;
};
/*
@@ -190,6 +197,7 @@
#define CAM_EB_RUNQ_SCHEDULED 0x01
u_int32_t refcount;
u_int generation;
+ device_t parent_dev;
};
struct cam_path {
@@ -240,8 +248,24 @@
} 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";
@@ -387,7 +411,7 @@
/*quirks*/0, /*mintags*/0, /*maxtags*/0
},
{
- /* Does not support other than LUN 0 */
+ /* This does not support other than LUN 0 */
{ T_DIRECT, SIP_MEDIA_FIXED, "VMware*", "*", "*" },
CAM_QUIRK_NOLUNS, /*mintags*/2, /*maxtags*/255
},
@@ -596,6 +620,18 @@
CAM_QUIRK_NOLUNS, /*mintags*/0, /*maxtags*/0
},
{
+ /*
+ * Western Digital My Book 250GB (USB)
+ * hangs upon serial number probing.
+ * PR: 107495
+ */
+ {
+ T_DIRECT, SIP_MEDIA_FIXED, "WD",
+ "2500JB External", "*"
+ },
+ CAM_QUIRK_NOSERIAL, /*mintags*/0, /*maxtags*/0
+ },
+ {
/* Default tagged queuing parameters for all devices */
{
T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
@@ -642,17 +678,12 @@
/* Queues for our software interrupt handler */
typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
-static cam_isrq_t cam_bioq;
-static struct mtx cam_bioq_lock;
+typedef TAILQ_HEAD(cam_simq, cam_sim) cam_simq_t;
+static cam_simq_t cam_simq;
+static struct mtx cam_simq_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;
@@ -682,14 +713,13 @@
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);
@@ -703,9 +733,6 @@
#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
@@ -714,9 +741,6 @@
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
@@ -748,7 +772,7 @@
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);
@@ -779,7 +803,7 @@
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);
@@ -811,11 +835,7 @@
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 void camisr_runqueue(void *);
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,
@@ -854,16 +874,8 @@
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,
@@ -873,12 +885,12 @@
static void probeschedule(struct cam_periph *probe_periph);
static void probestart(struct cam_periph *periph, union ccb *start_ccb);
static void proberequestdefaultnegotiation(struct cam_periph *periph);
+static int proberequestbackoff(struct cam_periph *periph,
+ struct cam_ed *device);
static void probedone(struct cam_periph *periph, union ccb *done_ccb);
static void probecleanup(struct cam_periph *periph);
static void xpt_find_quirk(struct cam_ed *device);
-#ifdef CAM_NEW_TRAN_CODE
static void xpt_devise_transport(struct cam_path *path);
-#endif /* CAM_NEW_TRAN_CODE */
static void xpt_set_transfer_settings(struct ccb_trans_settings *cts,
struct cam_ed *device,
int async_update);
@@ -994,9 +1006,6 @@
static int
xptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
- int unit;
-
- unit = minor(dev) & 0xff;
/*
* Only allow read-write access.
@@ -1008,22 +1017,14 @@
* 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);
}
@@ -1031,43 +1032,27 @@
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) {
/*
@@ -1079,9 +1064,16 @@
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,6 +1089,8 @@
ccb = xpt_alloc_ccb();
+ CAM_SIM_LOCK(bus->sim);
+
/*
* Create a path using the bus, target, and lun the
* user passed in.
@@ -1107,6 +1101,7 @@
inccb->ccb_h.target_lun) !=
CAM_REQ_CMP){
error = EINVAL;
+ CAM_SIM_UNLOCK(bus->sim);
xpt_free_ccb(ccb);
break;
}
@@ -1119,6 +1114,7 @@
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: {
@@ -1129,6 +1125,8 @@
* allocate it on the stack.
*/
+ CAM_SIM_LOCK(bus->sim);
+
/*
* Create a path using the bus, target, and lun the
* user passed in.
@@ -1147,6 +1145,7 @@
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;
@@ -1211,6 +1210,7 @@
error = ENOTSUP;
break;
}
+ xpt_release_bus(bus);
break;
}
/*
@@ -1224,7 +1224,7 @@
* we never return a status of CAM_GDEVLIST_LIST_CHANGED. It is
* (or rather should be) impossible for the device peripheral driver
* list to change since we look at the whole thing in one pass, and
- * we do it with splcam protection.
+ * we do it with lock protection.
*
*/
case CAMGETPASSTHRU: {
@@ -1236,13 +1236,12 @@
u_int cur_generation;
int base_periph_found;
int splbreaknum;
- int s;
ccb = (union ccb *)addr;
unit = ccb->cgdl.unit_number;
name = ccb->cgdl.periph_name;
/*
- * Every 100 devices, we want to drop our spl protection to
+ * Every 100 devices, we want to drop our lock protection to
* give the software interrupt handler a chance to run.
* Most systems won't run into this check, but this should
* avoid starvation in the software interrupt handler in
@@ -1264,9 +1263,9 @@
}
/* Keep the list from changing while we traverse it */
- s = splcam();
+ mtx_lock(&xsoftc.xpt_topo_lock);
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++)
@@ -1274,7 +1273,7 @@
break;
if (*p_drv == NULL) {
- splx(s);
+ mtx_unlock(&xsoftc.xpt_topo_lock);
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
ccb->cgdl.status = CAM_GDEVLIST_ERROR;
*ccb->cgdl.periph_name = '\0';
@@ -1296,10 +1295,10 @@
if (periph->unit_number == unit) {
break;
} else if (--splbreaknum == 0) {
- splx(s);
- s = splcam();
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ mtx_lock(&xsoftc.xpt_topo_lock);
splbreaknum = 100;
- if (cur_generation != xsoftc.generation)
+ if (cur_generation != xsoftc.xpt_generation)
goto ptstartover;
}
}
@@ -1382,11 +1381,11 @@
if (base_periph_found == 1) {
printf("xptioctl: pass driver is not in the "
"kernel\n");
- printf("xptioctl: put \"device pass0\" in "
+ printf("xptioctl: put \"device pass\" in "
"your kernel config file\n");
}
}
- splx(s);
+ mtx_unlock(&xsoftc.xpt_topo_lock);
break;
}
default:
@@ -1400,33 +1399,102 @@
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;
}
return 0;
}
-/* Functions accessed by the peripheral drivers */
+/* thread to handle bus rescans */
static void
-xpt_init(dummy)
- void *dummy;
+xpt_scanner_thread(void *dummy)
+{
+ cam_isrq_t queue;
+ union ccb *ccb;
+ struct cam_sim *sim;
+
+ for (;;) {
+ /*
+ * 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;
+ CAM_SIM_LOCK(sim);
+
+ 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);
+ CAM_SIM_UNLOCK(sim);
+ }
+ }
+}
+
+void
+xpt_rescan(union ccb *ccb)
+{
+ struct ccb_hdr *hdr;
+
+ /*
+ * Don't make duplicate entries for the same paths.
+ */
+ 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(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+ wakeup(&xsoftc.ccb_scanq);
+ xpt_unlock_buses();
+}
+
+/* Functions accessed by the peripheral drivers */
+static int
+xpt_init(void *dummy)
{
struct cam_sim *xpt_sim;
struct cam_path *path;
struct cam_devq *devq;
cam_status status;
- TAILQ_INIT(&xpt_busses);
- TAILQ_INIT(&cam_bioq);
- SLIST_INIT(&ccb_freeq);
- STAILQ_INIT(&highpowerq);
-
- mtx_init(&cam_bioq_lock, "CAM BIOQ lock", NULL, MTX_DEF);
+ TAILQ_INIT(&xsoftc.xpt_busses);
+ TAILQ_INIT(&cam_simq);
+ TAILQ_INIT(&xsoftc.ccb_scanq);
+ STAILQ_INIT(&xsoftc.highpowerq);
+ xsoftc.num_highpower = CAM_MAX_HIGHPOWER;
+
+ mtx_init(&cam_simq_lock, "CAM SIMQ 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.
@@ -1440,12 +1508,21 @@
"xpt",
/*softc*/NULL,
/*unit*/0,
+ /*mtx*/&xsoftc.xpt_lock,
/*max_dev_transactions*/0,
/*max_tagged_dev_transactions*/0,
devq);
- xpt_max_ccbs = 16;
-
- xpt_bus_register(xpt_sim, /*bus #*/0);
+ if (xpt_sim == NULL)
+ return (ENOMEM);
+
+ xpt_sim->max_ccbs = 16;
+
+ mtx_lock(&xsoftc.xpt_lock);
+ if ((status = xpt_bus_register(xpt_sim, NULL, 0)) != CAM_SUCCESS) {
+ printf("xpt_init: xpt_bus_register failed with status %#x,"
+ " failing attach\n", status);
+ return (EINVAL);
+ }
/*
* Looking at the XPT from the SIM layer, the XPT is
@@ -1457,49 +1534,57 @@
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) {
+ M_CAMXPT, M_NOWAIT | M_ZERO);
+ 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_CAMXPT);
printf("xpt_init: config_intrhook_establish failed "
"- failing attach\n");
}
+ /* fire up rescan thread */
+ if (kthread_create(xpt_scanner_thread, NULL, NULL, 0, 0, "xpt_thrd")) {
+ 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, NULL, 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);
}
@@ -1511,7 +1596,7 @@
int32_t status;
struct periph_list *periph_head;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
device = periph->path->device;
@@ -1520,25 +1605,22 @@
status = CAM_REQ_CMP;
if (device != NULL) {
- int s;
-
/*
* Make room for this peripheral
* so it will fit in the queue
* when it's scheduled to run
*/
- s = splsoftcam();
status = camq_resize(&device->drvq,
device->drvq.array_size + 1);
device->generation++;
SLIST_INSERT_HEAD(periph_head, periph, periph_links);
-
- splx(s);
}
- xsoftc.generation++;
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ xsoftc.xpt_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
return (status);
}
@@ -1548,32 +1630,28 @@
{
struct cam_ed *device;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
device = periph->path->device;
if (device != NULL) {
- int s;
struct periph_list *periph_head;
periph_head = &device->periphs;
/* Release the slot for this peripheral */
- s = splsoftcam();
camq_resize(&device->drvq, device->drvq.array_size - 1);
device->generation++;
SLIST_REMOVE(periph_head, periph, cam_periph, periph_links);
-
- splx(s);
}
- xsoftc.generation++;
-
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ xsoftc.xpt_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
}
-#ifdef CAM_NEW_TRAN_CODE
void
xpt_announce_periph(struct cam_periph *periph, char *announce_string)
@@ -1584,16 +1662,14 @@
u_int speed;
u_int freq;
u_int mb;
- int s;
- GIANT_REQUIRED;
+ mtx_assert(periph->sim->mtx, MA_OWNED);
path = periph->path;
/*
* To ensure that this is printed in one piece,
* mask out CAM interrupts.
*/
- s = splsoftcam();
printf("%s%d at %s%d bus %d target %d lun %d\n",
periph->periph_name, periph->unit_number,
path->bus->sim->sim_name,
@@ -1612,6 +1688,9 @@
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb*)&cts);
+ if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ return;
+ }
/* Ask the SIM for its base transfer speed */
xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
@@ -1641,6 +1720,13 @@
}
}
+ if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) {
+ struct ccb_trans_settings_sas *sas = &cts.xport_specific.sas;
+ if (sas->valid & CTS_SAS_VALID_SPEED) {
+ speed = sas->bitrate;
+ }
+ }
+
mb = speed / 1000;
if (mb > 0)
printf("%s%d: %d.%03dMB/s transfers",
@@ -1687,7 +1773,7 @@
if (path->device->inq_flags & SID_CmdQue
|| path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
- printf("\n%s%d: Tagged Queueing Enabled",
+ printf("\n%s%d: Command Queueing Enabled",
periph->periph_name, periph->unit_number);
}
printf("\n");
@@ -1699,116 +1785,8 @@
if (announce_string != NULL)
printf("%s%d: %s\n", periph->periph_name,
periph->unit_number, announce_string);
- splx(s);
-}
-#else /* CAM_NEW_TRAN_CODE */
-void
-xpt_announce_periph(struct cam_periph *periph, char *announce_string)
-{
- int s;
- u_int mb;
- struct cam_path *path;
- struct ccb_trans_settings cts;
-
- GIANT_REQUIRED;
-
- path = periph->path;
- /*
- * To ensure that this is printed in one piece,
- * mask out CAM interrupts.
- */
- s = splsoftcam();
- printf("%s%d at %s%d bus %d target %d lun %d\n",
- periph->periph_name, periph->unit_number,
- path->bus->sim->sim_name,
- path->bus->sim->unit_number,
- path->bus->sim->bus_id,
- path->target->target_id,
- path->device->lun_id);
- printf("%s%d: ", periph->periph_name, periph->unit_number);
- scsi_print_inquiry(&path->device->inq_data);
- if ((bootverbose)
- && (path->device->serial_num_len > 0)) {
- /* Don't wrap the screen - print only the first 60 chars */
- printf("%s%d: Serial Number %.60s\n", periph->periph_name,
- periph->unit_number, path->device->serial_num);
- }
- xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1);
- cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
- cts.flags = CCB_TRANS_CURRENT_SETTINGS;
- xpt_action((union ccb*)&cts);
- if (cts.ccb_h.status == CAM_REQ_CMP) {
- u_int speed;
- u_int freq;
-
- if ((cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0
- && cts.sync_offset != 0) {
- freq = scsi_calc_syncsrate(cts.sync_period);
- speed = freq;
- } else {
- struct ccb_pathinq cpi;
-
- /* Ask the SIM for its base transfer speed */
- xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
-
- speed = cpi.base_transfer_speed;
- freq = 0;
- }
- if ((cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
- speed *= (0x01 << cts.bus_width);
- mb = speed / 1000;
- if (mb > 0)
- printf("%s%d: %d.%03dMB/s transfers",
- periph->periph_name, periph->unit_number,
- mb, speed % 1000);
- else
- printf("%s%d: %dKB/s transfers", periph->periph_name,
- periph->unit_number, speed);
- if ((cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0
- && cts.sync_offset != 0) {
- printf(" (%d.%03dMHz, offset %d", freq / 1000,
- freq % 1000, cts.sync_offset);
- }
- if ((cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0
- && cts.bus_width > 0) {
- if ((cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0
- && cts.sync_offset != 0) {
- printf(", ");
- } else {
- printf(" (");
- }
- printf("%dbit)", 8 * (0x01 << cts.bus_width));
- } else if ((cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0
- && cts.sync_offset != 0) {
- printf(")");
- }
-
- if (path->device->inq_flags & SID_CmdQue
- || path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
- printf(", Tagged Queueing Enabled");
- }
-
- printf("\n");
- } else if (path->device->inq_flags & SID_CmdQue
- || path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
- printf("%s%d: Tagged Queueing Enabled\n",
- periph->periph_name, periph->unit_number);
- }
-
- /*
- * We only want to print the caller's announce string if they've
- * passed one in..
- */
- if (announce_string != NULL)
- printf("%s%d: %s\n", periph->periph_name,
- periph->unit_number, announce_string);
- splx(s);
}
-#endif /* CAM_NEW_TRAN_CODE */
-
static dev_match_ret
xptbusmatch(struct dev_match_pattern *patterns, u_int num_patterns,
struct cam_eb *bus)
@@ -2194,7 +2172,7 @@
cdm->pos.cookie.bus = bus;
cdm->pos.generations[CAM_BUS_GENERATION]=
- bus_generation;
+ xsoftc.bus_generation;
cdm->status = CAM_DEV_MATCH_MORE;
return(0);
}
@@ -2326,7 +2304,7 @@
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;
@@ -2436,7 +2414,7 @@
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;
@@ -2481,7 +2459,7 @@
*/
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);
}
@@ -2680,15 +2658,21 @@
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);
+ CAM_SIM_LOCK(bus->sim);
retval = tr_func(bus, arg);
+ CAM_SIM_UNLOCK(bus->sim);
if (retval == 0)
return(retval);
+ mtx_lock(&xsoftc.xpt_topo_lock);
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
return(retval);
}
@@ -2899,23 +2883,6 @@
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.
*/
@@ -2931,23 +2898,6 @@
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)
{
@@ -3006,24 +2956,47 @@
return(1);
}
+static void
+xpt_action_sasync_cb(void *context, int pending)
+{
+ struct async_node *cur_entry;
+ struct xpt_task *task;
+ uint32_t added;
+
+ task = (struct xpt_task *)context;
+ cur_entry = (struct async_node *)task->data1;
+ added = task->data2;
+
+ 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);
+ }
+
+ 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;
- iopl = splsoftcam();
switch (start_ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
{
-#ifdef CAM_NEW_TRAN_CODE
struct cam_ed *device;
-#endif /* CAM_NEW_TRAN_CODE */
#ifdef CAMDEBUG
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
struct cam_path *path;
@@ -3047,12 +3020,8 @@
* This means that this code will be exercised while probing
* devices with an ANSI revision greater than 2.
*/
-#ifdef CAM_NEW_TRAN_CODE
device = start_ccb->ccb_h.path->device;
if (device->protocol_version <= SCSI_REV_2
-#else /* CAM_NEW_TRAN_CODE */
- if (SID_ANSI_REV(&start_ccb->ccb_h.path->device->inq_data) <= 2
-#endif /* CAM_NEW_TRAN_CODE */
&& start_ccb->ccb_h.target_lun < 8
&& (start_ccb->ccb_h.flags & CAM_CDB_POINTER) == 0) {
@@ -3077,18 +3046,15 @@
{
struct cam_path *path;
struct cam_sim *sim;
- int s;
int runq;
path = start_ccb->ccb_h.path;
- s = splsoftcam();
sim = path->bus->sim;
if (SIM_DEAD(sim)) {
/* The SIM has gone; just execute the CCB directly. */
cam_ccbq_send_ccb(&path->device->ccbq, start_ccb);
(*(sim->sim_action))(sim, start_ccb);
- splx(s);
break;
}
@@ -3097,7 +3063,6 @@
runq = xpt_schedule_dev_sendq(path->bus, path->device);
else
runq = 0;
- splx(s);
if (runq != 0)
xpt_run_dev_sendq(path->bus);
break;
@@ -3144,7 +3109,6 @@
case XPT_ABORT:
{
union ccb* abort_ccb;
- int s;
abort_ccb = start_ccb->cab.abort_ccb;
if (XPT_FC_IS_DEV_QUEUED(abort_ccb)) {
@@ -3157,9 +3121,7 @@
abort_ccb->ccb_h.status =
CAM_REQ_ABORTED|CAM_DEV_QFRZN;
xpt_freeze_devq(abort_ccb->ccb_h.path, 1);
- s = splcam();
xpt_done(abort_ccb);
- splx(s);
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@@ -3222,10 +3184,8 @@
case XPT_GDEV_TYPE:
{
struct cam_ed *dev;
- int s;
dev = start_ccb->ccb_h.path->device;
- s = splcam();
if ((dev->flags & CAM_DEV_UNCONFIGURED) != 0) {
start_ccb->ccb_h.status = CAM_DEV_NOT_THERE;
} else {
@@ -3244,16 +3204,13 @@
bcopy(dev->serial_num, cgd->serial_num,
dev->serial_num_len);
}
- splx(s);
break;
}
case XPT_GDEV_STATS:
{
struct cam_ed *dev;
- int s;
dev = start_ccb->ccb_h.path->device;
- s = splcam();
if ((dev->flags & CAM_DEV_UNCONFIGURED) != 0) {
start_ccb->ccb_h.status = CAM_DEV_NOT_THERE;
} else {
@@ -3276,7 +3233,6 @@
cgds->last_reset = bus->last_reset;
cgds->ccb_h.status = CAM_REQ_CMP;
}
- splx(s);
break;
}
case XPT_GDEVLIST:
@@ -3285,7 +3241,6 @@
struct periph_list *periph_head;
struct ccb_getdevlist *cgdl;
u_int i;
- int s;
struct cam_ed *device;
int found;
@@ -3295,7 +3250,6 @@
/*
* Don't want anyone mucking with our data.
*/
- s = splcam();
device = start_ccb->ccb_h.path->device;
periph_head = &device->periphs;
cgdl = &start_ccb->cgdl;
@@ -3309,7 +3263,6 @@
if ((cgdl->index != 0) &&
(cgdl->generation != device->generation)) {
cgdl->status = CAM_GDEVLIST_LIST_CHANGED;
- splx(s);
break;
}
@@ -3330,7 +3283,6 @@
}
if (found == 0) {
cgdl->status = CAM_GDEVLIST_ERROR;
- splx(s);
break;
}
@@ -3342,23 +3294,17 @@
cgdl->index++;
cgdl->generation = device->generation;
- splx(s);
cgdl->ccb_h.status = CAM_REQ_CMP;
break;
}
case XPT_DEV_MATCH:
{
- int s;
dev_pos_type position_type;
struct ccb_dev_match *cdm;
cdm = &start_ccb->cdm;
/*
- * Prevent EDT changes while we traverse it.
- */
- s = splcam();
- /*
* There are two ways of getting at information in the EDT.
* The first way is via the primary EDT tree. It starts
* with a list of busses, then a list of targets on a bus,
@@ -3405,8 +3351,6 @@
break;
}
- splx(s);
-
if (cdm->status == CAM_DEV_MATCH_ERROR)
start_ccb->ccb_h.status = CAM_REQ_CMP_ERR;
else
@@ -3420,7 +3364,6 @@
struct async_node *cur_entry;
struct async_list *async_head;
u_int32_t added;
- int s;
csa = &start_ccb->csa;
added = csa->event_enable;
@@ -3430,7 +3373,6 @@
* If there is already an entry for us, simply
* update it.
*/
- s = splcam();
cur_entry = SLIST_FIRST(async_head);
while (cur_entry != NULL) {
if ((cur_entry->callback_arg == csa->callback_arg)
@@ -3457,7 +3399,6 @@
cur_entry = malloc(sizeof(*cur_entry), M_CAMXPT,
M_NOWAIT);
if (cur_entry == NULL) {
- splx(s);
csa->ccb_h.status = CAM_RESRC_UNAVAIL;
break;
}
@@ -3468,21 +3409,26 @@
csa->ccb_h.path->device->refcount++;
}
- 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);
+ /*
+ * Need to decouple this operation via a taqskqueue so that
+ * the locking doesn't become a mess.
+ */
+ if ((added & (AC_FOUND_DEVICE | AC_PATH_REGISTERED)) != 0) {
+ struct xpt_task *task;
+
+ task = malloc(sizeof(struct xpt_task), M_CAMXPT,
+ M_NOWAIT);
+ if (task == NULL) {
+ csa->ccb_h.status = CAM_RESRC_UNAVAIL;
+ break;
+ }
+
+ TASK_INIT(&task->task, 0, xpt_action_sasync_cb, task);
+ task->data1 = cur_entry;
+ task->data2 = added;
+ taskqueue_enqueue(taskqueue_thread, &task->task);
}
- splx(s);
+
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@@ -3490,7 +3436,6 @@
{
struct ccb_relsim *crs;
struct cam_ed *dev;
- int s;
crs = &start_ccb->crs;
dev = crs->ccb_h.path->device;
@@ -3500,8 +3445,6 @@
break;
}
- s = splcam();
-
if ((crs->release_flags & RELSIM_ADJUST_OPENINGS) != 0) {
if (INQ_DATA_TQ_ENABLED(&dev->inq_data)) {
@@ -3511,10 +3454,9 @@
crs->openings);
if (bootverbose) {
- xpt_print_path(crs->ccb_h.path);
- printf("tagged openings "
- "now %d\n",
- crs->openings);
+ xpt_print(crs->ccb_h.path,
+ "tagged openings now %d\n",
+ crs->openings);
}
}
}
@@ -3530,17 +3472,15 @@
* 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;
@@ -3574,8 +3514,7 @@
start_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
}
}
- splx(s);
-
+
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) {
xpt_release_devq(crs->ccb_h.path, /*count*/1,
@@ -3595,9 +3534,6 @@
break;
case XPT_DEBUG: {
#ifdef CAMDEBUG
- int s;
-
- s = splcam();
#ifdef CAM_DEBUG_DELAY
cam_debug_delay = CAM_DEBUG_DELAY;
#endif
@@ -3617,14 +3553,13 @@
cam_dflags = CAM_DEBUG_NONE;
} else {
start_ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_print_path(cam_dpath);
- printf("debugging flags now %x\n", cam_dflags);
+ xpt_print(cam_dpath, "debugging flags now %x\n",
+ cam_dflags);
}
} else {
cam_dpath = NULL;
start_ccb->ccb_h.status = CAM_REQ_CMP;
}
- splx(s);
#else /* !CAMDEBUG */
start_ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
#endif /* CAMDEBUG */
@@ -3643,26 +3578,23 @@
start_ccb->ccb_h.status = CAM_PROVIDE_FAIL;
break;
}
- splx(iopl);
}
void
xpt_polled_action(union ccb *start_ccb)
{
- int s;
u_int32_t timeout;
struct cam_sim *sim;
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;
- s = splcam();
+ mtx_assert(sim->mtx, MA_OWNED);
/*
* Steal an opening so that no other queued requests
@@ -3675,7 +3607,7 @@
dev->ccbq.dev_openings < 0) && (--timeout > 0)) {
DELAY(1000);
(*(sim->sim_poll))(sim);
- camisr(&cam_bioq);
+ camisr_runqueue(&sim->sim_doneq);
}
dev->ccbq.devq_openings++;
@@ -3685,7 +3617,7 @@
xpt_action(start_ccb);
while(--timeout > 0) {
(*(sim->sim_poll))(sim);
- camisr(&cam_bioq);
+ camisr_runqueue(&sim->sim_doneq);
if ((start_ccb->ccb_h.status & CAM_STATUS_MASK)
!= CAM_REQ_INPROG)
break;
@@ -3703,7 +3635,6 @@
} else {
start_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
}
- splx(s);
}
/*
@@ -3715,14 +3646,12 @@
{
struct cam_ed *device;
union ccb *work_ccb;
- 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;
- s = splsoftcam();
if (periph_is_queued(perph)) {
/* Simply reorder based on new priority */
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
@@ -3736,7 +3665,6 @@
} else if (SIM_DEAD(perph->path->bus->sim)) {
/* The SIM is gone so just call periph_start directly. */
work_ccb = xpt_get_ccb(perph->path->device);
- splx(s);
if (work_ccb == NULL)
return; /* XXX */
xpt_setup_ccb(&work_ccb->ccb_h, perph->path, new_priority);
@@ -3752,7 +3680,6 @@
camq_insert(&device->drvq, &perph->pinfo);
runq = xpt_schedule_dev_allocq(perph->path->bus, device);
}
- splx(s);
if (runq != 0) {
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
(" calling xpt_run_devq\n"));
@@ -3767,8 +3694,7 @@
* return 1 meaning the device queue should be run. If we
* were already queued, implying someone else has already
* started the queue, return 0 so the caller doesn't attempt
- * to run the queue. Must be run at either splsoftcam
- * (or splcam since that encompases splsoftcam).
+ * to run the queue.
*/
static int
xpt_schedule_dev(struct camq *queue, cam_pinfo *pinfo,
@@ -3812,7 +3738,6 @@
xpt_run_dev_allocq(struct cam_eb *bus)
{
struct cam_devq *devq;
- int s;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq\n"));
devq = bus->sim->devq;
@@ -3825,7 +3750,6 @@
devq->alloc_openings,
devq->alloc_active));
- s = splsoftcam();
devq->alloc_queue.qfrozen_cnt++;
while ((devq->alloc_queue.entries > 0)
&& (devq->alloc_openings > 0)
@@ -3855,7 +3779,6 @@
devq->alloc_openings--;
devq->alloc_active++;
drv = (struct cam_periph*)camq_remove(drvq, CAMQ_HEAD);
- splx(s);
xpt_setup_ccb(&work_ccb->ccb_h, drv->path,
drv->pinfo.priority);
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
@@ -3874,43 +3797,32 @@
break;
}
- /* Raise IPL for possible insertion and test at top of loop */
- s = splsoftcam();
-
if (drvq->entries > 0) {
/* We have more work. Attempt to reschedule */
xpt_schedule_dev_allocq(bus, device);
}
}
devq->alloc_queue.qfrozen_cnt--;
- splx(s);
}
static void
xpt_run_dev_sendq(struct cam_eb *bus)
{
struct cam_devq *devq;
- int s;
CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_sendq\n"));
devq = bus->sim->devq;
- s = splcam();
devq->send_queue.qfrozen_cnt++;
- splx(s);
- s = splsoftcam();
while ((devq->send_queue.entries > 0)
&& (devq->send_openings > 0)) {
struct cam_ed_qinfo *qinfo;
struct cam_ed *device;
union ccb *work_ccb;
struct cam_sim *sim;
- int ospl;
- ospl = splcam();
if (devq->send_queue.qfrozen_cnt > 1) {
- splx(ospl);
break;
}
@@ -3923,7 +3835,6 @@
* to run it.
*/
if (device->qfrozen_cnt > 0) {
- splx(ospl);
continue;
}
@@ -3933,13 +3844,13 @@
work_ccb = cam_ccbq_peek_ccb(&device->ccbq, CAMQ_HEAD);
if (work_ccb == NULL) {
printf("device on run queue with no ccbs???\n");
- splx(ospl);
continue;
}
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
@@ -3947,25 +3858,24 @@
* available.
*/
device->qfrozen_cnt++;
- STAILQ_INSERT_TAIL(&highpowerq,
+ STAILQ_INSERT_TAIL(&xsoftc.highpowerq,
&work_ccb->ccb_h,
xpt_links.stqe);
- splx(ospl);
continue;
} else {
/*
* 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);
cam_ccbq_send_ccb(&device->ccbq, work_ccb);
- splx(ospl);
devq->send_openings--;
devq->send_active++;
@@ -3978,12 +3888,8 @@
* The client wants to freeze the queue
* after this CCB is sent.
*/
- ospl = splcam();
device->qfrozen_cnt++;
- splx(ospl);
}
-
- splx(s);
/* In Target mode, the peripheral driver knows best... */
if (work_ccb->ccb_h.func_code == XPT_SCSI_IO) {
@@ -4007,16 +3913,9 @@
sim = work_ccb->ccb_h.path->bus->sim;
(*(sim->sim_action))(sim, work_ccb);
- ospl = splcam();
devq->active_dev = NULL;
- splx(ospl);
- /* Raise IPL for possible insertion and test at top of loop */
- s = splsoftcam();
}
- splx(s);
- s = splcam();
devq->send_queue.qfrozen_cnt--;
- splx(s);
}
/*
@@ -4026,7 +3925,6 @@
void
xpt_merge_ccb(union ccb *master_ccb, union ccb *slave_ccb)
{
- GIANT_REQUIRED;
/*
* Pull fields that are valid for peripheral drivers to set
@@ -4043,7 +3941,6 @@
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;
@@ -4071,8 +3968,6 @@
struct cam_path *path;
cam_status status;
- GIANT_REQUIRED;
-
path = (struct cam_path *)malloc(sizeof(*path), M_CAMXPT, M_NOWAIT);
if (path == NULL) {
@@ -4088,6 +3983,36 @@
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;
+ CAM_SIM_LOCK(bus->sim);
+ }
+ }
+ status = xpt_compile_path(path, periph, path_id, target_id, lun_id);
+ if (need_unlock)
+ CAM_SIM_UNLOCK(bus->sim);
+ 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)
@@ -4096,7 +4021,6 @@
struct cam_et *target;
struct cam_ed *device;
cam_status status;
- int s;
status = CAM_REQ_CMP; /* Completed without error */
target = NULL; /* Wildcarded */
@@ -4106,7 +4030,6 @@
* We will potentially modify the EDT, so block interrupts
* that may attempt to create cam paths.
*/
- s = splcam();
bus = xpt_find_bus(path_id);
if (bus == NULL) {
status = CAM_PATH_INVALID;
@@ -4140,7 +4063,6 @@
}
}
}
- splx(s);
/*
* Only touch the user's data if we are successful.
@@ -4183,7 +4105,6 @@
void
xpt_free_path(struct cam_path *path)
{
- GIANT_REQUIRED;
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_free_path\n"));
xpt_release_path(path);
@@ -4198,8 +4119,6 @@
int
xpt_path_comp(struct cam_path *path1, struct cam_path *path2)
{
- GIANT_REQUIRED;
-
int retval = 0;
if (path1->bus != path2->bus) {
@@ -4234,7 +4153,6 @@
void
xpt_print_path(struct cam_path *path)
{
- GIANT_REQUIRED;
if (path == NULL)
printf("(nopath): ");
@@ -4264,12 +4182,22 @@
}
}
+void
+xpt_print(struct cam_path *path, const char *fmt, ...)
+{
+ va_list ap;
+ xpt_print_path(path);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
int
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);
@@ -4307,7 +4235,7 @@
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);
}
@@ -4315,7 +4243,7 @@
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);
@@ -4326,7 +4254,7 @@
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);
@@ -4337,7 +4265,6 @@
struct cam_sim *
xpt_path_sim(struct cam_path *path)
{
- GIANT_REQUIRED;
return (path->bus->sim);
}
@@ -4345,7 +4272,7 @@
struct cam_periph*
xpt_path_periph(struct cam_path *path)
{
- GIANT_REQUIRED;
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
return (path->periph);
}
@@ -4359,38 +4286,38 @@
void
xpt_release_ccb(union ccb *free_ccb)
{
- int s;
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;
- s = splsoftcam();
+ sim = bus->sim;
+
+ 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) {
- splx(s);
+ if (sim->devq == NULL) {
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);
}
@@ -4406,14 +4333,13 @@
* availible, the bus will be probed.
*/
int32_t
-xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
+xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
{
struct cam_eb *new_bus;
struct cam_eb *old_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),
@@ -4436,17 +4362,17 @@
new_bus->flags = 0;
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++;
- splx(s);
+ TAILQ_INSERT_TAIL(&xsoftc.xpt_busses, new_bus, links);
+ xsoftc.bus_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
/* Notify interested parties */
if (sim->path_id != CAM_XPT_PATH_ID) {
@@ -4475,7 +4401,6 @@
union ccb *work_ccb;
cam_status status;
- GIANT_REQUIRED;
status = xpt_compile_path(&bus_path, NULL, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
@@ -4487,6 +4412,7 @@
/* The SIM may be gone, so use a dummy SIM for any stray operations. */
devq = bus_path.bus->sim->devq;
+ ccbsim = bus_path.bus->sim;
bus_path.bus->sim = &cam_dead_sim;
/* Execute any pending operations now. */
@@ -4501,7 +4427,6 @@
devq->active_dev = device;
cam_ccbq_remove_ccb(&device->ccbq, work_ccb);
cam_ccbq_send_ccb(&device->ccbq, work_ccb);
- ccbsim = work_ccb->ccb_h.path->bus->sim;
(*(ccbsim->sim_action))(ccbsim, work_ccb);
}
@@ -4513,8 +4438,8 @@
}
/* Make sure all completed CCBs are processed. */
- while (!TAILQ_EMPTY(&cam_bioq)) {
- camisr(&cam_bioq);
+ while (!TAILQ_EMPTY(&ccbsim->sim_doneq)) {
+ camisr_runqueue(&ccbsim->sim_doneq);
/* Repeat the async's for the benefit of any new devices. */
xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
@@ -4525,10 +4450,6 @@
xpt_release_bus(bus_path.bus);
xpt_release_path(&bus_path);
- /* Recheck for more completed CCBs. */
- while (!TAILQ_EMPTY(&cam_bioq))
- camisr(&cam_bioq);
-
return (CAM_REQ_CMP);
}
@@ -4540,15 +4461,16 @@
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) {
+ while (bus != NULL && bus->path_id <= pathid) {
if (bus->path_id == pathid)
pathid++;
bus = TAILQ_NEXT(bus, links);
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
/*
* Ensure that this pathid is not reserved for
@@ -4557,6 +4479,7 @@
if (resource_string_value("scbus", pathid, "at", &strval) == 0) {
++pathid;
/* Start the search over */
+ mtx_lock(&xsoftc.xpt_topo_lock);
goto retry;
}
return (pathid);
@@ -4611,9 +4534,8 @@
struct cam_eb *bus;
struct cam_et *target, *next_target;
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"));
@@ -4621,20 +4543,14 @@
* Most async events come from a CAM interrupt context. In
* a few cases, the error recovery code at the peripheral layer,
* which may run from our SWI or a process context, may signal
- * deferred events with a call to xpt_async. Ensure async
- * notifications are serialized by blocking cam interrupts.
+ * deferred events with a call to xpt_async.
*/
- s = splcam();
bus = path->bus;
if (async_code == AC_BUS_RESET) {
- int s;
-
- s = splclock();
/* Update our notion of when the last reset occurred */
microtime(&bus->last_reset);
- splx(s);
}
for (target = TAILQ_FIRST(&bus->et_entries);
@@ -4649,12 +4565,8 @@
continue;
if (async_code == AC_SENT_BDR) {
- int s;
-
/* Update our notion of when the last reset occurred */
- s = splclock();
microtime(&path->target->last_reset);
- splx(s);
}
for (device = TAILQ_FIRST(&target->ed_entries);
@@ -4683,7 +4595,6 @@
if (bus != xpt_periph->path->bus)
xpt_async_bcast(&xpt_periph->path->device->asyncs, async_code,
path, async_arg);
- splx(s);
}
static void
@@ -4777,12 +4688,10 @@
u_int32_t
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;
/*
@@ -4794,21 +4703,20 @@
* freezes the queue. To completly close the
* hole, controller drives must check to see
* if a ccb's status is still CAM_REQ_INPROG
- * under spl protection just before they queue
+ * just before they queue
* the CCB. See ahc_action/ahc_freeze_devq for
* an example.
*/
ccbh = TAILQ_LAST(&path->device->ccbq.active_ccbs, ccb_hdr_tailq);
if (ccbh && ccbh->status == CAM_REQ_INPROG)
ccbh->status = CAM_REQUEUE_REQ;
- splx(s);
return (path->device->qfrozen_cnt);
}
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) {
@@ -4835,7 +4743,7 @@
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);
}
@@ -4844,11 +4752,8 @@
xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
{
int rundevq;
- int s0, s1;
rundevq = 0;
- s0 = splsoftcam();
- s1 = splcam();
if (dev->qfrozen_cnt > 0) {
count = (count > dev->qfrozen_cnt) ? dev->qfrozen_cnt : count;
@@ -4866,8 +4771,7 @@
* 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;
}
@@ -4883,22 +4787,18 @@
}
}
}
- splx(s1);
if (rundevq != 0)
xpt_run_dev_sendq(dev->target->bus);
- splx(s0);
}
void
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();
if (sendq->qfrozen_cnt > 0) {
sendq->qfrozen_cnt--;
@@ -4911,12 +4811,10 @@
* 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);
- splx(s);
if (run_queue) {
/*
@@ -4925,13 +4823,14 @@
xpt_run_dev_sendq(bus);
}
xpt_release_bus(bus);
- } else
- splx(s);
- } else
- splx(s);
+ }
+ }
}
-static void
+/*
+ * XXX Appears to be unused.
+ */
+static void
xpt_release_simq_timeout(void *arg)
{
struct cam_sim *sim;
@@ -4943,9 +4842,7 @@
void
xpt_done(union ccb *done_ccb)
{
- int s;
-
- s = splcam();
+ struct cam_sim *sim;
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done\n"));
if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
@@ -4953,21 +4850,28 @@
* Queue up the request for handling by our SWI handler
* any of the "non-immediate" type of ccbs.
*/
+ sim = done_ccb->ccb_h.path->bus->sim;
switch (done_ccb->ccb_h.path->periph->type) {
case CAM_PERIPH_BIO:
- mtx_lock(&cam_bioq_lock);
- TAILQ_INSERT_TAIL(&cam_bioq, &done_ccb->ccb_h,
+ TAILQ_INSERT_TAIL(&sim->sim_doneq, &done_ccb->ccb_h,
sim_links.tqe);
done_ccb->ccb_h.pinfo.index = CAM_DONEQ_INDEX;
- mtx_unlock(&cam_bioq_lock);
- swi_sched(cambio_ih, 0);
+ if ((sim->flags & CAM_SIM_ON_DONEQ) == 0) {
+ mtx_lock(&cam_simq_lock);
+ TAILQ_INSERT_TAIL(&cam_simq, sim,
+ links);
+ sim->flags |= CAM_SIM_ON_DONEQ;
+ mtx_unlock(&cam_simq_lock);
+ }
+ if ((done_ccb->ccb_h.path->periph->flags &
+ CAM_PERIPH_POLLED) == 0)
+ swi_sched(cambio_ih, 0);
break;
default:
panic("unknown periph type %d",
done_ccb->ccb_h.path->periph->type);
}
}
- splx(s);
}
union ccb *
@@ -4975,9 +4879,7 @@
{
union ccb *new_ccb;
- GIANT_REQUIRED;
-
- new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_WAITOK);
+ new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_ZERO|M_WAITOK);
return (new_ccb);
}
@@ -4986,9 +4888,7 @@
{
union ccb *new_ccb;
- GIANT_REQUIRED;
-
- new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_NOWAIT);
+ new_ccb = malloc(sizeof(*new_ccb), M_CAMXPT, M_ZERO|M_NOWAIT);
return (new_ccb);
}
@@ -5013,40 +4913,37 @@
xpt_get_ccb(struct cam_ed *device)
{
union ccb *new_ccb;
- int s;
+ struct cam_sim *sim;
- s = splsoftcam();
- if ((new_ccb = (union ccb *)SLIST_FIRST(&ccb_freeq)) == NULL) {
+ sim = device->sim;
+ if ((new_ccb = (union ccb *)SLIST_FIRST(&sim->ccb_freeq)) == NULL) {
new_ccb = xpt_alloc_ccb_nowait();
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,
+ if ((sim->flags & CAM_SIM_MPSAFE) == 0)
+ callout_handle_init(&new_ccb->ccb_h.timeout_ch);
+ 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);
- splx(s);
+ SLIST_REMOVE_HEAD(&sim->ccb_freeq, xpt_links.sle);
return (new_ccb);
}
static void
xpt_release_bus(struct cam_eb *bus)
{
- int s;
- s = splcam();
if ((--bus->refcount == 0)
&& (TAILQ_FIRST(&bus->et_entries) == NULL)) {
- TAILQ_REMOVE(&xpt_busses, bus, links);
- bus_generation++;
- splx(s);
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
+ xsoftc.bus_generation++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
free(bus, M_CAMXPT);
- } else
- splx(s);
+ }
}
static struct cam_et *
@@ -5088,26 +4985,20 @@
static void
xpt_release_target(struct cam_eb *bus, struct cam_et *target)
{
- int s;
- s = splcam();
if ((--target->refcount == 0)
&& (TAILQ_FIRST(&target->ed_entries) == NULL)) {
TAILQ_REMOVE(&bus->et_entries, target, links);
bus->generation++;
- splx(s);
free(target, M_CAMXPT);
xpt_release_bus(bus);
- } else
- splx(s);
+ }
}
static struct cam_ed *
xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
{
-#ifdef CAM_NEW_TRAN_CODE
struct cam_path path;
-#endif /* CAM_NEW_TRAN_CODE */
struct cam_ed *device;
struct cam_devq *devq;
cam_status status;
@@ -5135,6 +5026,7 @@
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);
@@ -5165,7 +5057,10 @@
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
@@ -5177,7 +5072,7 @@
* 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)
@@ -5188,7 +5083,6 @@
TAILQ_INSERT_TAIL(&target->ed_entries, device, links);
}
target->generation++;
-#ifdef CAM_NEW_TRAN_CODE
if (lun_id != CAM_LUN_WILDCARD) {
xpt_compile_path(&path,
NULL,
@@ -5198,7 +5092,6 @@
xpt_devise_transport(&path);
xpt_release_path(&path);
}
-#endif /* CAM_NEW_TRAN_CODE */
}
return (device);
}
@@ -5207,9 +5100,7 @@
xpt_release_device(struct cam_eb *bus, struct cam_et *target,
struct cam_ed *device)
{
- int s;
- s = splcam();
if ((--device->refcount == 0)
&& ((device->flags & CAM_DEV_UNCONFIGURED) != 0)) {
struct cam_devq *devq;
@@ -5219,36 +5110,31 @@
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;
cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
}
- splx(s);
camq_fini(&device->drvq);
camq_fini(&device->ccbq.queue);
free(device, M_CAMXPT);
xpt_release_target(bus, target);
- } else
- splx(s);
+ }
}
static u_int32_t
xpt_dev_ccbq_resize(struct cam_path *path, int newopenings)
{
- int s;
int diff;
int result;
struct cam_ed *dev;
dev = path->device;
- s = splsoftcam();
diff = newopenings - (dev->ccbq.dev_active + dev->ccbq.dev_openings);
result = cam_ccbq_resize(&dev->ccbq, newopenings);
@@ -5259,8 +5145,7 @@
|| (dev->inq_flags & SID_CmdQue) != 0)
dev->tag_saved_openings = newopenings;
/* Adjust the global limit */
- xpt_max_ccbs += diff;
- splx(s);
+ dev->sim->max_ccbs += diff;
return (result);
}
@@ -5269,7 +5154,8 @@
{
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) {
@@ -5277,6 +5163,7 @@
break;
}
}
+ mtx_unlock(&xsoftc.xpt_topo_lock);
return (bus);
}
@@ -5318,6 +5205,11 @@
int counter;
} xpt_scan_bus_info;
+/*
+ * To start a scan, request_ccb is an XPT_SCAN_BUS ccb.
+ * As the scan progresses, xpt_scan_bus is used as the
+ * callback on completion function.
+ */
static void
xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
{
@@ -5329,14 +5221,19 @@
xpt_scan_bus_info *scan_info;
union ccb *work_ccb;
struct cam_path *path;
- u_int i;
- u_int max_target;
- u_int initiator_id;
+ u_int i;
+ u_int max_target;
+ u_int initiator_id;
/* Find out the characteristics of the bus */
- work_ccb = xpt_alloc_ccb();
+ work_ccb = xpt_alloc_ccb_nowait();
+ if (work_ccb == NULL) {
+ request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_done(request_ccb);
+ return;
+ }
xpt_setup_ccb(&work_ccb->ccb_h, request_ccb->ccb_h.path,
- request_ccb->ccb_h.pinfo.priority);
+ request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_PATH_INQ;
xpt_action(work_ccb);
if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
@@ -5359,7 +5256,7 @@
/* 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_CAMXPT, M_NOWAIT);
scan_info->request_ccb = request_ccb;
scan_info->cpi = &work_ccb->cpi;
@@ -5387,21 +5284,28 @@
continue;
status = xpt_create_path(&path, xpt_periph,
- request_ccb->ccb_h.path_id,
- i, 0);
+ request_ccb->ccb_h.path_id,
+ i, 0);
if (status != CAM_REQ_CMP) {
printf("xpt_scan_bus: xpt_create_path failed"
" with status %#x, bus scan halted\n",
status);
- free(scan_info, M_TEMP);
+ free(scan_info, M_CAMXPT);
request_ccb->ccb_h.status = status;
xpt_free_ccb(work_ccb);
xpt_done(request_ccb);
break;
}
- work_ccb = xpt_alloc_ccb();
+ work_ccb = xpt_alloc_ccb_nowait();
+ if (work_ccb == NULL) {
+ free(scan_info, M_CAMXPT);
+ xpt_free_path(path);
+ request_ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_done(request_ccb);
+ break;
+ }
xpt_setup_ccb(&work_ccb->ccb_h, path,
- request_ccb->ccb_h.pinfo.priority);
+ request_ccb->ccb_h.pinfo.priority);
work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
work_ccb->ccb_h.cbfcnp = xpt_scan_bus;
work_ccb->ccb_h.ppriv_ptr0 = scan_info;
@@ -5422,7 +5326,7 @@
/* Reuse the same CCB to query if a device was really found */
scan_info = (xpt_scan_bus_info *)request_ccb->ccb_h.ppriv_ptr0;
xpt_setup_ccb(&request_ccb->ccb_h, request_ccb->ccb_h.path,
- request_ccb->ccb_h.pinfo.priority);
+ request_ccb->ccb_h.pinfo.priority);
request_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
path_id = request_ccb->ccb_h.path_id;
@@ -5433,7 +5337,7 @@
if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
struct cam_ed *device;
struct cam_et *target;
- int s, phl;
+ int phl;
/*
* If we already probed lun 0 successfully, or
@@ -5450,14 +5354,12 @@
* path in the request ccb.
*/
phl = 0;
- s = splcam();
device = TAILQ_FIRST(&target->ed_entries);
if (device != NULL) {
phl = CAN_SRCH_HI_SPARSE(device);
if (device->lun_id == 0)
device = TAILQ_NEXT(device, links);
}
- splx(s);
if ((lun_id != 0) || (device != NULL)) {
if (lun_id < (CAM_SCSI2_MAXLUN-1) || phl)
lun_id++;
@@ -5509,7 +5411,7 @@
xpt_free_ccb(request_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
- free(scan_info, M_TEMP);
+ free(scan_info, M_CAMXPT);
request_ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(request_ccb);
break;
@@ -5528,7 +5430,7 @@
xpt_free_ccb(request_ccb);
xpt_free_ccb((union ccb *)scan_info->cpi);
request_ccb = scan_info->request_ccb;
- free(scan_info, M_TEMP);
+ free(scan_info, M_CAMXPT);
request_ccb->ccb_h.status = status;
xpt_done(request_ccb);
break;
@@ -5542,7 +5444,7 @@
scan_info->request_ccb->crcn.flags;
} else {
status = xpt_create_path(&path, xpt_periph,
- path_id, target_id, lun_id);
+ path_id, target_id, lun_id);
if (status != CAM_REQ_CMP) {
printf("xpt_scan_bus: xpt_create_path failed "
"with status %#x, halting LUN scan\n",
@@ -5550,7 +5452,7 @@
goto hop_again;
}
xpt_setup_ccb(&request_ccb->ccb_h, path,
- request_ccb->ccb_h.pinfo.priority);
+ request_ccb->ccb_h.pinfo.priority);
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->ccb_h.cbfcnp = xpt_scan_bus;
request_ccb->ccb_h.ppriv_ptr0 = scan_info;
@@ -5567,11 +5469,14 @@
typedef enum {
PROBE_TUR,
- PROBE_INQUIRY,
+ PROBE_INQUIRY, /* this counts as DV0 for Basic Domain Validation */
PROBE_FULL_INQUIRY,
PROBE_MODE_SENSE,
PROBE_SERIAL_NUM,
- PROBE_TUR_FOR_NEGOTIATION
+ PROBE_TUR_FOR_NEGOTIATION,
+ PROBE_INQUIRY_BASIC_DV1,
+ PROBE_INQUIRY_BASIC_DV2,
+ PROBE_DV_EXIT
} probe_action;
typedef enum {
@@ -5597,8 +5502,7 @@
cam_status status;
struct cam_path *new_path;
struct cam_periph *old_periph;
- int s;
-
+
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("xpt_scan_lun\n"));
@@ -5627,19 +5531,17 @@
}
if (request_ccb == NULL) {
- request_ccb = malloc(sizeof(union ccb), M_TEMP, M_NOWAIT);
+ request_ccb = malloc(sizeof(union ccb), M_CAMXPT, M_NOWAIT);
if (request_ccb == NULL) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't allocate CCB, can't "
- "continue\n");
+ xpt_print(path, "xpt_scan_lun: can't allocate CCB, "
+ "can't continue\n");
return;
}
- new_path = malloc(sizeof(*new_path), M_TEMP, M_NOWAIT);
+ new_path = malloc(sizeof(*new_path), M_CAMXPT, M_NOWAIT);
if (new_path == NULL) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't allocate path, can't "
- "continue\n");
- free(request_ccb, M_TEMP);
+ xpt_print(path, "xpt_scan_lun: can't allocate path, "
+ "can't continue\n");
+ free(request_ccb, M_CAMXPT);
return;
}
status = xpt_compile_path(new_path, xpt_periph,
@@ -5648,11 +5550,10 @@
path->device->lun_id);
if (status != CAM_REQ_CMP) {
- xpt_print_path(path);
- printf("xpt_scan_lun: can't compile path, can't "
- "continue\n");
- free(request_ccb, M_TEMP);
- free(new_path, M_TEMP);
+ xpt_print(path, "xpt_scan_lun: can't compile path, "
+ "can't continue\n");
+ free(request_ccb, M_CAMXPT);
+ free(new_path, M_CAMXPT);
return;
}
xpt_setup_ccb(&request_ccb->ccb_h, new_path, /*priority*/ 1);
@@ -5661,7 +5562,6 @@
request_ccb->crcn.flags = flags;
}
- s = splsoftcam();
if ((old_periph = cam_periph_find(path, "probe")) != NULL) {
probe_softc *softc;
@@ -5676,28 +5576,27 @@
request_ccb);
if (status != CAM_REQ_CMP) {
- xpt_print_path(path);
- printf("xpt_scan_lun: cam_alloc_periph returned an "
- "error, can't continue probe\n");
+ xpt_print(path, "xpt_scan_lun: cam_alloc_periph "
+ "returned an error, can't continue probe\n");
request_ccb->ccb_h.status = status;
xpt_done(request_ccb);
}
}
- splx(s);
}
static void
xptscandone(struct cam_periph *periph, union ccb *done_ccb)
{
xpt_release_path(done_ccb->ccb_h.path);
- free(done_ccb->ccb_h.path, M_TEMP);
- free(done_ccb, M_TEMP);
+ free(done_ccb->ccb_h.path, M_CAMXPT);
+ free(done_ccb, M_CAMXPT);
}
static cam_status
proberegister(struct cam_periph *periph, void *arg)
{
union ccb *request_ccb; /* CCB representing the probe request */
+ cam_status status;
probe_softc *softc;
request_ccb = (union ccb *)arg;
@@ -5712,7 +5611,7 @@
return(CAM_REQ_CMP_ERR);
}
- softc = (probe_softc *)malloc(sizeof(*softc), M_TEMP, M_NOWAIT);
+ softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT);
if (softc == NULL) {
printf("proberegister: Unable to probe new device. "
@@ -5724,7 +5623,12 @@
periph_links.tqe);
softc->flags = 0;
periph->softc = softc;
- cam_periph_acquire(periph);
+ status = cam_periph_acquire(periph);
+ if (status != CAM_REQ_CMP) {
+ return (status);
+ }
+
+
/*
* Ensure we've waited at least a bus settle
* delay before attempting to probe the device.
@@ -5802,6 +5706,7 @@
switch (softc->action) {
case PROBE_TUR:
case PROBE_TUR_FOR_NEGOTIATION:
+ case PROBE_DV_EXIT:
{
scsi_test_unit_ready(csio,
/*retries*/4,
@@ -5813,11 +5718,14 @@
}
case PROBE_INQUIRY:
case PROBE_FULL_INQUIRY:
+ case PROBE_INQUIRY_BASIC_DV1:
+ case PROBE_INQUIRY_BASIC_DV2:
{
u_int inquiry_len;
struct scsi_inquiry_data *inq_buf;
inq_buf = &periph->path->device->inq_data;
+
/*
* If the device is currently configured, we calculate an
* MD5 checksum of the inquiry data, and if the serial number
@@ -5844,9 +5752,7 @@
if (softc->action == PROBE_INQUIRY)
inquiry_len = SHORT_INQUIRY_LENGTH;
else
- inquiry_len = inq_buf->additional_length
- + offsetof(struct scsi_inquiry_data,
- additional_length) + 1;
+ inquiry_len = SID_ADDITIONAL_LENGTH(inq_buf);
/*
* Some parallel SCSI devices fail to send an
@@ -5856,6 +5762,22 @@
*/
inquiry_len = roundup2(inquiry_len, 2);
+ if (softc->action == PROBE_INQUIRY_BASIC_DV1
+ || softc->action == PROBE_INQUIRY_BASIC_DV2) {
+ inq_buf = malloc(inquiry_len, M_CAMXPT, M_NOWAIT);
+ }
+ if (inq_buf == NULL) {
+ xpt_print(periph->path, "malloc failure- skipping Basic"
+ "Domain Validation\n");
+ softc->action = PROBE_DV_EXIT;
+ scsi_test_unit_ready(csio,
+ /*retries*/4,
+ probedone,
+ MSG_SIMPLE_Q_TAG,
+ SSD_FULL_SIZE,
+ /*timeout*/60000);
+ break;
+ }
scsi_inquiry(csio,
/*retries*/4,
probedone,
@@ -5876,7 +5798,7 @@
mode_buf_len = sizeof(struct scsi_mode_header_6)
+ sizeof(struct scsi_mode_blk_desc)
+ sizeof(struct scsi_control_page);
- mode_buf = malloc(mode_buf_len, M_TEMP, M_NOWAIT);
+ mode_buf = malloc(mode_buf_len, M_CAMXPT, M_NOWAIT);
if (mode_buf != NULL) {
scsi_mode_sense(csio,
/*retries*/4,
@@ -5891,8 +5813,8 @@
/*timeout*/60000);
break;
}
- xpt_print_path(periph->path);
- printf("Unable to mode sense control page - malloc failure\n");
+ xpt_print(periph->path, "Unable to mode sense control page - "
+ "malloc failure\n");
softc->action = PROBE_SERIAL_NUM;
}
/* FALLTHROUGH */
@@ -5908,7 +5830,7 @@
if ((device->quirk->quirks & CAM_QUIRK_NOSERIAL) == 0)
serial_buf = (struct scsi_vpd_unit_serial_number *)
- malloc(sizeof(*serial_buf), M_TEMP,
+ malloc(sizeof(*serial_buf), M_CAMXPT,
M_NOWAIT | M_ZERO);
if (serial_buf != NULL) {
@@ -5943,22 +5865,121 @@
xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
-#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_USER_SETTINGS;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags = CCB_TRANS_USER_SETTINGS;
-#endif /* CAM_NEW_TRAN_CODE */
xpt_action((union ccb *)&cts);
+ if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ return;
+ }
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
-#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_CURRENT_SETTINGS;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags &= ~CCB_TRANS_USER_SETTINGS;
- cts.flags |= CCB_TRANS_CURRENT_SETTINGS;
-#endif /* CAM_NEW_TRAN_CODE */
xpt_action((union ccb *)&cts);
}
+/*
+ * Backoff Negotiation Code- only pertinent for SPI devices.
+ */
+static int
+proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
+{
+ struct ccb_trans_settings cts;
+ struct ccb_trans_settings_spi *spi;
+
+ memset(&cts, 0, sizeof (cts));
+ xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (bootverbose) {
+ xpt_print(periph->path,
+ "failed to get current device settings\n");
+ }
+ return (0);
+ }
+ if (cts.transport != XPORT_SPI) {
+ if (bootverbose) {
+ xpt_print(periph->path, "not SPI transport\n");
+ }
+ return (0);
+ }
+ spi = &cts.xport_specific.spi;
+
+ /*
+ * We cannot renegotiate sync rate if we don't have one.
+ */
+ if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
+ if (bootverbose) {
+ xpt_print(periph->path, "no sync rate known\n");
+ }
+ return (0);
+ }
+
+ /*
+ * We'll assert that we don't have to touch PPR options- the
+ * SIM will see what we do with period and offset and adjust
+ * the PPR options as appropriate.
+ */
+
+ /*
+ * A sync rate with unknown or zero offset is nonsensical.
+ * A sync period of zero means Async.
+ */
+ if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0
+ || spi->sync_offset == 0 || spi->sync_period == 0) {
+ if (bootverbose) {
+ xpt_print(periph->path, "no sync rate available\n");
+ }
+ return (0);
+ }
+
+ if (device->flags & CAM_DEV_DV_HIT_BOTTOM) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("hit async: giving up on DV\n"));
+ return (0);
+ }
+
+
+ /*
+ * Jump sync_period up by one, but stop at 5MHz and fall back to Async.
+ * We don't try to remember 'last' settings to see if the SIM actually
+ * gets into the speed we want to set. We check on the SIM telling
+ * us that a requested speed is bad, but otherwise don't try and
+ * check the speed due to the asynchronous and handshake nature
+ * of speed setting.
+ */
+ spi->valid = CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_SYNC_OFFSET;
+ for (;;) {
+ spi->sync_period++;
+ if (spi->sync_period >= 0xf) {
+ spi->sync_period = 0;
+ spi->sync_offset = 0;
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("setting to async for DV\n"));
+ /*
+ * Once we hit async, we don't want to try
+ * any more settings.
+ */
+ device->flags |= CAM_DEV_DV_HIT_BOTTOM;
+ } else if (bootverbose) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("DV: period 0x%x\n", spi->sync_period));
+ printf("setting period to 0x%x\n", spi->sync_period);
+ }
+ cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if ((cts.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ break;
+ }
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("DV: failed to set period 0x%x\n", spi->sync_period));
+ if (spi->sync_period == 0) {
+ return (0);
+ }
+ }
+ return (1);
+}
+
static void
probedone(struct cam_periph *periph, union ccb *done_ccb)
{
@@ -6031,9 +6052,7 @@
xpt_find_quirk(path->device);
-#ifdef CAM_NEW_TRAN_CODE
xpt_devise_transport(path);
-#endif /* CAM_NEW_TRAN_CODE */
if (INQ_DATA_TQ_ENABLED(inq_buf))
softc->action = PROBE_MODE_SENSE;
else
@@ -6101,7 +6120,7 @@
/*count*/1, /*run_queue*/TRUE);
}
xpt_release_ccb(done_ccb);
- free(mode_hdr, M_TEMP);
+ free(mode_hdr, M_CAMXPT);
softc->action = PROBE_SERIAL_NUM;
xpt_schedule(periph, priority);
return;
@@ -6188,7 +6207,7 @@
xpt_async(AC_LOST_DEVICE, path, NULL);
}
if (serial_buf != NULL)
- free(serial_buf, M_TEMP);
+ free(serial_buf, M_CAMXPT);
if (changed != 0) {
/*
@@ -6197,7 +6216,7 @@
* negotiations... Controllers don't perform
* any negotiation or tagged queuing until
* after the first XPT_SET_TRAN_SETTINGS ccb is
- * received. So, on a new device, just retreive
+ * received. So, on a new device, just retrieve
* the user settings, and set them as the current
* settings to set the device up.
*/
@@ -6216,25 +6235,96 @@
break;
}
case PROBE_TUR_FOR_NEGOTIATION:
+ case PROBE_DV_EXIT:
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
/* Don't wedge the queue */
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
/*run_queue*/TRUE);
}
-
- path->device->flags &= ~CAM_DEV_UNCONFIGURED;
-
+ /*
+ * Do Domain Validation for lun 0 on devices that claim
+ * to support Synchronous Transfer modes.
+ */
+ if (softc->action == PROBE_TUR_FOR_NEGOTIATION
+ && done_ccb->ccb_h.target_lun == 0
+ && (path->device->inq_data.flags & SID_Sync) != 0
+ && (path->device->flags & CAM_DEV_IN_DV) == 0) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("Begin Domain Validation\n"));
+ path->device->flags |= CAM_DEV_IN_DV;
+ xpt_release_ccb(done_ccb);
+ softc->action = PROBE_INQUIRY_BASIC_DV1;
+ xpt_schedule(periph, priority);
+ return;
+ }
+ if (softc->action == PROBE_DV_EXIT) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("Leave Domain Validation\n"));
+ }
+ path->device->flags &=
+ ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM);
if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
/* Inform the XPT that a new device has been found */
done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action(done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+ done_ccb);
+ }
+ xpt_release_ccb(done_ccb);
+ break;
+ case PROBE_INQUIRY_BASIC_DV1:
+ case PROBE_INQUIRY_BASIC_DV2:
+ {
+ struct scsi_inquiry_data *nbuf;
+ struct ccb_scsiio *csio;
+ if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ /* Don't wedge the queue */
+ xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+ /*run_queue*/TRUE);
+ }
+ csio = &done_ccb->csio;
+ nbuf = (struct scsi_inquiry_data *)csio->data_ptr;
+ if (bcmp(nbuf, &path->device->inq_data, SHORT_INQUIRY_LENGTH)) {
+ xpt_print(path,
+ "inquiry data fails comparison at DV%d step\n",
+ softc->action == PROBE_INQUIRY_BASIC_DV1? 1 : 2);
+ if (proberequestbackoff(periph, path->device)) {
+ path->device->flags &= ~CAM_DEV_IN_DV;
+ softc->action = PROBE_TUR_FOR_NEGOTIATION;
+ } else {
+ /* give up */
+ softc->action = PROBE_DV_EXIT;
+ }
+ free(nbuf, M_CAMXPT);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ free(nbuf, M_CAMXPT);
+ if (softc->action == PROBE_INQUIRY_BASIC_DV1) {
+ softc->action = PROBE_INQUIRY_BASIC_DV2;
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
+ }
+ if (softc->action == PROBE_DV_EXIT) {
+ CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
+ ("Leave Domain Validation Successfully\n"));
+ }
+ path->device->flags &=
+ ~(CAM_DEV_UNCONFIGURED|CAM_DEV_IN_DV|CAM_DEV_DV_HIT_BOTTOM);
+ if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
+ /* Inform the XPT that a new device has been found */
+ done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action(done_ccb);
xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
done_ccb);
}
xpt_release_ccb(done_ccb);
break;
}
+ }
done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe);
done_ccb->ccb_h.status = CAM_REQ_CMP;
@@ -6250,7 +6340,7 @@
static void
probecleanup(struct cam_periph *periph)
{
- free(periph->softc, M_TEMP);
+ free(periph->softc, M_CAMXPT);
}
static void
@@ -6275,7 +6365,7 @@
int error, bool;
bool = cam_srch_hi;
- error = sysctl_handle_int(oidp, &bool, sizeof(bool), req);
+ error = sysctl_handle_int(oidp, &bool, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (bool == 0 || bool == 1) {
@@ -6286,7 +6376,6 @@
}
}
-#ifdef CAM_NEW_TRAN_CODE
static void
xpt_devise_transport(struct cam_path *path)
@@ -6396,17 +6485,16 @@
cts->protocol_version = device->protocol_version;
if (cts->protocol != device->protocol) {
- xpt_print_path(cts->ccb_h.path);
- printf("Uninitialized Protocol %x:%x?\n",
+ xpt_print(cts->ccb_h.path, "Uninitialized Protocol %x:%x?\n",
cts->protocol, device->protocol);
cts->protocol = device->protocol;
}
if (cts->protocol_version > device->protocol_version) {
if (bootverbose) {
- xpt_print_path(cts->ccb_h.path);
- printf("Down reving Protocol Version from %d to %d?\n",
- cts->protocol_version, device->protocol_version);
+ xpt_print(cts->ccb_h.path, "Down reving Protocol "
+ "Version from %d to %d?\n", cts->protocol_version,
+ device->protocol_version);
}
cts->protocol_version = device->protocol_version;
}
@@ -6422,18 +6510,16 @@
cts->transport_version = device->transport_version;
if (cts->transport != device->transport) {
- xpt_print_path(cts->ccb_h.path);
- printf("Uninitialized Transport %x:%x?\n",
- cts->transport, device->transport);
+ xpt_print(cts->ccb_h.path, "Uninitialized Transport %x:%x?\n",
+ cts->transport, device->transport);
cts->transport = device->transport;
}
if (cts->transport_version > device->transport_version) {
if (bootverbose) {
- xpt_print_path(cts->ccb_h.path);
- printf("Down reving Transport Version from %d to %d?\n",
- cts->transport_version,
- device->transport_version);
+ xpt_print(cts->ccb_h.path, "Down reving Transport "
+ "Version from %d to %d?\n", cts->transport_version,
+ device->transport_version);
}
cts->transport_version = device->transport_version;
}
@@ -6478,7 +6564,9 @@
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cur_cts.type = cts->type;
xpt_action((union ccb *)&cur_cts);
-
+ if ((cur_cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ return;
+ }
cur_scsi = &cur_cts.proto_specific.scsi;
if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
@@ -6525,8 +6613,8 @@
&& (inq_data->flags & SID_Sync) == 0
&& cts->type == CTS_TYPE_CURRENT_SETTINGS)
|| ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)
- || (cur_spi->sync_offset == 0)
- || (cur_spi->sync_period == 0)) {
+ || (spi->sync_offset == 0)
+ || (spi->sync_period == 0)) {
/* Force async */
spi->sync_period = 0;
spi->sync_offset = 0;
@@ -6656,194 +6744,6 @@
(*(sim->sim_action))(sim, (union ccb *)cts);
}
-#else /* CAM_NEW_TRAN_CODE */
-
-static void
-xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
- int async_update)
-{
- struct cam_sim *sim;
- int qfrozen;
-
- sim = cts->ccb_h.path->bus->sim;
- if (async_update == FALSE) {
- struct scsi_inquiry_data *inq_data;
- struct ccb_pathinq cpi;
- struct ccb_trans_settings cur_cts;
-
- if (device == NULL) {
- cts->ccb_h.status = CAM_PATH_INVALID;
- xpt_done((union ccb *)cts);
- return;
- }
-
- /*
- * Perform sanity checking against what the
- * controller and device can do.
- */
- xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
- xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1);
- cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
- cur_cts.flags = CCB_TRANS_CURRENT_SETTINGS;
- xpt_action((union ccb *)&cur_cts);
- inq_data = &device->inq_data;
-
- /* Fill in any gaps in what the user gave us */
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0)
- cts->sync_period = cur_cts.sync_period;
- if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0)
- cts->sync_offset = cur_cts.sync_offset;
- if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) == 0)
- cts->bus_width = cur_cts.bus_width;
- if ((cts->valid & CCB_TRANS_DISC_VALID) == 0) {
- cts->flags &= ~CCB_TRANS_DISC_ENB;
- cts->flags |= cur_cts.flags & CCB_TRANS_DISC_ENB;
- }
- if ((cts->valid & CCB_TRANS_TQ_VALID) == 0) {
- cts->flags &= ~CCB_TRANS_TAG_ENB;
- cts->flags |= cur_cts.flags & CCB_TRANS_TAG_ENB;
- }
-
- if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
- && (inq_data->flags & SID_Sync) == 0)
- || ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)
- || (cts->sync_offset == 0)
- || (cts->sync_period == 0)) {
- /* Force async */
- cts->sync_period = 0;
- cts->sync_offset = 0;
- } else if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
- && (inq_data->spi3data & SID_SPI_CLOCK_DT) == 0
- && cts->sync_period <= 0x9) {
- /*
- * Don't allow DT transmission rates if the
- * device does not support it.
- */
- cts->sync_period = 0xa;
- }
-
- switch (cts->bus_width) {
- case MSG_EXT_WDTR_BUS_32_BIT:
- if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
- || (inq_data->flags & SID_WBus32) != 0)
- && (cpi.hba_inquiry & PI_WIDE_32) != 0)
- break;
- /* FALLTHROUGH to 16-bit */
- case MSG_EXT_WDTR_BUS_16_BIT:
- if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
- || (inq_data->flags & SID_WBus16) != 0)
- && (cpi.hba_inquiry & PI_WIDE_16) != 0) {
- cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
- break;
- }
- /* FALLTHROUGH to 8-bit */
- default: /* New bus width?? */
- case MSG_EXT_WDTR_BUS_8_BIT:
- /* All targets can do this */
- cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
- break;
- }
-
- if ((cts->flags & CCB_TRANS_DISC_ENB) == 0) {
- /*
- * Can't tag queue without disconnection.
- */
- cts->flags &= ~CCB_TRANS_TAG_ENB;
- cts->valid |= CCB_TRANS_TQ_VALID;
- }
-
- if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
- || (INQ_DATA_TQ_ENABLED(inq_data)) == 0
- || (device->queue_flags & SCP_QUEUE_DQUE) != 0
- || (device->quirk->mintags == 0)) {
- /*
- * Can't tag on hardware that doesn't support,
- * doesn't have it enabled, or has broken tag support.
- */
- cts->flags &= ~CCB_TRANS_TAG_ENB;
- }
- }
-
- qfrozen = FALSE;
- if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {
- int device_tagenb;
-
- /*
- * If we are transitioning from tags to no-tags or
- * vice-versa, we need to carefully freeze and restart
- * the queue so that we don't overlap tagged and non-tagged
- * commands. We also temporarily stop tags if there is
- * a change in transfer negotiation settings to allow
- * "tag-less" negotiation.
- */
- if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
- || (device->inq_flags & SID_CmdQue) != 0)
- device_tagenb = TRUE;
- else
- device_tagenb = FALSE;
-
- if (((cts->flags & CCB_TRANS_TAG_ENB) != 0
- && device_tagenb == FALSE)
- || ((cts->flags & CCB_TRANS_TAG_ENB) == 0
- && device_tagenb == TRUE)) {
-
- if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) {
- /*
- * Delay change to use tags until after a
- * few commands have gone to this device so
- * the controller has time to perform transfer
- * negotiations without tagged messages getting
- * in the way.
- */
- device->tag_delay_count = CAM_TAG_DELAY_COUNT;
- device->flags |= CAM_DEV_TAG_AFTER_COUNT;
- } else {
- xpt_freeze_devq(cts->ccb_h.path, /*count*/1);
- qfrozen = TRUE;
- device->inq_flags &= ~SID_CmdQue;
- xpt_dev_ccbq_resize(cts->ccb_h.path,
- sim->max_dev_openings);
- device->flags &= ~CAM_DEV_TAG_AFTER_COUNT;
- device->tag_delay_count = 0;
- }
- }
- }
-
- if (async_update == FALSE) {
- /*
- * If we are currently performing tagged transactions to
- * this device and want to change its negotiation parameters,
- * go non-tagged for a bit to give the controller a chance to
- * negotiate unhampered by tag messages.
- */
- if ((device->inq_flags & SID_CmdQue) != 0
- && (cts->flags & (CCB_TRANS_SYNC_RATE_VALID|
- CCB_TRANS_SYNC_OFFSET_VALID|
- CCB_TRANS_BUS_WIDTH_VALID)) != 0)
- xpt_toggle_tags(cts->ccb_h.path);
-
- (*(sim->sim_action))(sim, (union ccb *)cts);
- }
-
- if (qfrozen) {
- struct ccb_relsim crs;
-
- xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path,
- /*priority*/1);
- crs.ccb_h.func_code = XPT_REL_SIMQ;
- crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
- crs.openings
- = crs.release_timeout
- = crs.qfrozen_cnt
- = 0;
- xpt_action((union ccb *)&crs);
- }
-}
-
-
-#endif /* CAM_NEW_TRAN_CODE */
static void
xpt_toggle_tags(struct cam_path *path)
@@ -6864,24 +6764,15 @@
struct ccb_trans_settings cts;
xpt_setup_ccb(&cts.ccb_h, path, 1);
-#ifdef CAM_NEW_TRAN_CODE
cts.protocol = PROTO_SCSI;
cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
cts.transport = XPORT_UNSPECIFIED;
cts.transport_version = XPORT_VERSION_UNSPECIFIED;
cts.proto_specific.scsi.flags = 0;
cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags = 0;
- cts.valid = CCB_TRANS_TQ_VALID;
-#endif /* CAM_NEW_TRAN_CODE */
xpt_set_transfer_settings(&cts, path->device,
/*async_update*/TRUE);
-#ifdef CAM_NEW_TRAN_CODE
cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
-#else /* CAM_NEW_TRAN_CODE */
- cts.flags = CCB_TRANS_TAG_ENB;
-#endif /* CAM_NEW_TRAN_CODE */
xpt_set_transfer_settings(&cts, path->device,
/*async_update*/TRUE);
}
@@ -6922,6 +6813,9 @@
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;
@@ -6950,11 +6844,18 @@
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();
+ if (work_ccb == NULL) {
+ busses_to_config--;
+ xpt_finishconfig(xpt_periph, NULL);
+ return(0);
+ }
if ((status = xpt_create_path(&path, xpt_periph, bus->path_id,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD)) !=CAM_REQ_CMP){
@@ -7014,6 +6915,11 @@
#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) {
@@ -7069,11 +6975,40 @@
}
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_CAMXPT);
+ 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"));
@@ -7096,29 +7031,50 @@
}
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)();
+ 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);
}
-
- /*
- * 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;
}
+
if (done_ccb != NULL)
xpt_free_ccb(done_ccb);
}
+cam_status
+xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg,
+ struct cam_path *path)
+{
+ struct ccb_setasync csa;
+ cam_status status;
+ int xptpath = 0;
+
+ if (path == NULL) {
+ mtx_lock(&xsoftc.xpt_lock);
+ status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
+ if (status != CAM_REQ_CMP) {
+ mtx_unlock(&xsoftc.xpt_lock);
+ return (status);
+ }
+ xptpath = 1;
+ }
+
+ xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
+ csa.ccb_h.func_code = XPT_SASYNC_CB;
+ csa.event_enable = event;
+ csa.callback = cbfunc;
+ csa.callback_arg = cbarg;
+ xpt_action((union ccb *)&csa);
+ status = csa.ccb_h.status;
+ if (xptpath) {
+ xpt_free_path(path);
+ mtx_unlock(&xsoftc.xpt_lock);
+ }
+ return (status);
+}
+
static void
xptaction(struct cam_sim *sim, union ccb *work_ccb)
{
@@ -7145,12 +7101,10 @@
cpi->unit_number = sim->unit_number;
cpi->bus_id = sim->bus_id;
cpi->base_transfer_speed = 0;
-#ifdef CAM_NEW_TRAN_CODE
cpi->protocol = PROTO_UNSPECIFIED;
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
cpi->transport = XPORT_UNSPECIFIED;
cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
-#endif /* CAM_NEW_TRAN_CODE */
cpi->ccb_h.status = CAM_REQ_CMP;
xpt_done(work_ccb);
break;
@@ -7171,31 +7125,49 @@
{
}
+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)
+camisr(void *dummy)
{
- cam_isrq_t *oqueue = V_queue;
- cam_isrq_t queue;
- int s;
- struct ccb_hdr *ccb_h;
+ cam_simq_t queue;
+ struct cam_sim *sim;
- /*
- * Transfer the ccb_bioq list to a temporary list so we can operate
- * on it without needing to lock/unlock on every loop. The concat
- * function with re-init the real list for us.
- */
- s = splcam();
- mtx_lock(&cam_bioq_lock);
+ mtx_lock(&cam_simq_lock);
TAILQ_INIT(&queue);
- TAILQ_CONCAT(&queue, oqueue, sim_links.tqe);
- mtx_unlock(&cam_bioq_lock);
+ TAILQ_CONCAT(&queue, &cam_simq, links);
+ mtx_unlock(&cam_simq_lock);
- while ((ccb_h = TAILQ_FIRST(&queue)) != NULL) {
+ while ((sim = TAILQ_FIRST(&queue)) != NULL) {
+ TAILQ_REMOVE(&queue, sim, links);
+ CAM_SIM_LOCK(sim);
+ sim->flags &= ~CAM_SIM_ON_DONEQ;
+ camisr_runqueue(&sim->sim_doneq);
+ CAM_SIM_UNLOCK(sim);
+ }
+}
+
+static void
+camisr_runqueue(void *V_queue)
+{
+ cam_isrq_t *queue = V_queue;
+ struct ccb_hdr *ccb_h;
+
+ while ((ccb_h = TAILQ_FIRST(queue)) != NULL) {
int runq;
- TAILQ_REMOVE(&queue, ccb_h, sim_links.tqe);
+ TAILQ_REMOVE(queue, ccb_h, sim_links.tqe);
ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
- splx(s);
CAM_DEBUG(ccb_h->path, CAM_DEBUG_TRACE,
("camisr\n"));
@@ -7206,14 +7178,15 @@
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?
@@ -7221,24 +7194,25 @@
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);
}
+
if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) {
struct cam_ed *dev;
dev = ccb_h->path->device;
- s = splcam();
cam_ccbq_ccb_done(&dev->ccbq, (union ccb *)ccb_h);
if (!SIM_DEAD(ccb_h->path->bus->sim)) {
ccb_h->path->bus->sim->devq->send_active--;
ccb_h->path->bus->sim->devq->send_openings++;
}
- splx(s);
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
&& (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
@@ -7279,11 +7253,7 @@
/* Call the peripheral driver's callback */
(*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h);
-
- /* Raise IPL for while test */
- s = splcam();
}
- splx(s);
}
static void
Index: cam_sim.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_sim.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_sim.h -L sys/cam/cam_sim.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_sim.h
+++ sys/cam/cam_sim.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_sim.h,v 1.6 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam_sim.h,v 1.8 2007/04/19 14:28:43 scottl Exp $
*/
#ifndef _CAM_CAM_SIM_H
@@ -56,6 +56,7 @@
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,36 @@
sim_poll_func sim_poll;
const char *sim_name;
void *softc;
+ struct mtx *mtx;
+ TAILQ_HEAD(, ccb_hdr) sim_doneq;
+ TAILQ_ENTRY(cam_sim) links;
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
+#define CAM_SIM_ON_DONEQ 0x04
+ 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)
{
Index: cam.c
===================================================================
RCS file: /home/cvs/src/sys/cam/cam.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam.c -L sys/cam/cam.c -u -r1.1.1.1 -r1.2
--- sys/cam/cam.c
+++ sys/cam/cam.c
@@ -27,11 +27,10 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam.c,v 1.9 2005/01/05 22:34:34 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam.c,v 1.11 2007/05/23 13:27:37 cognet Exp $");
#include <sys/param.h>
#ifdef _KERNEL
-#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
@@ -373,7 +372,16 @@
{
uint32_t size_mb, secs_per_cylinder;
- size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);
+ if (ccg->block_size == 0) {
+ ccg->ccb_h.status = CAM_REQ_CMP_ERR;
+ return;
+ }
+ size_mb = (1024L * 1024L) / ccg->block_size;
+ if (size_mb == 0) {
+ ccg->ccb_h.status = CAM_REQ_CMP_ERR;
+ return;
+ }
+ size_mb = ccg->volume_size / size_mb;
if (size_mb > 1024 && extended) {
ccg->heads = 255;
ccg->secs_per_track = 63;
@@ -382,6 +390,10 @@
ccg->secs_per_track = 32;
}
secs_per_cylinder = ccg->heads * ccg->secs_per_track;
+ if (secs_per_cylinder == 0) {
+ ccg->ccb_h.status = CAM_REQ_CMP_ERR;
+ return;
+ }
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
ccg->ccb_h.status = CAM_REQ_CMP;
}
Index: cam_xpt_sim.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_xpt_sim.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_xpt_sim.h -L sys/cam/cam_xpt_sim.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_xpt_sim.h
+++ sys/cam/cam_xpt_sim.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_xpt_sim.h,v 1.8 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam_xpt_sim.h,v 1.9 2007/06/17 05:55:53 scottl Exp $
*/
#ifndef _CAM_CAM_XPT_SIM_H
@@ -37,7 +37,8 @@
/* Functions accessed by SIM drivers */
#ifdef _KERNEL
-int32_t xpt_bus_register(struct cam_sim *sim, u_int32_t bus);
+int32_t xpt_bus_register(struct cam_sim *sim, device_t parent,
+ u_int32_t bus);
int32_t xpt_bus_deregister(path_id_t path_id);
u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count);
void xpt_release_simq(struct cam_sim *sim, int run_queue);
Index: cam_ccb.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_ccb.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/cam_ccb.h -L sys/cam/cam_ccb.h -u -r1.2 -r1.3
--- sys/cam/cam_ccb.h
+++ sys/cam/cam_ccb.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_ccb.h,v 1.28.2.1 2006/06/08 17:51:27 mjacob Exp $
+ * $FreeBSD: src/sys/cam/cam_ccb.h,v 1.35 2007/04/15 08:49:09 scottl Exp $
*/
#ifndef _CAM_CAM_CCB_H
@@ -34,9 +34,7 @@
#include <sys/queue.h>
#include <sys/cdefs.h>
#include <sys/time.h>
-#ifdef CAM_NEW_TRAN_CODE
#include <sys/limits.h>
-#endif /* CAM_NEW_TRAN_CODE */
#ifndef _KERNEL
#include <sys/callout.h>
#endif
@@ -209,7 +207,6 @@
#define XPT_FC_IS_QUEUED(ccb) \
(((ccb)->ccb_h.func_code & XPT_FC_QUEUED) != 0)
-#ifdef CAM_NEW_TRAN_CODE
typedef enum {
PROTO_UNKNOWN,
PROTO_UNSPECIFIED,
@@ -226,14 +223,14 @@
XPORT_SSA, /* Serial Storage Architecture */
XPORT_USB, /* Universal Serial Bus */
XPORT_PPB, /* Parallel Port Bus */
- XPORT_ATA /* AT Attachment */
+ XPORT_ATA, /* AT Attachment */
+ XPORT_SAS, /* Serial Attached SCSI */
} cam_xport;
-#define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
-#define PROTO_VERSION_UNSPECIFIED UINT_MAX
-#define XPORT_VERSION_UNKNOWN (UINT_MAX - 1)
-#define XPORT_VERSION_UNSPECIFIED UINT_MAX
-#endif /* CAM_NEW_TRAN_CODE */
+#define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
+#define PROTO_VERSION_UNSPECIFIED UINT_MAX
+#define XPORT_VERSION_UNKNOWN (UINT_MAX - 1)
+#define XPORT_VERSION_UNSPECIFIED UINT_MAX
typedef union {
LIST_ENTRY(ccb_hdr) le;
@@ -245,8 +242,7 @@
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 {
@@ -277,8 +273,12 @@
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 */
@@ -517,7 +517,6 @@
PIM_SEQSCAN = 0x04 /* Do bus scans sequentially, not in parallel */
} pi_miscflag;
-#ifdef CAM_NEW_TRAN_CODE
/* Path Inquiry CCB */
struct ccb_pathinq_settings_spi {
u_int8_t ppr_options;
@@ -528,8 +527,10 @@
u_int32_t port; /* 24 bit port id, if known */
u_int32_t bitrate; /* Mbps */
};
+struct ccb_pathinq_settings_sas {
+ u_int32_t bitrate; /* Mbps */
+};
#define PATHINQ_SETTINGS_SIZE 128
-#endif /* CAM_NEW_TRAN_CODE */
struct ccb_pathinq {
struct ccb_hdr ccb_h;
@@ -551,7 +552,6 @@
u_int32_t unit_number; /* Unit number for SIM */
u_int32_t bus_id; /* Bus ID for SIM */
u_int32_t base_transfer_speed;/* Base bus speed in KB/sec */
-#ifdef CAM_NEW_TRAN_CODE
cam_proto protocol;
u_int protocol_version;
cam_xport transport;
@@ -559,9 +559,9 @@
union {
struct ccb_pathinq_settings_spi spi;
struct ccb_pathinq_settings_fc fc;
+ struct ccb_pathinq_settings_sas sas;
char ccb_pathinq_settings_opaque[PATHINQ_SETTINGS_SIZE];
} xport_specific;
-#endif /* CAM_NEW_TRAN_CODE */
};
/* Path Statistics CCB */
@@ -699,27 +699,6 @@
union ccb *termio_ccb; /* Pointer to CCB to terminate */
};
-#ifndef CAM_NEW_TRAN_CODE
-/* Get/Set transfer rate/width/disconnection/tag queueing settings */
-struct ccb_trans_settings {
- struct ccb_hdr ccb_h;
- u_int valid; /* Which fields to honor */
-#define CCB_TRANS_SYNC_RATE_VALID 0x01
-#define CCB_TRANS_SYNC_OFFSET_VALID 0x02
-#define CCB_TRANS_BUS_WIDTH_VALID 0x04
-#define CCB_TRANS_DISC_VALID 0x08
-#define CCB_TRANS_TQ_VALID 0x10
- u_int flags;
-#define CCB_TRANS_CURRENT_SETTINGS 0x01
-#define CCB_TRANS_USER_SETTINGS 0x02
-#define CCB_TRANS_DISC_ENB 0x04
-#define CCB_TRANS_TAG_ENB 0x08
- u_int sync_period;
- u_int sync_offset;
- u_int bus_width;
-};
-
-#else /* CAM_NEW_TRAN_CODE */
typedef enum {
CTS_TYPE_CURRENT_SETTINGS,
CTS_TYPE_USER_SETTINGS
@@ -743,7 +722,6 @@
#define CTS_SPI_VALID_PPR_OPTIONS 0x10
u_int flags;
#define CTS_SPI_FLAGS_DISC_ENB 0x01
-#define CTS_SPI_FLAGS_TAG_ENB 0x02
u_int sync_period;
u_int sync_offset;
u_int bus_width;
@@ -762,6 +740,13 @@
u_int32_t bitrate; /* Mbps */
};
+struct ccb_trans_settings_sas {
+ u_int valid; /* Which fields to honor */
+#define CTS_SAS_VALID_SPEED 0x1000
+ u_int32_t bitrate; /* Mbps */
+};
+
+
/* Get/Set transfer rate/width/disconnection/tag queueing settings */
struct ccb_trans_settings {
struct ccb_hdr ccb_h;
@@ -778,10 +763,10 @@
u_int valid; /* Which fields to honor */
struct ccb_trans_settings_spi spi;
struct ccb_trans_settings_fc fc;
+ struct ccb_trans_settings_sas sas;
} xport_specific;
};
-#endif /* CAM_NEW_TRAN_CODE */
/*
* Calculate the geometry parameters for a device
Index: cam_periph.c
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_periph.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/cam_periph.c -L sys/cam/cam_periph.c -u -r1.2 -r1.3
--- sys/cam/cam_periph.c
+++ sys/cam/cam_periph.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_periph.c,v 1.60.2.1 2006/02/26 22:38:39 iedowse Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_periph.c,v 1.69 2007/05/14 21:48:52 scottl Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,6 +51,7 @@
#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>
@@ -86,6 +87,14 @@
MALLOC_DEFINE(M_CAMPERIPH, "CAM periph", "CAM peripheral buffers");
+static int periph_selto_delay = 1000;
+TUNABLE_INT("kern.cam.periph_selto_delay", &periph_selto_delay);
+static int periph_noresrc_delay = 500;
+TUNABLE_INT("kern.cam.periph_noresrc_delay", &periph_noresrc_delay);
+static int periph_busy_delay = 500;
+TUNABLE_INT("kern.cam.periph_busy_delay", &periph_busy_delay);
+
+
void
periphdriver_register(void *data)
{
@@ -93,7 +102,8 @@
int ndrivers;
ndrivers = nperiph_drivers + 2;
- newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_TEMP, M_WAITOK);
+ newdrivers = malloc(sizeof(*newdrivers) * ndrivers, M_CAMPERIPH,
+ M_WAITOK);
if (periph_drivers)
bcopy(periph_drivers, newdrivers,
sizeof(*newdrivers) * nperiph_drivers);
@@ -102,7 +112,7 @@
old = periph_drivers;
periph_drivers = newdrivers;
if (old)
- free(old, M_TEMP);
+ free(old, M_CAMPERIPH);
nperiph_drivers++;
}
@@ -114,6 +124,7 @@
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;
@@ -121,7 +132,6 @@
lun_id_t lun_id;
cam_status status;
u_int init_level;
- int s;
init_level = 0;
/*
@@ -155,11 +165,14 @@
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);
@@ -173,6 +186,7 @@
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)
@@ -186,7 +200,6 @@
if (status != CAM_REQ_CMP)
goto failure;
- s = splsoftcam();
cur_periph = TAILQ_FIRST(&(*p_drv)->units);
while (cur_periph != NULL
&& cur_periph->unit_number < periph->unit_number)
@@ -199,8 +212,6 @@
(*p_drv)->generation++;
}
- splx(s);
-
init_level++;
status = periph_ctor(periph, arg);
@@ -214,9 +225,7 @@
/* Initialized successfully */
break;
case 3:
- s = splsoftcam();
TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
- splx(s);
xpt_remove_periph(periph);
/* FALLTHROUGH */
case 2:
@@ -244,38 +253,38 @@
{
struct periph_driver **p_drv;
struct cam_periph *periph;
- int s;
+ xpt_lock_buses();
for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
if (name != NULL && (strcmp((*p_drv)->driver_name, name) != 0))
continue;
- s = splsoftcam();
TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) {
if (xpt_path_comp(periph->path, path) == 0) {
- splx(s);
+ xpt_unlock_buses();
return(periph);
}
}
- splx(s);
- if (name != NULL)
+ if (name != NULL) {
+ xpt_unlock_buses();
return(NULL);
+ }
}
+ xpt_unlock_buses();
return(NULL);
}
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);
}
@@ -283,20 +292,68 @@
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
@@ -311,11 +368,9 @@
{
struct cam_periph *periph;
char *periph_name;
- int s;
int i, val, dunit, r;
const char *dname, *strval;
- s = splsoftcam();
periph_name = p_drv->driver_name;
for (;;newunit++) {
@@ -326,12 +381,12 @@
if (periph != NULL && periph->unit_number == newunit) {
if (wired != 0) {
- xpt_print_path(periph->path);
- printf("Duplicate Wired Device entry!\n");
- xpt_print_path(periph->path);
- printf("Second device (%s device at scbus%d "
- "target %d lun %d) will not be wired\n",
- periph_name, pathid, target, lun);
+ xpt_print(periph->path, "Duplicate Wired "
+ "Device entry!\n");
+ xpt_print(periph->path, "Second device (%s "
+ "device at scbus%d target %d lun %d) will "
+ "not be wired\n", periph_name, pathid,
+ target, lun);
wired = 0;
}
continue;
@@ -361,7 +416,6 @@
if (r != 0)
break;
}
- splx(s);
return (newunit);
}
@@ -416,13 +470,10 @@
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
- * splsoftcam().
+ * invalidated.
*/
if (((periph->flags & CAM_PERIPH_INVALID) == 0)
&& (periph->periph_oninval != NULL))
@@ -431,17 +482,17 @@
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
camperiphfree(struct cam_periph *periph)
{
- int s;
struct periph_driver **p_drv;
for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
@@ -452,15 +503,13 @@
printf("camperiphfree: attempt to free non-existant periph\n");
return;
}
-
- if (periph->periph_dtor != NULL)
- periph->periph_dtor(periph);
-
- s = splsoftcam();
+
TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
(*p_drv)->generation++;
- splx(s);
+ xpt_unlock_buses();
+ if (periph->periph_dtor != NULL)
+ periph->periph_dtor(periph);
xpt_remove_periph(periph);
if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) {
@@ -489,50 +538,7 @@
}
xpt_free_path(periph->path);
free(periph, M_CAMPERIPH);
-}
-
-/*
- * Wait interruptibly for an exclusive lock.
- */
-int
-cam_periph_lock(struct cam_periph *periph, int priority)
-{
- 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;
-}
-
-/*
- * Unlock and wake up any waiters.
- */
-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);
+ xpt_lock_buses();
}
/*
@@ -673,6 +679,16 @@
mapinfo->num_bufs_used++;
}
+ /*
+ * Now that we've gotten this far, change ownership to the kernel
+ * of the buffers so that we don't run afoul of returning to user
+ * space with locks (on the buffer) held.
+ */
+ for (i = 0; i < numbufs; i++) {
+ BUF_KERNPROC(mapinfo->bp[i]);
+ }
+
+
return(0);
}
@@ -734,12 +750,11 @@
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;
@@ -747,26 +762,33 @@
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)
{
- int s;
+ struct mtx *mtx;
+ struct cam_sim *sim;
- 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);
-
- splx(s);
+ msleep(&ccb->ccb_h.cbfcnp, mtx, PRIBIO, "cbwait", 0);
}
int
@@ -839,10 +861,13 @@
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.
@@ -977,8 +1002,8 @@
saved_ccb->ccb_h.status |=
CAM_AUTOSNS_VALID;
#if 0
- xpt_print_path(saved_ccb->ccb_h.path);
- printf("Recovered Sense\n");
+ xpt_print(saved_ccb->ccb_h.path,
+ "Recovered Sense\n");
scsi_sense_print(&saved_ccb->csio);
cam_error_print(saved_ccb, CAM_ESF_ALL,
CAM_EPF_ALL);
@@ -1168,11 +1193,8 @@
{
struct timeval delta;
struct timeval duration_tv;
- int s;
- s = splclock();
microtime(&delta);
- splx(s);
timevalsub(&delta, event_time);
duration_tv.tv_sec = duration_ms / 1000;
duration_tv.tv_usec = (duration_ms % 1000) * 1000;
@@ -1269,8 +1291,7 @@
*timeout = 0;
error = ERESTART;
if (bootverbose) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Queue Full\n");
+ xpt_print(ccb->ccb_h.path, "Queue Full\n");
}
break;
}
@@ -1282,8 +1303,7 @@
* command completes or a 1 second timeout.
*/
if (bootverbose) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Device Busy\n");
+ xpt_print(ccb->ccb_h.path, "Device Busy\n");
}
if (ccb->ccb_h.retry_count > 0) {
ccb->ccb_h.retry_count--;
@@ -1296,13 +1316,12 @@
}
break;
case SCSI_STATUS_RESERV_CONFLICT:
- xpt_print_path(ccb->ccb_h.path);
- printf("Reservation Conflict\n");
+ xpt_print(ccb->ccb_h.path, "Reservation Conflict\n");
error = EIO;
break;
default:
- xpt_print_path(ccb->ccb_h.path);
- printf("SCSI Status 0x%x\n", ccb->csio.scsi_status);
+ xpt_print(ccb->ccb_h.path, "SCSI Status 0x%x\n",
+ ccb->csio.scsi_status);
error = EIO;
break;
}
@@ -1534,7 +1553,7 @@
int error, printed = 0;
int openings;
u_int32_t relsim_flags;
- u_int32_t timeout;
+ u_int32_t timeout = 0;
action_string = NULL;
status = ccb->ccb_h.status;
@@ -1556,42 +1575,38 @@
&timeout);
break;
case CAM_AUTOSENSE_FAIL:
- xpt_print_path(ccb->ccb_h.path);
- printf("AutoSense Failed\n");
+ xpt_print(ccb->ccb_h.path, "AutoSense Failed\n");
error = EIO; /* we have to kill the command */
break;
case CAM_REQ_CMP_ERR:
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Request completed with CAM_REQ_CMP_ERR\n");
+ xpt_print(ccb->ccb_h.path,
+ "Request completed with CAM_REQ_CMP_ERR\n");
printed++;
}
/* FALLTHROUGH */
case CAM_CMD_TIMEOUT:
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Command timed out\n");
+ xpt_print(ccb->ccb_h.path, "Command timed out\n");
printed++;
}
/* FALLTHROUGH */
case CAM_UNEXP_BUSFREE:
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Unexpected Bus Free\n");
+ xpt_print(ccb->ccb_h.path, "Unexpected Bus Free\n");
printed++;
}
/* FALLTHROUGH */
case CAM_UNCOR_PARITY:
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Uncorrected Parity Error\n");
+ xpt_print(ccb->ccb_h.path,
+ "Uncorrected Parity Error\n");
printed++;
}
/* FALLTHROUGH */
case CAM_DATA_RUN_ERR:
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Data Overrun\n");
+ xpt_print(ccb->ccb_h.path, "Data Overrun\n");
printed++;
}
error = EIO; /* we have to kill the command */
@@ -1620,17 +1635,17 @@
ccb->ccb_h.retry_count--;
error = ERESTART;
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Selection Timeout\n");
+ xpt_print(ccb->ccb_h.path,
+ "Selection Timeout\n");
printed++;
}
/*
- * Wait a second to give the device
+ * Wait a bit to give the device
* time to recover before we try again.
*/
relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
- timeout = 1000;
+ timeout = periph_selto_delay;
break;
}
}
@@ -1683,22 +1698,29 @@
/* Unconditional requeue */
error = ERESTART;
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("Request Requeued\n");
+ xpt_print(ccb->ccb_h.path, "Request Requeued\n");
printed++;
}
break;
case CAM_RESRC_UNAVAIL:
+ /* Wait a bit for the resource shortage to abate. */
+ timeout = periph_noresrc_delay;
+ /* FALLTHROUGH */
case CAM_BUSY:
- /* timeout??? */
+ if (timeout == 0) {
+ /* Wait a bit for the busy condition to abate. */
+ timeout = periph_busy_delay;
+ }
+ relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT;
+ /* FALLTHROUGH */
default:
/* decrement the number of retries */
if (ccb->ccb_h.retry_count > 0) {
ccb->ccb_h.retry_count--;
error = ERESTART;
if (bootverbose && printed == 0) {
- xpt_print_path(ccb->ccb_h.path);
- printf("CAM Status 0x%x\n", status);
+ xpt_print(ccb->ccb_h.path, "CAM Status 0x%x\n",
+ status);
printed++;
}
} else {
@@ -1737,11 +1759,9 @@
if (action_string == NULL)
action_string = "Unretryable Error";
if (error != ERESTART) {
- xpt_print_path(ccb->ccb_h.path);
- printf("error %d\n", error);
+ xpt_print(ccb->ccb_h.path, "error %d\n", error);
}
- xpt_print_path(ccb->ccb_h.path);
- printf("%s\n", action_string);
+ xpt_print(ccb->ccb_h.path, "%s\n", action_string);
}
return (error);
Index: cam_xpt.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_xpt.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_xpt.h -L sys/cam/cam_xpt.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_xpt.h
+++ sys/cam/cam_xpt.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_xpt.h,v 1.5 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam_xpt.h,v 1.9 2007/05/16 16:54:23 scottl Exp $
*/
#ifndef _CAM_CAM_XPT_H
@@ -58,10 +58,15 @@
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);
void xpt_print_path(struct cam_path *path);
+void xpt_print(struct cam_path *path, const char *fmt, ...);
int xpt_path_string(struct cam_path *path, char *str,
size_t str_len);
path_id_t xpt_path_path_id(struct cam_path *path);
@@ -71,6 +76,11 @@
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);
+cam_status xpt_register_async(int event, ac_callback_t *cbfunc,
+ void *cbarg, struct cam_path *path);
#endif /* _KERNEL */
#endif /* _CAM_CAM_XPT_H */
Index: cam_xpt_periph.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_xpt_periph.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_xpt_periph.h -L sys/cam/cam_xpt_periph.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_xpt_periph.h
+++ sys/cam/cam_xpt_periph.h
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_xpt_periph.h,v 1.5 2005/07/01 15:21:29 avatar Exp $
+ * $FreeBSD: src/sys/cam/cam_xpt_periph.h,v 1.7 2007/04/18 04:58:52 scottl Exp $
*/
#ifndef _CAM_CAM_XPT_PERIPH_H
Index: cam_debug.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_debug.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_debug.h -L sys/cam/cam_debug.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_debug.h
+++ sys/cam/cam_debug.h
@@ -25,15 +25,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_debug.h,v 1.8 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam_debug.h,v 1.9 2006/05/16 14:37:57 phk Exp $
*/
#ifndef _CAM_CAM_DEBUG_H
#define _CAM_CAM_DEBUG_H 1
-#if defined(CAMDEBUG) && defined(_KERNEL)
-#include <machine/clock.h>
-#endif /* CAMDEBUG && _KERNEL */
-
/*
* Debugging flags.
*/
Index: cam_periph.h
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_periph.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_periph.h -L sys/cam/cam_periph.h -u -r1.1.1.1 -r1.2
--- sys/cam/cam_periph.h
+++ sys/cam/cam_periph.h
@@ -25,13 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/cam/cam_periph.h,v 1.16 2005/01/05 22:34:34 imp Exp $
+ * $FreeBSD: src/sys/cam/cam_periph.h,v 1.18 2007/04/19 22:46:26 scottl Exp $
*/
#ifndef _CAM_CAM_PERIPH_H
#define _CAM_CAM_PERIPH_H 1
#include <sys/queue.h>
+#include <cam/cam_sim.h>
#ifdef _KERNEL
@@ -104,6 +105,7 @@
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 +115,7 @@
#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 +139,10 @@
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_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);
@@ -173,5 +176,17 @@
int cam_periph_error(union ccb *ccb, cam_flags camflags,
u_int32_t sense_flags, union ccb *save_ccb);
+static __inline void
+cam_periph_lock(struct cam_periph *periph)
+{
+ mtx_lock(periph->sim->mtx);
+}
+
+static __inline void
+cam_periph_unlock(struct cam_periph *periph)
+{
+ mtx_unlock(periph->sim->mtx);
+}
+
#endif /* _KERNEL */
#endif /* _CAM_CAM_PERIPH_H */
Index: cam_sim.c
===================================================================
RCS file: /home/cvs/src/sys/cam/cam_sim.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/cam_sim.c -L sys/cam/cam_sim.c -u -r1.1.1.1 -r1.2
--- sys/cam/cam_sim.c
+++ sys/cam/cam_sim.c
@@ -27,12 +27,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/cam_sim.c,v 1.9 2005/07/01 15:21:29 avatar Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/cam_sim.c,v 1.11 2007/04/19 14:28:43 scottl Exp $");
#include <sys/param.h>
#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,43 @@
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);
+ TAILQ_INIT(&sim->sim_doneq);
+
return (sim);
}
Index: scsi_pass.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_pass.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_pass.c -L sys/cam/scsi/scsi_pass.c -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_pass.c
+++ sys/cam/scsi/scsi_pass.c
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_pass.c,v 1.43.2.1 2006/08/17 19:55:35 jhb Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_pass.c,v 1.48 2007/05/16 16:54:23 scottl Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,6 +46,7 @@
#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 @@
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,
@@ -117,27 +118,12 @@
passinit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = passasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, passasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("pass: Failed to attach master async callback "
@@ -150,20 +136,13 @@
passoninvalidate(struct cam_periph *periph)
{
struct pass_softc *softc;
- struct ccb_setasync csa;
softc = (struct pass_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = passasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, passasync, periph, periph->path);
softc->flags |= PASS_FLAG_INVALID;
@@ -174,8 +153,7 @@
*/
if (bootverbose) {
- xpt_print_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
}
@@ -192,8 +170,7 @@
destroy_dev(softc->dev);
if (bootverbose) {
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
}
free(softc, M_DEVBUF);
}
@@ -203,6 +180,7 @@
struct cam_path *path, void *arg)
{
struct cam_periph *periph;
+ struct cam_sim *sim;
periph = (struct cam_periph *)callback_arg;
@@ -221,6 +199,7 @@
* 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,
@@ -249,7 +228,6 @@
passregister(struct cam_periph *periph, void *arg)
{
struct pass_softc *softc;
- struct ccb_setasync csa;
struct ccb_getdev *cgd;
int no_tags;
@@ -284,6 +262,7 @@
* know what the blocksize of this device is, if
* it even has a blocksize.
*/
+ mtx_unlock(periph->sim->mtx);
no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
softc->device_stats = devstat_new_entry("pass",
unit2minor(periph->unit_number), 0,
@@ -298,18 +277,14 @@
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;
/*
* Add an async callback so that we get
* notified if this device goes away.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = passasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_LOST_DEVICE, passasync, periph, periph->path);
if (bootverbose)
xpt_announce_periph(periph, NULL);
@@ -323,19 +298,20 @@
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);
}
@@ -344,7 +320,8 @@
*/
error = securelevel_gt(td->td_ucred, 1);
if (error) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(error);
}
@@ -352,7 +329,8 @@
* Only allow read-write access.
*/
if (((flags & FWRITE) == 0) || ((flags & FREAD) == 0)) {
- splx(s);
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(EPERM);
}
@@ -360,23 +338,17 @@
* We don't allow nonblocking access.
*/
if ((flags & O_NONBLOCK) != 0) {
- xpt_print_path(periph->path);
- printf("can't do nonblocking access\n");
- splx(s);
+ xpt_print(periph->path, "can't do nonblocking access\n");
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
return(EINVAL);
}
- if ((error = cam_periph_lock(periph, 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);
@@ -389,17 +361,14 @@
{
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);
@@ -412,18 +381,15 @@
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;
}
@@ -457,6 +423,7 @@
if (periph == NULL)
return(ENXIO);
+ cam_periph_lock(periph);
softc = (struct pass_softc *)periph->softc;
error = 0;
@@ -476,9 +443,9 @@
* through the transport layer device.
*/
if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
- xpt_print_path(periph->path);
- printf("CCB function code %#x is restricted to the "
- "XPT device\n", inccb->ccb_h.func_code);
+ xpt_print(periph->path, "CCB function code %#x is "
+ "restricted to the XPT device\n",
+ inccb->ccb_h.func_code);
error = ENODEV;
break;
}
@@ -495,7 +462,7 @@
inccb->ccb_h.pinfo.priority);
ccb_malloced = 0;
} else {
- ccb = xpt_alloc_ccb();
+ ccb = xpt_alloc_ccb_nowait();
if (ccb != NULL)
xpt_setup_ccb(&ccb->ccb_h, periph->path,
@@ -504,8 +471,7 @@
}
if (ccb == NULL) {
- xpt_print_path(periph->path);
- printf("unable to allocate CCB\n");
+ xpt_print(periph->path, "unable to allocate CCB\n");
error = ENOMEM;
break;
}
@@ -524,6 +490,7 @@
break;
}
+ cam_periph_unlock(periph);
return(error);
}
@@ -572,7 +539,14 @@
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.
Index: scsi_pt.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_pt.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_pt.c -L sys/cam/scsi/scsi_pt.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_pt.c
+++ sys/cam/scsi/scsi_pt.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_pt.c,v 1.43 2005/01/05 22:34:34 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_pt.c,v 1.47 2007/05/16 16:54:23 scottl Exp $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -119,7 +119,7 @@
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 @@
{
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 @@
{
struct cam_periph *periph;
struct pt_softc *softc;
- int error;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
@@ -190,8 +179,7 @@
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 @@
{
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 @@
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 @@
*/
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;
}
@@ -254,27 +234,12 @@
ptinit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = ptasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, ptasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("pt: Failed to attach master async callback "
@@ -286,7 +251,6 @@
ptctor(struct cam_periph *periph, void *arg)
{
struct pt_softc *softc;
- struct ccb_setasync csa;
struct ccb_getdev *cgd;
cgd = (struct ccb_getdev *)arg;
@@ -317,6 +281,7 @@
periph->softc = softc;
+ cam_periph_unlock(periph);
softc->device_stats = devstat_new_entry("pt",
periph->unit_number, 0,
DEVSTAT_NO_BLOCKSIZE,
@@ -326,6 +291,7 @@
softc->dev = make_dev(&pt_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;
/*
@@ -336,12 +302,8 @@
* them and the only alternative would be to
* not attach the device on failure.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
- csa.callback = ptasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
+ ptasync, periph, periph->path);
/* Tell the user we've attached to the device */
xpt_announce_periph(periph, NULL);
@@ -352,43 +314,25 @@
static void
ptoninvalidate(struct cam_periph *periph)
{
- int s;
struct pt_softc *softc;
- struct ccb_setasync csa;
softc = (struct pt_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = ptasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, ptasync, periph, periph->path);
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_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
static void
@@ -402,8 +346,7 @@
destroy_dev(softc->dev);
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
free(softc, M_DEVBUF);
}
@@ -447,10 +390,8 @@
{
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.
@@ -458,7 +399,6 @@
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:
@@ -472,14 +412,12 @@
{
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,
@@ -488,14 +426,10 @@
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);
@@ -517,14 +451,11 @@
* 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);
@@ -548,12 +479,10 @@
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)
@@ -570,15 +499,13 @@
return;
}
if (error != 0) {
- s = splbio();
-
if (error == ENXIO) {
/*
* Catastrophic error. Mark our device
* as invalid.
*/
- xpt_print_path(periph->path);
- printf("Invalidating device\n");
+ xpt_print(periph->path,
+ "Invalidating device\n");
softc->flags |= PT_FLAG_DEVICE_INVALID;
}
@@ -588,7 +515,6 @@
* 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;
@@ -616,9 +542,7 @@
* 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;
@@ -649,7 +573,7 @@
{
struct cam_periph *periph;
struct pt_softc *softc;
- int error;
+ int error = 0;
periph = (struct cam_periph *)dev->si_drv1;
if (periph == NULL)
@@ -657,9 +581,7 @@
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:
@@ -669,20 +591,14 @@
*(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;
Index: scsi_ch.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_ch.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_ch.c -L sys/cam/scsi/scsi_ch.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_ch.c
+++ sys/cam/scsi/scsi_ch.c
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_ch.c,v 1.42 2005/03/26 04:21:11 ken Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_ch.c,v 1.46 2007/05/16 16:54:23 scottl Exp $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -173,8 +173,6 @@
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,38 +211,25 @@
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,
.d_name = "ch",
};
+MALLOC_DEFINE(M_SCSICH, "scsi_ch", "scsi_ch buffers");
+
static void
chinit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = chasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, chasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("ch: Failed to attach master async callback "
@@ -256,25 +241,17 @@
choninvalidate(struct cam_periph *periph)
{
struct ch_softc *softc;
- struct ccb_setasync csa;
softc = (struct ch_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = chasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, chasync, periph, periph->path);
softc->flags |= CH_FLAG_INVALID;
- xpt_print_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
@@ -287,8 +264,7 @@
devstat_remove_entry(softc->device_stats);
destroy_dev(softc->dev);
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
free(softc, M_DEVBUF);
}
@@ -340,7 +316,6 @@
chregister(struct cam_periph *periph, void *arg)
{
struct ch_softc *softc;
- struct ccb_setasync csa;
struct ccb_getdev *cgd;
cgd = (struct ccb_getdev *)arg;
@@ -371,6 +346,7 @@
* Changers don't have a blocksize, and obviously don't support
* tagged queueing.
*/
+ cam_periph_unlock(periph);
softc->device_stats = devstat_new_entry("ch",
periph->unit_number, 0,
DEVSTAT_NO_BLOCKSIZE | DEVSTAT_NO_ORDERED_TAGS,
@@ -381,24 +357,20 @@
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;
/*
* Add an async callback so that we get
* notified if this device goes away.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = chasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_LOST_DEVICE, chasync, periph, periph->path);
/*
- * 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);
@@ -410,31 +382,30 @@
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);
}
/*
@@ -447,6 +418,7 @@
return(error);
}
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return(error);
@@ -467,8 +439,7 @@
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;
@@ -482,24 +453,20 @@
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:
@@ -515,7 +482,7 @@
sizeof(struct scsi_mode_blk_desc) +
sizeof(struct page_element_address_assignment);
- mode_buffer = malloc(mode_buffer_len, M_TEMP, M_NOWAIT);
+ mode_buffer = malloc(mode_buffer_len, M_SCSICH, M_NOWAIT);
if (mode_buffer == NULL) {
printf("chstart: couldn't malloc mode sense data\n");
@@ -647,13 +614,12 @@
== CAM_SCSI_STATUS_ERROR)
scsi_sense_print(&done_ccb->csio);
else {
- xpt_print_path(periph->path);
- printf("got CAM status %#x\n",
- done_ccb->ccb_h.status);
+ xpt_print(periph->path,
+ "got CAM status %#x\n",
+ done_ccb->ccb_h.status);
}
- xpt_print_path(periph->path);
- printf("fatal error, failed to attach to"
- " device\n");
+ xpt_print(periph->path, "fatal error, failed "
+ "to attach to device\n");
cam_periph_invalidate(periph);
@@ -663,7 +629,7 @@
if (announce_buf[0] != '\0')
xpt_announce_periph(periph, announce_buf);
softc->state = CH_STATE_NORMAL;
- free(mode_header, M_TEMP);
+ free(mode_header, M_SCSICH);
/*
* Since our peripheral may be invalidated by an error
* above or an external event, we must release our CCB
@@ -673,7 +639,7 @@
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case CH_CCB_WAITING:
@@ -712,6 +678,7 @@
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;
@@ -732,8 +699,10 @@
break;
default:
- if ((flag & FWRITE) == 0)
+ if ((flag & FWRITE) == 0) {
+ cam_periph_unlock(periph);
return (EBADF);
+ }
}
switch (cmd) {
@@ -757,8 +726,10 @@
{
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;
}
@@ -797,6 +768,7 @@
break;
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -1094,8 +1066,10 @@
* 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,
@@ -1116,6 +1090,7 @@
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 +
@@ -1133,6 +1108,7 @@
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,
@@ -1152,6 +1128,7 @@
if (error)
goto done;
+ cam_periph_unlock(periph);
/*
* Fill in the user status array.
@@ -1162,8 +1139,8 @@
avail = scsi_2btoul(st_hdr->count);
if (avail != cesr->cesr_element_count) {
- xpt_print_path(periph->path);
- printf("warning, READ ELEMENT STATUS avail != count\n");
+ xpt_print(periph->path,
+ "warning, READ ELEMENT STATUS avail != count\n");
}
user_data = (struct changer_element_status *)
@@ -1189,6 +1166,7 @@
error = copyout(user_data,
cesr->cesr_element_status,
avail * sizeof(struct changer_element_status));
+ cam_periph_lock(periph);
done:
xpt_release_ccb(ccb);
@@ -1349,7 +1327,7 @@
*/
mode_buffer_len = sizeof(struct scsi_mode_sense_data);
- mode_buffer = malloc(mode_buffer_len, M_TEMP, M_NOWAIT);
+ mode_buffer = malloc(mode_buffer_len, M_SCSICH, M_NOWAIT);
if (mode_buffer == NULL) {
printf("chgetparams: couldn't malloc mode sense data\n");
@@ -1403,11 +1381,11 @@
}
if (error) {
- xpt_print_path(periph->path);
- printf("chgetparams: error getting element "
- "address page\n");
+ xpt_print(periph->path,
+ "chgetparams: error getting element "
+ "address page\n");
xpt_release_ccb(ccb);
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSICH);
return(error);
}
}
@@ -1466,11 +1444,11 @@
}
if (error) {
- xpt_print_path(periph->path);
- printf("chgetparams: error getting device "
- "capabilities page\n");
+ xpt_print(periph->path,
+ "chgetparams: error getting device "
+ "capabilities page\n");
xpt_release_ccb(ccb);
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSICH);
return(error);
}
}
@@ -1489,7 +1467,7 @@
softc->sc_exchangemask[from] = exchanges[from];
}
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSICH);
return(error);
}
Index: scsi_all.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_all.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_all.c -L sys/cam/scsi/scsi_all.c -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_all.c
+++ sys/cam/scsi/scsi_all.c
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.48.2.1 2006/09/09 07:21:18 ken Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.51 2007/06/04 18:25:03 dwmalone Exp $");
#include <sys/param.h>
@@ -727,8 +727,6 @@
#endif
-#include <sys/param.h>
-
#if !defined(SCSI_NO_SENSE_STRINGS)
#define SST(asc, ascq, action, desc) \
asc, ascq, action, desc
@@ -3025,7 +3023,7 @@
int error, delay;
delay = scsi_delay;
- error = sysctl_handle_int(oidp, &delay, sizeof(delay), req);
+ error = sysctl_handle_int(oidp, &delay, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
return (set_scsi_delay(delay));
Index: scsi_ses.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_ses.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_ses.c -L sys/cam/scsi/scsi_ses.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_ses.c
+++ sys/cam/scsi/scsi_ses.c
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_ses.c,v 1.32 2005/07/01 15:21:30 avatar Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_ses.c,v 1.35 2007/05/16 16:54:23 scottl Exp $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -43,6 +43,7 @@
#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,34 +183,19 @@
.d_close = sesclose,
.d_ioctl = sesioctl,
.d_name = "ses",
- .d_flags = D_NEEDGIANT,
+ .d_flags = 0,
};
static void
sesinit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback. This callback will
* receive async callbacks like "new device found".
*/
- status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = sesasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, sesasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("ses: Failed to attach master async callback "
@@ -221,24 +207,17 @@
sesoninvalidate(struct cam_periph *periph)
{
struct ses_softc *softc;
- struct ccb_setasync csa;
softc = (struct ses_softc *)periph->softc;
/*
* Unregister any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = sesasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, sesasync, periph, periph->path);
softc->ses_flags |= SES_FLAG_INVALID;
- xpt_print_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
static void
@@ -250,8 +229,7 @@
destroy_dev(softc->ses_dev);
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
free(softc, M_SCSISES);
}
@@ -311,7 +289,6 @@
sesregister(struct cam_periph *periph, void *arg)
{
struct ses_softc *softc;
- struct ccb_setasync csa;
struct ccb_getdev *cgd;
char *tname;
@@ -365,21 +342,18 @@
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;
/*
* Add an async callback so that we get
* notified if this device goes away.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = sesasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_LOST_DEVICE, sesasync, periph, periph->path);
switch (softc->ses_type) {
default:
@@ -411,25 +385,20 @@
{
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) {
@@ -455,10 +424,10 @@
}
out:
+ cam_periph_unlock(periph);
if (error) {
cam_periph_release(periph);
}
- cam_periph_unlock(periph);
return (error);
}
@@ -475,11 +444,9 @@
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);
@@ -491,13 +458,11 @@
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
@@ -541,14 +506,17 @@
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;
@@ -578,22 +546,34 @@
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;
@@ -602,7 +582,9 @@
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:
@@ -613,7 +595,9 @@
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));
@@ -632,7 +616,9 @@
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.
@@ -642,11 +628,15 @@
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);
Index: scsi_low.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_low.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_low.c -L sys/cam/scsi/scsi_low.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_low.c
+++ sys/cam/scsi/scsi_low.c
@@ -2,7 +2,7 @@
/* $NetBSD$ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_low.c,v 1.24 2005/07/01 15:21:30 avatar Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_low.c,v 1.29 2007/06/17 05:55:54 scottl Exp $");
#define SCSI_LOW_STATICS
#define SCSI_LOW_DEBUG
@@ -1084,6 +1084,8 @@
break;
case XPT_SET_TRAN_SETTINGS: {
+ struct ccb_trans_settings_scsi *scsi;
+ struct ccb_trans_settings_spi *spi;
struct ccb_trans_settings *cts;
u_int val;
@@ -1102,49 +1104,46 @@
lun = 0;
s = SCSI_LOW_SPLSCSI();
- if ((cts->valid & (CCB_TRANS_BUS_WIDTH_VALID |
- CCB_TRANS_SYNC_RATE_VALID |
- CCB_TRANS_SYNC_OFFSET_VALID)) != 0)
+ scsi = &cts->proto_specific.scsi;
+ spi = &cts->xport_specific.spi;
+ if ((spi->valid & (CTS_SPI_VALID_BUS_WIDTH |
+ CTS_SPI_VALID_SYNC_RATE |
+ CTS_SPI_VALID_SYNC_OFFSET)) != 0)
{
- if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) {
- val = cts->bus_width;
+ if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
+ val = spi->bus_width;
if (val < ti->ti_width)
ti->ti_width = val;
}
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
- val = cts->sync_period;
+ if (spi->valid & CTS_SPI_VALID_SYNC_RATE) {
+ val = spi->sync_period;
if (val == 0 || val > ti->ti_maxsynch.period)
ti->ti_maxsynch.period = val;
}
- if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) {
- val = cts->sync_offset;
+ if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
+ val = spi->sync_offset;
if (val < ti->ti_maxsynch.offset)
ti->ti_maxsynch.offset = val;
}
-
ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID;
scsi_low_calcf_target(ti);
}
- if ((cts->valid & (CCB_TRANS_DISC_VALID |
- CCB_TRANS_TQ_VALID)) != 0)
- {
+ if ((spi->valid & CTS_SPI_FLAGS_DISC_ENB) != 0 ||
+ (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
+
li = scsi_low_alloc_li(ti, lun, 1);
- if ((cts->valid & CCB_TRANS_DISC_VALID) != 0)
- {
- if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)
- li->li_quirks |= SCSI_LOW_DISK_DISC;
- else
- li->li_quirks &= ~SCSI_LOW_DISK_DISC;
- }
- if ((cts->valid & CCB_TRANS_TQ_VALID) != 0)
- {
- if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)
- li->li_quirks |= SCSI_LOW_DISK_QTAG;
- else
- li->li_quirks &= ~SCSI_LOW_DISK_QTAG;
+ if (spi->valid & CTS_SPI_FLAGS_DISC_ENB) {
+ li->li_quirks |= SCSI_LOW_DISK_DISC;
+ } else {
+ li->li_quirks &= ~SCSI_LOW_DISK_DISC;
}
+ if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
+ li->li_quirks |= SCSI_LOW_DISK_QTAG;
+ } else {
+ li->li_quirks &= ~SCSI_LOW_DISK_QTAG;
+ }
li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID;
scsi_low_calcf_target(ti);
scsi_low_calcf_lun(li);
@@ -1178,7 +1177,6 @@
s = SCSI_LOW_SPLSCSI();
li = scsi_low_alloc_li(ti, lun, 1);
-#ifdef CAM_NEW_TRAN_CODE
if (li != NULL && cts->type == CTS_TYPE_CURRENT_SETTINGS) {
struct ccb_trans_settings_scsi *scsi =
&cts->proto_specific.scsi;
@@ -1222,65 +1220,6 @@
scsi->valid = 0;
} else
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
-#else
- if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0)
- {
-#ifdef SCSI_LOW_DIAGNOSTIC
- if ((li->li_flags_valid & SCSI_LOW_LUN_FLAGS_DISK_VALID) == 0)
- {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- printf("%s: invalid GET_TRANS_USER_SETTINGS call\n",
- slp->sl_xname);
- goto settings_out;
- }
-#endif /* SCSI_LOW_DIAGNOSTIC */
- diskflags = li->li_diskflags & li->li_cfgflags;
- if ((diskflags & SCSI_LOW_DISK_DISC) != 0)
- cts->flags |= CCB_TRANS_DISC_ENB;
- else
- cts->flags &= ~CCB_TRANS_DISC_ENB;
- if ((diskflags & SCSI_LOW_DISK_QTAG) != 0)
- cts->flags |= CCB_TRANS_TAG_ENB;
- else
- cts->flags &= ~CCB_TRANS_TAG_ENB;
- }
- else if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
- {
-#ifdef SCSI_LOW_DIAGNOSTIC
- if (li->li_flags_valid != SCSI_LOW_LUN_FLAGS_ALL_VALID)
- {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- printf("%s: invalid GET_TRANS_CURRENT_SETTINGS call\n",
- slp->sl_xname);
- goto settings_out;
- }
-#endif /* SCSI_LOW_DIAGNOSTIC */
- if ((li->li_flags & SCSI_LOW_DISC) != 0)
- cts->flags |= CCB_TRANS_DISC_ENB;
- else
- cts->flags &= ~CCB_TRANS_DISC_ENB;
- if ((li->li_flags & SCSI_LOW_QTAG) != 0)
- cts->flags |= CCB_TRANS_TAG_ENB;
- else
- cts->flags &= ~CCB_TRANS_TAG_ENB;
- }
- else
- {
- ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- goto settings_out;
- }
-
- cts->sync_period = ti->ti_maxsynch.period;
- cts->sync_offset = ti->ti_maxsynch.offset;
- cts->bus_width = ti->ti_width;
-
- cts->valid = CCB_TRANS_SYNC_RATE_VALID
- | CCB_TRANS_SYNC_OFFSET_VALID
- | CCB_TRANS_BUS_WIDTH_VALID
- | CCB_TRANS_DISC_VALID
- | CCB_TRANS_TQ_VALID;
- ccb->ccb_h.status = CAM_REQ_CMP;
-#endif
settings_out:
splx(s);
xpt_done(ccb);
@@ -1361,12 +1300,10 @@
cpi->initiator_id = slp->sl_hostid;
cpi->bus_id = cam_sim_bus(sim);
cpi->base_transfer_speed = 3300;
-#ifdef CAM_NEW_TRAN_CODE
cpi->transport = XPORT_SPI;
cpi->transport_version = 2;
cpi->protocol = PROTO_SCSI;
cpi->protocol_version = SCSI_REV_2;
-#endif
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -1406,7 +1343,7 @@
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) {
@@ -1414,7 +1351,7 @@
return ENODEV;
}
- if (xpt_bus_register(slp->sl_si.sim, 0) != CAM_SUCCESS) {
+ if (xpt_bus_register(slp->sl_si.sim, NULL, 0) != CAM_SUCCESS) {
free(slp->sl_si.sim, M_SCSILOW);
return ENODEV;
}
--- /dev/null
+++ sys/cam/scsi/scsi_sg.h
@@ -0,0 +1,144 @@
+/*
+ * Structures and definitions for SCSI commands to the SG passthrough device.
+ *
+ * $FreeBSD: src/sys/cam/scsi/scsi_sg.h,v 1.2 2007/04/10 20:03:42 scottl Exp $
+ */
+
+#ifndef _SCSI_SG_H
+#define _SCSI_SG_H
+
+#define SGIOC '"'
+#define SG_SET_TIMEOUT _IO(SGIOC, 0x01)
+#define SG_GET_TIMEOUT _IO(SGIOC, 0x02)
+#define SG_EMULATED_HOST _IO(SGIOC, 0x03)
+#define SG_SET_TRANSFORM _IO(SGIOC, 0x04)
+#define SG_GET_TRANSFORM _IO(SGIOC, 0x05)
+#define SG_GET_COMMAND_Q _IO(SGIOC, 0x70)
+#define SG_SET_COMMAND_Q _IO(SGIOC, 0x71)
+#define SG_GET_RESERVED_SIZE _IO(SGIOC, 0x72)
+#define SG_SET_RESERVED_SIZE _IO(SGIOC, 0x75)
+#define SG_GET_SCSI_ID _IO(SGIOC, 0x76)
+#define SG_SET_FORCE_LOW_DMA _IO(SGIOC, 0x79)
+#define SG_GET_LOW_DMA _IO(SGIOC, 0x7a)
+#define SG_SET_FORCE_PACK_ID _IO(SGIOC, 0x7b)
+#define SG_GET_PACK_ID _IO(SGIOC, 0x7c)
+#define SG_GET_NUM_WAITING _IO(SGIOC, 0x7d)
+#define SG_SET_DEBUG _IO(SGIOC, 0x7e)
+#define SG_GET_SG_TABLESIZE _IO(SGIOC, 0x7f)
+#define SG_GET_VERSION_NUM _IO(SGIOC, 0x82)
+#define SG_NEXT_CMD_LEN _IO(SGIOC, 0x83)
+#define SG_SCSI_RESET _IO(SGIOC, 0x84)
+#define SG_IO _IO(SGIOC, 0x85)
+#define SG_GET_REQUEST_TABLE _IO(SGIOC, 0x86)
+#define SG_SET_KEEP_ORPHAN _IO(SGIOC, 0x87)
+#define SG_GET_KEEP_ORPHAN _IO(SGIOC, 0x88)
+#define SG_GET_ACCESS_COUNT _IO(SGIOC, 0x89)
+
+struct sg_io_hdr {
+ int interface_id;
+ int dxfer_direction;
+ u_char cmd_len;
+ u_char mx_sb_len;
+ u_short iovec_count;
+ u_int dxfer_len;
+ void *dxferp;
+ u_char *cmdp;
+ u_char *sbp;
+ u_int timeout;
+ u_int flags;
+ int pack_id;
+ void *usr_ptr;
+ u_char status;
+ u_char masked_status;
+ u_char msg_status;
+ u_char sb_len_wr;
+ u_short host_status;
+ u_short driver_status;
+ int resid;
+ u_int duration;
+ u_int info;
+};
+
+#define SG_DXFER_NONE -1
+#define SG_DXFER_TO_DEV -2
+#define SG_DXFER_FROM_DEV -3
+#define SG_DXFER_TO_FROM_DEV -4
+#define SG_DXFER_UNKNOWN -5
+
+#define SG_MAX_SENSE 16
+struct sg_header {
+ int pack_len;
+ int reply_len;
+ int pack_id;
+ int result;
+ u_int twelve_byte:1;
+ u_int target_status:5;
+ u_int host_status:8;
+ u_int driver_status:8;
+ u_int other_flags:10;
+ u_char sense_buffer[SG_MAX_SENSE];
+};
+
+struct sg_scsi_id {
+ int host_no;
+ int channel;
+ int scsi_id;
+ int lun;
+ int scsi_type;
+ short h_cmd_per_lun;
+ short d_queue_depth;
+ int unused[2];
+};
+
+struct scsi_idlun {
+ uint32_t dev_id;
+ uint32_t host_unique_id;
+};
+
+/*
+ * Host codes
+ */
+#define DID_OK 0x00 /* OK */
+#define DID_NO_CONNECT 0x01 /* timeout during connect */
+#define DID_BUS_BUSY 0x02 /* timeout during command */
+#define DID_TIME_OUT 0x03 /* other timeout */
+#define DID_BAD_TARGET 0x04 /* bad target */
+#define DID_ABORT 0x05 /* abort */
+#define DID_PARITY 0x06 /* parity error */
+#define DID_ERROR 0x07 /* internal error */
+#define DID_RESET 0x08 /* reset by somebody */
+#define DID_BAD_INTR 0x09 /* unexpected interrupt */
+#define DID_PASSTHROUGH 0x0a /* passthrough */
+#define DID_SOFT_ERROR 0x0b /* low driver wants retry */
+#define DID_IMM_RETRY 0x0c /* retry without decreasing retrycnt */
+
+/*
+ * Driver codes
+ */
+#define DRIVER_OK 0x00
+#define DRIVER_BUSY 0x01
+#define DRIVER_SOFT 0x02
+#define DRIVER_MEDIA 0x03
+#define DRIVER_ERROR 0x04
+
+#define DRIVER_INVALID 0x05
+#define DRIVER_TIMEOUT 0x06
+#define DRIVER_HARD 0x07
+#define DRIVER_SENSE 0x08
+
+#define SUGGEST_RETRY 0x10
+#define SUGGEST_ABORT 0x20
+#define SUGGEST_REMAP 0x30
+#define SUGGEST_DIE 0x40
+#define SUGGEST_SENSE 0x80
+#define SUGGEST_IS_OK 0xff
+
+#define DRIVER_MASK 0x0f
+#define SUGGEST_MASK 0xf0
+
+/* Other definitions */
+/* HZ isn't always available, so simulate it */
+#define SG_DEFAULT_HZ 1000
+#define SG_DEFAULT_TIMEOUT (60*SG_DEFAULT_HZ)
+
+#endif /* !_SCSI_SG_H */
--- /dev/null
+++ sys/cam/scsi/scsi_sg.c
@@ -0,0 +1,983 @@
+/*-
+ * Copyright (c) 2007 Scott Long
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * scsi_sg peripheral driver. This driver is meant to implement the Linux
+ * SG passthrough interface for SCSI.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_sg.c,v 1.9 2007/05/16 16:54:23 scottl Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/bio.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/ioccom.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/devicestat.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_periph.h>
+#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>
+#include <cam/scsi/scsi_sg.h>
+
+#include <compat/linux/linux_ioctl.h>
+
+typedef enum {
+ SG_FLAG_OPEN = 0x01,
+ SG_FLAG_LOCKED = 0x02,
+ SG_FLAG_INVALID = 0x04
+} sg_flags;
+
+typedef enum {
+ SG_STATE_NORMAL
+} sg_state;
+
+typedef enum {
+ SG_RDWR_FREE,
+ SG_RDWR_INPROG,
+ SG_RDWR_DONE
+} sg_rdwr_state;
+
+typedef enum {
+ SG_CCB_RDWR_IO,
+ SG_CCB_WAITING
+} sg_ccb_types;
+
+#define ccb_type ppriv_field0
+#define ccb_rdwr ppriv_ptr1
+
+struct sg_rdwr {
+ TAILQ_ENTRY(sg_rdwr) rdwr_link;
+ int tag;
+ int state;
+ int buf_len;
+ char *buf;
+ union ccb *ccb;
+ union {
+ struct sg_header hdr;
+ struct sg_io_hdr io_hdr;
+ } hdr;
+};
+
+struct sg_softc {
+ sg_state state;
+ sg_flags flags;
+ struct devstat *device_stats;
+ TAILQ_HEAD(, sg_rdwr) rdwr_done;
+ struct cdev *dev;
+ int sg_timeout;
+ int sg_user_timeout;
+ uint8_t pd_type;
+ union ccb saved_ccb;
+};
+
+static d_open_t sgopen;
+static d_close_t sgclose;
+static d_ioctl_t sgioctl;
+static d_write_t sgwrite;
+static d_read_t sgread;
+
+static periph_init_t sginit;
+static periph_ctor_t sgregister;
+static periph_oninv_t sgoninvalidate;
+static periph_dtor_t sgcleanup;
+static periph_start_t sgstart;
+static void sgasync(void *callback_arg, uint32_t code,
+ struct cam_path *path, void *arg);
+static void sgdone(struct cam_periph *periph, union ccb *done_ccb);
+static int sgsendccb(struct cam_periph *periph, union ccb *ccb);
+static int sgsendrdwr(struct cam_periph *periph, union ccb *ccb);
+static int sgerror(union ccb *ccb, uint32_t cam_flags,
+ uint32_t sense_flags);
+static void sg_scsiio_status(struct ccb_scsiio *csio,
+ u_short *hoststat, u_short *drvstat);
+
+static int scsi_group_len(u_char cmd);
+
+static struct periph_driver sgdriver =
+{
+ sginit, "sg",
+ TAILQ_HEAD_INITIALIZER(sgdriver.units), /* gen */ 0
+};
+PERIPHDRIVER_DECLARE(sg, sgdriver);
+
+static struct cdevsw sg_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = D_NEEDGIANT,
+ .d_open = sgopen,
+ .d_close = sgclose,
+ .d_ioctl = sgioctl,
+ .d_write = sgwrite,
+ .d_read = sgread,
+ .d_name = "sg",
+};
+
+static int sg_version = 30125;
+
+static void
+sginit(void)
+{
+ cam_status status;
+
+ /*
+ * Install a global async callback. This callback will receive aync
+ * callbacks like "new device found".
+ */
+ status = xpt_register_async(AC_FOUND_DEVICE, sgasync, NULL, NULL);
+
+ if (status != CAM_REQ_CMP) {
+ printf("sg: Failed to attach master async callbac "
+ "due to status 0x%x!\n", status);
+ }
+}
+
+static void
+sgoninvalidate(struct cam_periph *periph)
+{
+ struct sg_softc *softc;
+
+ softc = (struct sg_softc *)periph->softc;
+
+ /*
+ * Deregister any async callbacks.
+ */
+ xpt_register_async(0, sgasync, periph, periph->path);
+
+ softc->flags |= SG_FLAG_INVALID;
+
+ /*
+ * XXX Return all queued I/O with ENXIO.
+ * XXX Handle any transactions queued to the card
+ * with XPT_ABORT_CCB.
+ */
+
+ if (bootverbose) {
+ xpt_print(periph->path, "lost device\n");
+ }
+}
+
+static void
+sgcleanup(struct cam_periph *periph)
+{
+ struct sg_softc *softc;
+
+ softc = (struct sg_softc *)periph->softc;
+ devstat_remove_entry(softc->device_stats);
+ destroy_dev(softc->dev);
+ if (bootverbose) {
+ xpt_print(periph->path, "removing device entry\n");
+ }
+ free(softc, M_DEVBUF);
+}
+
+static void
+sgasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
+{
+ struct cam_periph *periph;
+
+ periph = (struct cam_periph *)callback_arg;
+
+ switch (code) {
+ case AC_FOUND_DEVICE:
+ {
+ struct ccb_getdev *cgd;
+ cam_status status;
+
+ cgd = (struct ccb_getdev *)arg;
+ if (cgd == NULL)
+ break;
+
+ /*
+ * Allocate a peripheral instance for this device and
+ * start the probe process.
+ */
+ status = cam_periph_alloc(sgregister, sgoninvalidate,
+ sgcleanup, sgstart, "sg",
+ CAM_PERIPH_BIO, cgd->ccb_h.path,
+ sgasync, AC_FOUND_DEVICE, cgd);
+ if ((status != CAM_REQ_CMP) && (status != CAM_REQ_INPROG)) {
+ const struct cam_status_entry *entry;
+
+ entry = cam_fetch_status_entry(status);
+ printf("sgasync: Unable to attach new device "
+ "due to status %#x: %s\n", status, entry ?
+ entry->status_text : "Unknown");
+ }
+ break;
+ }
+ default:
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
+}
+
+static cam_status
+sgregister(struct cam_periph *periph, void *arg)
+{
+ struct sg_softc *softc;
+ struct ccb_getdev *cgd;
+ int no_tags;
+
+ cgd = (struct ccb_getdev *)arg;
+ if (periph == NULL) {
+ printf("sgregister: periph was NULL!!\n");
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ if (cgd == NULL) {
+ printf("sgregister: no getdev CCB, can't register device\n");
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ softc = malloc(sizeof(*softc), M_DEVBUF, M_ZERO | M_NOWAIT);
+ if (softc == NULL) {
+ printf("sgregister: Unable to allocate softc\n");
+ return (CAM_REQ_CMP_ERR);
+ }
+
+ softc->state = SG_STATE_NORMAL;
+ softc->pd_type = SID_TYPE(&cgd->inq_data);
+ softc->sg_timeout = SG_DEFAULT_TIMEOUT / SG_DEFAULT_HZ * hz;
+ softc->sg_user_timeout = SG_DEFAULT_TIMEOUT;
+ TAILQ_INIT(&softc->rdwr_done);
+ periph->softc = softc;
+
+ /*
+ * We pass in 0 for all blocksize, since we don't know what the
+ * blocksize of the device is, if it even has a blocksize.
+ */
+ cam_periph_unlock(periph);
+ no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
+ softc->device_stats = devstat_new_entry("sg",
+ unit2minor(periph->unit_number), 0,
+ DEVSTAT_NO_BLOCKSIZE
+ | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
+ softc->pd_type |
+ DEVSTAT_TYPE_IF_SCSI |
+ DEVSTAT_TYPE_PASS,
+ DEVSTAT_PRIORITY_PASS);
+
+ /* Register the device */
+ softc->dev = make_dev(&sg_cdevsw, unit2minor(periph->unit_number),
+ UID_ROOT, GID_OPERATOR, 0600, "%s%d",
+ periph->periph_name, periph->unit_number);
+ (void)make_dev_alias(softc->dev, "sg%c", 'a' + periph->unit_number);
+ cam_periph_lock(periph);
+ softc->dev->si_drv1 = periph;
+
+ /*
+ * Add as async callback so that we get
+ * notified if this device goes away.
+ */
+ xpt_register_async(AC_LOST_DEVICE, sgasync, periph, periph->path);
+
+ if (bootverbose)
+ xpt_announce_periph(periph, NULL);
+
+ return (CAM_REQ_CMP);
+}
+
+static void
+sgstart(struct cam_periph *periph, union ccb *start_ccb)
+{
+ struct sg_softc *softc;
+
+ softc = (struct sg_softc *)periph->softc;
+
+ switch (softc->state) {
+ case SG_STATE_NORMAL:
+ start_ccb->ccb_h.ccb_type = SG_CCB_WAITING;
+ SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
+ periph_links.sle);
+ periph->immediate_priority = CAM_PRIORITY_NONE;
+ wakeup(&periph->ccb_list);
+ break;
+ }
+}
+
+static void
+sgdone(struct cam_periph *periph, union ccb *done_ccb)
+{
+ struct sg_softc *softc;
+ struct ccb_scsiio *csio;
+
+ softc = (struct sg_softc *)periph->softc;
+ csio = &done_ccb->csio;
+ switch (csio->ccb_h.ccb_type) {
+ case SG_CCB_WAITING:
+ /* Caller will release the CCB */
+ wakeup(&done_ccb->ccb_h.cbfcnp);
+ return;
+ case SG_CCB_RDWR_IO:
+ {
+ struct sg_rdwr *rdwr;
+ int state;
+
+ devstat_end_transaction(softc->device_stats,
+ csio->dxfer_len,
+ csio->tag_action & 0xf,
+ ((csio->ccb_h.flags & CAM_DIR_MASK) ==
+ CAM_DIR_NONE) ? DEVSTAT_NO_DATA :
+ (csio->ccb_h.flags & CAM_DIR_OUT) ?
+ DEVSTAT_WRITE : DEVSTAT_READ,
+ NULL, NULL);
+
+ rdwr = done_ccb->ccb_h.ccb_rdwr;
+ state = rdwr->state;
+ rdwr->state = SG_RDWR_DONE;
+ wakeup(rdwr);
+ break;
+ }
+ default:
+ panic("unknown sg CCB type");
+ }
+}
+
+static int
+sgopen(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+ struct sg_softc *softc;
+ int error = 0;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ /*
+ * Don't allow access when we're running at a high securelevel.
+ */
+ error = securelevel_gt(td->td_ucred, 1);
+ if (error)
+ 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) {
+ softc->flags |= SG_FLAG_OPEN;
+ } else {
+ /* Device closes aren't symmetrical, fix up the refcount. */
+ cam_periph_release(periph);
+ }
+
+ cam_periph_unlock(periph);
+
+ return (error);
+}
+
+static int
+sgclose(struct cdev *dev, int flag, int fmt, struct thread *td)
+{
+ struct cam_periph *periph;
+ struct sg_softc *softc;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ cam_periph_lock(periph);
+
+ softc = (struct sg_softc *)periph->softc;
+ softc->flags &= ~SG_FLAG_OPEN;
+
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+
+ return (0);
+}
+
+static int
+sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
+{
+ union ccb *ccb;
+ struct ccb_scsiio *csio;
+ struct cam_periph *periph;
+ struct sg_softc *softc;
+ struct sg_io_hdr req;
+ int dir, error;
+
+ periph = (struct cam_periph *)dev->si_drv1;
+ if (periph == NULL)
+ return (ENXIO);
+
+ cam_periph_lock(periph);
+
+ softc = (struct sg_softc *)periph->softc;
+ error = 0;
+
+ switch (cmd) {
+ case LINUX_SCSI_GET_BUS_NUMBER: {
+ int busno;
+
+ busno = xpt_path_path_id(periph->path);
+ error = copyout(&busno, arg, sizeof(busno));
+ break;
+ }
+ case LINUX_SCSI_GET_IDLUN: {
+ struct scsi_idlun idlun;
+ struct cam_sim *sim;
+
+ idlun.dev_id = xpt_path_target_id(periph->path);
+ sim = xpt_path_sim(periph->path);
+ idlun.host_unique_id = sim->unit_number;
+ error = copyout(&idlun, arg, sizeof(idlun));
+ break;
+ }
+ case SG_GET_VERSION_NUM:
+ case LINUX_SG_GET_VERSION_NUM:
+ error = copyout(&sg_version, arg, sizeof(sg_version));
+ break;
+ case SG_SET_TIMEOUT:
+ case LINUX_SG_SET_TIMEOUT: {
+ u_int user_timeout;
+
+ error = copyin(arg, &user_timeout, sizeof(u_int));
+ if (error == 0) {
+ softc->sg_user_timeout = user_timeout;
+ softc->sg_timeout = user_timeout / SG_DEFAULT_HZ * hz;
+ }
+ break;
+ }
+ case SG_GET_TIMEOUT:
+ case LINUX_SG_GET_TIMEOUT:
+ /*
+ * The value is returned directly to the syscall.
+ */
+ td->td_retval[0] = softc->sg_user_timeout;
+ error = 0;
+ break;
+ case SG_IO:
+ case LINUX_SG_IO:
+ error = copyin(arg, &req, sizeof(req));
+ if (error)
+ break;
+
+ if (req.cmd_len > IOCDBLEN) {
+ error = EINVAL;
+ break;
+ }
+
+ if (req.iovec_count != 0) {
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ ccb = cam_periph_getccb(periph, /*priority*/5);
+ csio = &ccb->csio;
+
+ error = copyin(req.cmdp, &csio->cdb_io.cdb_bytes,
+ req.cmd_len);
+ if (error) {
+ xpt_release_ccb(ccb);
+ break;
+ }
+
+ switch(req.dxfer_direction) {
+ case SG_DXFER_TO_DEV:
+ dir = CAM_DIR_OUT;
+ break;
+ case SG_DXFER_FROM_DEV:
+ dir = CAM_DIR_IN;
+ break;
+ case SG_DXFER_TO_FROM_DEV:
+ dir = CAM_DIR_IN | CAM_DIR_OUT;
+ break;
+ case SG_DXFER_NONE:
+ default:
+ dir = CAM_DIR_NONE;
+ break;
+ }
+
+ cam_fill_csio(csio,
+ /*retries*/1,
+ sgdone,
+ dir|CAM_DEV_QFRZDIS,
+ MSG_SIMPLE_Q_TAG,
+ req.dxferp,
+ req.dxfer_len,
+ req.mx_sb_len,
+ req.cmd_len,
+ req.timeout);
+
+ error = sgsendccb(periph, ccb);
+ if (error) {
+ req.host_status = DID_ERROR;
+ req.driver_status = DRIVER_INVALID;
+ xpt_release_ccb(ccb);
+ break;
+ }
+
+ req.status = csio->scsi_status;
+ req.masked_status = (csio->scsi_status >> 1) & 0x7f;
+ sg_scsiio_status(csio, &req.host_status, &req.driver_status);
+ req.resid = csio->resid;
+ req.duration = csio->ccb_h.timeout;
+ req.info = 0;
+
+ error = copyout(&req, arg, sizeof(req));
+ if ((error == 0) && (csio->ccb_h.status & CAM_AUTOSNS_VALID)
+ && (req.sbp != NULL)) {
+ req.sb_len_wr = req.mx_sb_len - csio->sense_resid;
+ error = copyout(&csio->sense_data, req.sbp,
+ req.sb_len_wr);
+ }
+
+ xpt_release_ccb(ccb);
+ break;
+
+ case SG_GET_RESERVED_SIZE:
+ case LINUX_SG_GET_RESERVED_SIZE: {
+ int size = 32768;
+
+ error = copyout(&size, arg, sizeof(size));
+ break;
+ }
+
+ case SG_GET_SCSI_ID:
+ case LINUX_SG_GET_SCSI_ID:
+ {
+ struct sg_scsi_id id;
+
+ id.host_no = 0; /* XXX */
+ id.channel = xpt_path_path_id(periph->path);
+ id.scsi_id = xpt_path_target_id(periph->path);
+ id.lun = xpt_path_lun_id(periph->path);
+ id.scsi_type = softc->pd_type;
+ id.h_cmd_per_lun = 1;
+ id.d_queue_depth = 1;
+ id.unused[0] = 0;
+ id.unused[1] = 0;
+
+ error = copyout(&id, arg, sizeof(id));
+ break;
+ }
+
+ case SG_EMULATED_HOST:
+ case SG_SET_TRANSFORM:
+ case SG_GET_TRANSFORM:
+ case SG_GET_NUM_WAITING:
+ case SG_SCSI_RESET:
+ case SG_GET_REQUEST_TABLE:
+ case SG_SET_KEEP_ORPHAN:
+ case SG_GET_KEEP_ORPHAN:
+ case SG_GET_ACCESS_COUNT:
+ case SG_SET_FORCE_LOW_DMA:
+ case SG_GET_LOW_DMA:
+ case SG_GET_SG_TABLESIZE:
+ case SG_SET_FORCE_PACK_ID:
+ case SG_GET_PACK_ID:
+ case SG_SET_RESERVED_SIZE:
+ case SG_GET_COMMAND_Q:
+ case SG_SET_COMMAND_Q:
+ case SG_SET_DEBUG:
+ case SG_NEXT_CMD_LEN:
+ case LINUX_SG_EMULATED_HOST:
+ case LINUX_SG_SET_TRANSFORM:
+ case LINUX_SG_GET_TRANSFORM:
+ case LINUX_SG_GET_NUM_WAITING:
+ case LINUX_SG_SCSI_RESET:
+ case LINUX_SG_GET_REQUEST_TABLE:
+ case LINUX_SG_SET_KEEP_ORPHAN:
+ case LINUX_SG_GET_KEEP_ORPHAN:
+ case LINUX_SG_GET_ACCESS_COUNT:
+ case LINUX_SG_SET_FORCE_LOW_DMA:
+ case LINUX_SG_GET_LOW_DMA:
+ case LINUX_SG_GET_SG_TABLESIZE:
+ case LINUX_SG_SET_FORCE_PACK_ID:
+ case LINUX_SG_GET_PACK_ID:
+ case LINUX_SG_SET_RESERVED_SIZE:
+ case LINUX_SG_GET_COMMAND_Q:
+ case LINUX_SG_SET_COMMAND_Q:
+ case LINUX_SG_SET_DEBUG:
+ case LINUX_SG_NEXT_CMD_LEN:
+ default:
+#ifdef CAMDEBUG
+ printf("sgioctl: rejecting cmd 0x%lx\n", cmd);
+#endif
+ error = ENODEV;
+ break;
+ }
+
+ cam_periph_unlock(periph);
+ return (error);
+}
+
+static int
+sgwrite(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ union ccb *ccb;
+ struct cam_periph *periph;
+ struct ccb_scsiio *csio;
+ struct sg_softc *sc;
+ struct sg_header *hdr;
+ struct sg_rdwr *rdwr;
+ u_char cdb_cmd;
+ char *buf;
+ int error = 0, cdb_len, buf_len, dir;
+
+ periph = dev->si_drv1;
+ rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO);
+ hdr = &rdwr->hdr.hdr;
+
+ /* Copy in the header block and sanity check it */
+ if (uio->uio_resid < sizeof(*hdr)) {
+ error = EINVAL;
+ goto out_hdr;
+ }
+ error = uiomove(hdr, sizeof(*hdr), uio);
+ if (error)
+ goto out_hdr;
+
+ ccb = xpt_alloc_ccb();
+ if (ccb == NULL) {
+ error = ENOMEM;
+ goto out_hdr;
+ }
+ csio = &ccb->csio;
+
+ /*
+ * Copy in the CDB block. The designers of the interface didn't
+ * bother to provide a size for this in the header, so we have to
+ * figure it out ourselves.
+ */
+ if (uio->uio_resid < 1)
+ goto out_ccb;
+ error = uiomove(&cdb_cmd, 1, uio);
+ if (error)
+ goto out_ccb;
+ if (hdr->twelve_byte)
+ cdb_len = 12;
+ else
+ cdb_len = scsi_group_len(cdb_cmd);
+ /*
+ * We've already read the first byte of the CDB and advanced the uio
+ * pointer. Just read the rest.
+ */
+ csio->cdb_io.cdb_bytes[0] = cdb_cmd;
+ error = uiomove(&csio->cdb_io.cdb_bytes[1], cdb_len - 1, uio);
+ if (error)
+ goto out_ccb;
+
+ /*
+ * Now set up the data block. Again, the designers didn't bother
+ * to make this reliable.
+ */
+ buf_len = uio->uio_resid;
+ if (buf_len != 0) {
+ buf = malloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO);
+ error = uiomove(buf, buf_len, uio);
+ if (error)
+ goto out_buf;
+ dir = CAM_DIR_OUT;
+ } else if (hdr->reply_len != 0) {
+ buf = malloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO);
+ buf_len = hdr->reply_len;
+ dir = CAM_DIR_IN;
+ } else {
+ buf = NULL;
+ buf_len = 0;
+ 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,
+ dir|CAM_DEV_QFRZDIS,
+ MSG_SIMPLE_Q_TAG,
+ buf,
+ buf_len,
+ SG_MAX_SENSE,
+ cdb_len,
+ sc->sg_timeout);
+
+ /*
+ * Send off the command and hope that it works. This path does not
+ * go through sgstart because the I/O is supposed to be asynchronous.
+ */
+ rdwr->buf = buf;
+ rdwr->buf_len = buf_len;
+ rdwr->tag = hdr->pack_id;
+ rdwr->ccb = ccb;
+ rdwr->state = SG_RDWR_INPROG;
+ ccb->ccb_h.ccb_rdwr = rdwr;
+ ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO;
+ TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link);
+ error = sgsendrdwr(periph, ccb);
+ cam_periph_unlock(periph);
+ return (error);
+
+out_buf:
+ free(buf, M_DEVBUF);
+out_ccb:
+ xpt_free_ccb(ccb);
+out_hdr:
+ free(rdwr, M_DEVBUF);
+ return (error);
+}
+
+static int
+sgread(struct cdev *dev, struct uio *uio, int ioflag)
+{
+ struct ccb_scsiio *csio;
+ struct cam_periph *periph;
+ struct sg_softc *sc;
+ struct sg_header *hdr;
+ struct sg_rdwr *rdwr;
+ u_short hstat, dstat;
+ int error, pack_len, reply_len, pack_id;
+
+ periph = dev->si_drv1;
+
+ /* XXX The pack len field needs to be updated and written out instead
+ * of discarded. Not sure how to do that.
+ */
+ uio->uio_rw = UIO_WRITE;
+ if ((error = uiomove(&pack_len, 4, uio)) != 0)
+ return (error);
+ if ((error = uiomove(&reply_len, 4, uio)) != 0)
+ return (error);
+ if ((error = uiomove(&pack_id, 4, uio)) != 0)
+ 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 (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;
+ sg_scsiio_status(csio, &hstat, &dstat);
+ hdr->host_status = hstat;
+ hdr->driver_status = dstat;
+ hdr->target_status = csio->scsi_status >> 1;
+
+ switch (hstat) {
+ case DID_OK:
+ case DID_PASSTHROUGH:
+ case DID_SOFT_ERROR:
+ hdr->result = 0;
+ break;
+ case DID_NO_CONNECT:
+ case DID_BUS_BUSY:
+ case DID_TIME_OUT:
+ hdr->result = EBUSY;
+ break;
+ case DID_BAD_TARGET:
+ case DID_ABORT:
+ case DID_PARITY:
+ case DID_RESET:
+ case DID_BAD_INTR:
+ case DID_ERROR:
+ default:
+ hdr->result = EIO;
+ break;
+ }
+
+ if (dstat == DRIVER_SENSE) {
+ bcopy(&csio->sense_data, hdr->sense_buffer,
+ min(csio->sense_len, SG_MAX_SENSE));
+#ifdef CAMDEBUG
+ scsi_sense_print(csio);
+#endif
+ }
+
+ error = uiomove(&hdr->result, sizeof(*hdr) -
+ offsetof(struct sg_header, result), uio);
+ 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);
+}
+
+static int
+sgsendccb(struct cam_periph *periph, union ccb *ccb)
+{
+ struct sg_softc *softc;
+ struct cam_periph_map_info mapinfo;
+ int error, need_unmap = 0;
+
+ softc = periph->softc;
+ 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;
+ }
+
+ error = cam_periph_runccb(ccb,
+ sgerror,
+ CAM_RETRY_SELTO,
+ SF_RETRY_UA,
+ softc->device_stats);
+
+ if (need_unmap)
+ cam_periph_unmapmem(ccb, &mapinfo);
+
+ return (error);
+}
+
+static int
+sgsendrdwr(struct cam_periph *periph, union ccb *ccb)
+{
+ struct sg_softc *softc;
+
+ softc = periph->softc;
+ devstat_start_transaction(softc->device_stats, NULL);
+ xpt_action(ccb);
+ return (0);
+}
+
+static int
+sgerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags)
+{
+ struct cam_periph *periph;
+ struct sg_softc *softc;
+
+ periph = xpt_path_periph(ccb->ccb_h.path);
+ softc = (struct sg_softc *)periph->softc;
+
+ return (cam_periph_error(ccb, cam_flags, sense_flags,
+ &softc->saved_ccb));
+}
+
+static void
+sg_scsiio_status(struct ccb_scsiio *csio, u_short *hoststat, u_short *drvstat)
+{
+ int status;
+
+ status = csio->ccb_h.status;
+
+ switch (status & CAM_STATUS_MASK) {
+ case CAM_REQ_CMP:
+ *hoststat = DID_OK;
+ *drvstat = 0;
+ break;
+ case CAM_REQ_CMP_ERR:
+ *hoststat = DID_ERROR;
+ *drvstat = 0;
+ break;
+ case CAM_REQ_ABORTED:
+ *hoststat = DID_ABORT;
+ *drvstat = 0;
+ break;
+ case CAM_REQ_INVALID:
+ *hoststat = DID_ERROR;
+ *drvstat = DRIVER_INVALID;
+ break;
+ case CAM_DEV_NOT_THERE:
+ *hoststat = DID_BAD_TARGET;
+ *drvstat = 0;
+ case CAM_SEL_TIMEOUT:
+ *hoststat = DID_NO_CONNECT;
+ *drvstat = 0;
+ break;
+ case CAM_CMD_TIMEOUT:
+ *hoststat = DID_TIME_OUT;
+ *drvstat = 0;
+ break;
+ case CAM_SCSI_STATUS_ERROR:
+ *hoststat = DID_ERROR;
+ *drvstat = 0;
+ case CAM_SCSI_BUS_RESET:
+ *hoststat = DID_RESET;
+ *drvstat = 0;
+ break;
+ case CAM_UNCOR_PARITY:
+ *hoststat = DID_PARITY;
+ *drvstat = 0;
+ break;
+ case CAM_SCSI_BUSY:
+ *hoststat = DID_BUS_BUSY;
+ *drvstat = 0;
+ default:
+ *hoststat = DID_ERROR;
+ *drvstat = DRIVER_ERROR;
+ }
+
+ if (status & CAM_AUTOSNS_VALID)
+ *drvstat = DRIVER_SENSE;
+}
+
+static int
+scsi_group_len(u_char cmd)
+{
+ int len[] = {6, 10, 10, 12, 12, 12, 10, 10};
+ int group;
+
+ group = (cmd >> 5) & 0x7;
+ return (len[group]);
+}
+
Index: scsi_ses.h
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_ses.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_ses.h -L sys/cam/scsi/scsi_ses.h -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_ses.h
+++ sys/cam/scsi/scsi_ses.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/cam/scsi/scsi_ses.h,v 1.3.2.1 2006/03/09 21:43:10 mjacob Exp $ */
+/* $FreeBSD: src/sys/cam/scsi/scsi_ses.h,v 1.4 2006/01/18 08:37:27 mjacob Exp $ */
/*-
* Copyright (c) 2000 by Matthew Jacob
* All rights reserved.
Index: scsi_sa.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_sa.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_sa.c -L sys/cam/scsi/scsi_sa.c -u -r1.1.1.2 -r1.2
--- sys/cam/scsi/scsi_sa.c
+++ sys/cam/scsi/scsi_sa.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_sa.c,v 1.105.2.1 2006/01/26 04:57:04 mjacob Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_sa.c,v 1.113 2007/06/16 18:20:29 scottl Exp $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -447,37 +447,33 @@
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 @@
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 @@
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?
*/
@@ -566,8 +571,8 @@
*/
error = sacheckeod(periph);
if (error) {
- xpt_print_path(periph->path);
- printf("failed to write terminating filemark(s)\n");
+ xpt_print(periph->path,
+ "failed to write terminating filemark(s)\n");
softc->flags |= SA_FLAG_TAPE_FROZEN;
}
@@ -622,19 +627,18 @@
if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) {
tmp = saspace(periph, -1, SS_FILEMARKS);
if (tmp) {
- xpt_print_path(periph->path);
- printf("unable to backspace over one of double"
- " filemarks at end of tape\n");
- xpt_print_path(periph->path);
- printf("it is possible that this device"
- " needs a SA_QUIRK_1FM quirk set for it\n");
+ xpt_print(periph->path, "unable to backspace "
+ "over one of double filemarks at end of "
+ "tape\n");
+ xpt_print(periph->path, "it is possible that "
+ "this device needs a SA_QUIRK_1FM quirk set"
+ "for it\n");
softc->flags |= SA_FLAG_TAPE_FROZEN;
}
}
break;
default:
- xpt_print_path(periph->path);
- panic("unknown mode 0x%x in saclose", mode);
+ xpt_print(periph->path, "unknown mode 0x%x in saclose\n", mode);
/* NOTREACHED */
break;
}
@@ -654,15 +658,15 @@
* Inform users if tape state if frozen....
*/
if (softc->flags & SA_FLAG_TAPE_FROZEN) {
- xpt_print_path(periph->path);
- printf("tape is now frozen- use an OFFLINE, REWIND or MTEOM "
- "command to clear this state.\n");
+ xpt_print(periph->path, "tape is now frozen- use an OFFLINE, "
+ "REWIND or MTEOM command to clear this state.\n");
}
/* release the device if it is no longer mounted */
if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
sareservereleaseunit(periph, FALSE);
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
cam_periph_release(periph);
@@ -679,7 +683,6 @@
{
struct cam_periph *periph;
struct sa_softc *softc;
- int s;
bp->bio_resid = bp->bio_bcount;
if (SA_IS_CTRL(bp->bio_dev)) {
@@ -691,18 +694,18 @@
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;
}
@@ -713,16 +716,15 @@
* 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;
}
@@ -735,6 +737,7 @@
* If it's a null transfer, return immediately
*/
if (bp->bio_bcount == 0) {
+ cam_periph_unlock(periph);
biodone(bp);
return;
}
@@ -749,10 +752,10 @@
((bp->bio_bcount & softc->blk_mask) != 0)) ||
((softc->blk_mask == ~0) &&
((bp->bio_bcount % softc->min_blk) != 0))) {
- xpt_print_path(periph->path);
- printf("Invalid request. Fixed block device "
- "requests must be a multiple "
- "of %d bytes\n", softc->min_blk);
+ 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;
}
@@ -761,25 +764,19 @@
(bp->bio_bcount & softc->blk_mask) != 0) {
xpt_print_path(periph->path);
- printf("Invalid request. Variable block device "
- "requests must be ");
+ printf("Invalid request. Variable block "
+ "device requests must be ");
if (softc->blk_mask != 0) {
printf("a multiple of %d ", (0x1 << softc->blk_gran));
}
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);
@@ -794,12 +791,12 @@
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;
}
@@ -822,7 +819,6 @@
struct sa_softc *softc;
scsi_space_code spaceop;
int didlockperiph = 0;
- int s;
int mode;
int error = 0;
@@ -834,6 +830,7 @@
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
softc = (struct sa_softc *)periph->softc;
/*
@@ -859,13 +856,10 @@
* 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;
@@ -898,12 +892,9 @@
* 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;
@@ -1070,8 +1061,8 @@
nmarks = softc->filemarks;
error = sacheckeod(periph);
if (error) {
- xpt_print_path(periph->path);
- printf("EOD check prior to spacing failed\n");
+ xpt_print(periph->path,
+ "EOD check prior to spacing failed\n");
softc->flags |= SA_FLAG_EIO_PENDING;
break;
}
@@ -1322,16 +1313,17 @@
softc->fileno = (daddr_t) -1;
softc->blkno = (daddr_t) -1;
softc->flags &= ~SA_FLAG_TAPE_FROZEN;
- xpt_print_path(periph->path);
- printf("tape state now unfrozen.\n");
+ xpt_print(periph->path,
+ "tape state now unfrozen.\n");
break;
default:
break;
}
}
if (didlockperiph) {
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -1339,29 +1331,11 @@
sainit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback.
*/
- status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- /* Register the async callbacks of interrest */
- struct ccb_setasync csa; /*
- * This is an immediate CCB,
- * so using the stack is OK
- */
- xpt_setup_ccb(&csa.ccb_h, path, 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = saasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, saasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("sa: Failed to attach master async callback "
@@ -1373,42 +1347,25 @@
saoninvalidate(struct cam_periph *periph)
{
struct sa_softc *softc;
- struct ccb_setasync csa;
- int s;
softc = (struct sa_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = saasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, saasync, periph, periph->path);
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_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
@@ -1430,8 +1387,7 @@
destroy_dev(softc->devs.mode_devs[i].er_dev);
}
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
free(softc, M_SCSISA);
}
@@ -1481,7 +1437,6 @@
saregister(struct cam_periph *periph, void *arg)
{
struct sa_softc *softc;
- struct ccb_setasync csa;
struct ccb_getdev *cgd;
caddr_t match;
int i;
@@ -1525,9 +1480,8 @@
softc->last_media_blksize =
((struct sa_quirk_entry *)match)->prefblk;
#ifdef CAMDEBUG
- xpt_print_path(periph->path);
- printf("found quirk entry %d\n", (int)
- (((struct sa_quirk_entry *) match) - sa_quirk_table));
+ xpt_print(periph->path, "found quirk entry %d\n",
+ (int) (((struct sa_quirk_entry *) match) - sa_quirk_table));
#endif
} else
softc->quirks = SA_QUIRK_NONE;
@@ -1537,6 +1491,7 @@
* blocksize until we media is inserted. So, set a flag to
* indicate that the blocksize is unavailable right now.
*/
+ cam_periph_unlock(periph);
softc->device_stats = devstat_new_entry("sa", periph->unit_number, 0,
DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) |
DEVSTAT_TYPE_IF_SCSI, DEVSTAT_PRIORITY_TAPE);
@@ -1583,17 +1538,13 @@
alias->si_drv1 = periph;
}
}
+ cam_periph_lock(periph);
/*
* Add an async callback so that we get
* notified if this device goes away.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = saasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_LOST_DEVICE, saasync, periph, periph->path);
xpt_announce_periph(periph, NULL);
@@ -1615,12 +1566,10 @@
{
/* 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,
@@ -1629,10 +1578,8 @@
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;
@@ -1675,7 +1622,6 @@
"%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 {
@@ -1693,10 +1639,8 @@
softc->media_blksize;
} else {
bp->bio_error = EIO;
- xpt_print_path(periph->path);
- printf("zero blocksize for "
- "FIXED length writes?\n");
- splx(s);
+ xpt_print(periph->path, "zero blocksize"
+ " for FIXED length writes?\n");
biodone(bp);
break;
}
@@ -1747,7 +1691,6 @@
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);
}
@@ -1792,7 +1735,6 @@
}
if (error == EIO) {
- int s;
/*
* Catastrophic error. Mark the tape as frozen
@@ -1805,10 +1747,8 @@
*
*/
- 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;
@@ -1920,8 +1860,8 @@
*/
softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
- xpt_print_path(periph->path);
- printf("error %d on TUR in samount\n", error);
+ xpt_print(periph->path,
+ "error %d on TUR in samount\n", error);
}
}
} else {
@@ -1982,10 +1922,9 @@
* read a full record.
*/
rblim = (struct scsi_read_block_limits_data *)
- malloc(8192, M_TEMP, M_WAITOK);
+ malloc(8192, M_SCSISA, M_NOWAIT);
if (rblim == NULL) {
- xpt_print_path(periph->path);
- printf("no memory for test read\n");
+ xpt_print(periph->path, "no memory for test read\n");
xpt_release_ccb(ccb);
error = ENOMEM;
goto exit;
@@ -2006,8 +1945,8 @@
softc->device_stats);
QFRLS(ccb);
if (error) {
- xpt_print_path(periph->path);
- printf("unable to rewind after test read\n");
+ xpt_print(periph->path,
+ "unable to rewind after test read\n");
xpt_release_ccb(ccb);
goto exit;
}
@@ -2171,8 +2110,8 @@
if ((softc->max_blk < softc->media_blksize) ||
(softc->min_blk > softc->media_blksize &&
softc->media_blksize)) {
- xpt_print_path(periph->path);
- printf("BLOCK LIMITS (%d..%d) could not match current "
+ xpt_print(periph->path,
+ "BLOCK LIMITS (%d..%d) could not match current "
"block settings (%d)- adjusting\n", softc->min_blk,
softc->max_blk, softc->media_blksize);
softc->max_blk = softc->min_blk =
@@ -2206,9 +2145,9 @@
error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
softc->media_blksize, 0, 0, SF_NO_PRINT);
if (error) {
- xpt_print_path(periph->path);
- printf("unable to set fixed blocksize to %d\n",
- softc->media_blksize);
+ xpt_print(periph->path,
+ "unable to set fixed blocksize to %d\n",
+ softc->media_blksize);
goto exit;
}
}
@@ -2233,8 +2172,8 @@
softc->last_media_blksize = 512;
goto tryagain;
}
- xpt_print_path(periph->path);
- printf("unable to set variable blocksize\n");
+ xpt_print(periph->path,
+ "unable to set variable blocksize\n");
goto exit;
}
}
@@ -2291,8 +2230,8 @@
if (error == 0) {
softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF;
} else {
- xpt_print_path(periph->path);
- printf("unable to set buffered mode\n");
+ xpt_print(periph->path,
+ "unable to set buffered mode\n");
}
error = 0; /* not an error */
}
@@ -2303,7 +2242,7 @@
}
exit:
if (rblim != NULL)
- free(rblim, M_TEMP);
+ free(rblim, M_SCSISA);
if (error != 0) {
softc->dsreg = MTIO_DSREG_NIL;
@@ -2534,8 +2473,8 @@
*/
if (error == 0 && (sense->flags & SSD_ILI)) {
if (info < 0) {
- xpt_print_path(csio->ccb_h.path);
- printf(toobig, csio->dxfer_len - info);
+ xpt_print(csio->ccb_h.path, toobig,
+ csio->dxfer_len - info);
csio->resid = csio->dxfer_len;
error = EIO;
} else {
@@ -2604,7 +2543,12 @@
mode_buffer_len += sizeof (sa_comp_t);
}
- mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK | M_ZERO);
+ /* XXX Fix M_NOWAIT */
+ mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
+ if (mode_buffer == NULL) {
+ xpt_release_ccb(ccb);
+ return (ENOMEM);
+ }
mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
@@ -2633,7 +2577,7 @@
goto retry;
}
softc->quirks |= SA_QUIRK_NOCOMP;
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSISA);
goto retry;
} else if (status == CAM_SCSI_STATUS_ERROR) {
/* Tell the user about the fatal error. */
@@ -2742,7 +2686,7 @@
sagetparamsexit:
xpt_release_ccb(ccb);
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSISA);
return (error);
}
@@ -2784,7 +2728,9 @@
softc = (struct sa_softc *)periph->softc;
- ccomp = malloc(sizeof (sa_comp_t), M_TEMP, M_WAITOK);
+ ccomp = malloc(sizeof (sa_comp_t), M_SCSISA, M_NOWAIT);
+ if (ccomp == NULL)
+ return (ENOMEM);
/*
* Since it doesn't make sense to set the number of blocks, or
@@ -2799,7 +2745,7 @@
¤t_calg, ccomp);
if (error != 0) {
- free(ccomp, M_TEMP);
+ free(ccomp, M_SCSISA);
return (error);
}
@@ -2807,7 +2753,11 @@
if (params_to_set & SA_PARAM_COMPRESSION)
mode_buffer_len += sizeof (sa_comp_t);
- mode_buffer = malloc(mode_buffer_len, M_TEMP, M_WAITOK | M_ZERO);
+ mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
+ if (mode_buffer == NULL) {
+ free(ccomp, M_SCSISA);
+ return (ENOMEM);
+ }
mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
@@ -2956,8 +2906,8 @@
* so turn off the set compression bit.
*/
params_to_set &= ~SA_PARAM_COMPRESSION;
- xpt_print_path(periph->path);
- printf("device does not seem to support compression\n");
+ xpt_print(periph->path,
+ "device does not seem to support compression\n");
/*
* If that was the only thing the user wanted us to set,
@@ -2965,7 +2915,7 @@
* 'operation not supported'.
*/
if (params_to_set == SA_PARAM_NONE) {
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSISA);
xpt_release_ccb(ccb);
return (ENODEV);
}
@@ -3050,7 +3000,7 @@
xpt_release_ccb(ccb);
if (ccomp != NULL)
- free(ccomp, M_TEMP);
+ free(ccomp, M_SCSISA);
if (params_to_set & SA_PARAM_COMPRESSION) {
if (error) {
@@ -3069,7 +3019,7 @@
}
}
- free(mode_buffer, M_TEMP);
+ free(mode_buffer, M_SCSISA);
return (error);
}
Index: scsi_cd.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_cd.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_cd.c -L sys/cam/scsi/scsi_cd.c -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_cd.c
+++ sys/cam/scsi/scsi_cd.c
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_cd.c,v 1.93.2.3 2006/07/26 07:48:51 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_cd.c,v 1.102 2007/07/21 18:07:45 kan Exp $");
#include "opt_cd.h"
@@ -70,6 +70,7 @@
#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 @@
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 @@
PERIPHDRIVER_DECLARE(cd, cddriver);
-
-static int num_changers;
-
#ifndef CHANGER_MIN_BUSY_SECONDS
#define CHANGER_MIN_BUSY_SECONDS 5
#endif
@@ -319,41 +318,32 @@
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;
+MALLOC_DEFINE(M_SCSICD, "scsi_cd", "scsi_cd buffers");
static void
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".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = cdasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, cdasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("cd: Failed to attach master async callback "
@@ -364,39 +354,23 @@
static void
cdoninvalidate(struct cam_periph *periph)
{
- int s;
struct cd_softc *softc;
- struct ccb_setasync csa;
softc = (struct cd_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = cdasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, cdasync, periph, periph->path);
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
@@ -408,28 +382,23 @@
camq_remove(&softc->changer->devq, softc->pinfo.index);
disk_gone(softc->disk);
- xpt_print_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
static void
cdcleanup(struct cam_periph *periph)
{
struct cd_softc *softc;
- int s;
softc = (struct cd_softc *)periph->softc;
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
if ((softc->flags & CD_FLAG_SCTX_INIT) != 0
&& sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
- xpt_print_path(periph->path);
- printf("can't remove sysctl context\n");
+ 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
@@ -459,8 +428,7 @@
* 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--;
@@ -481,27 +449,27 @@
* 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);
- xpt_print_path(periph->path);
- printf("removing changer entry\n");
- free(softc->changer, M_DEVBUF);
num_changers--;
+ mtx_unlock(&changerq_mtx);
+ xpt_print(periph->path, "removing changer entry\n");
+ free(softc->changer, M_DEVBUF);
}
+ cam_periph_unlock(periph);
disk_destroy(softc->disk);
+ cam_periph_lock(periph);
free(softc, M_DEVBUF);
- splx(s);
}
static void
@@ -548,10 +516,8 @@
{
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.
@@ -559,7 +525,6 @@
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:
@@ -576,8 +541,10 @@
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);
@@ -592,6 +559,7 @@
if (softc->sysctl_tree == NULL) {
printf("cdsysctlinit: unable to allocate sysctl tree\n");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
return;
}
@@ -605,6 +573,7 @@
"Minimum CDB size");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
}
/*
@@ -648,7 +617,6 @@
cdregister(struct cam_periph *periph, void *arg)
{
struct cd_softc *softc;
- struct ccb_setasync csa;
struct ccb_pathinq cpi;
struct ccb_getdev *cgd;
char tmpstr[80];
@@ -738,6 +706,7 @@
* 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,
@@ -751,20 +720,16 @@
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
* notified if this device goes away.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
- csa.callback = cdasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
+ cdasync, periph, periph->path);
/*
* If the target lun is greater than 0, we most likely have a CD
@@ -787,13 +752,11 @@
/* 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;
@@ -804,6 +767,7 @@
break;
}
}
+ mtx_unlock(&changerq_mtx);
/*
* If we found a matching entry, just add this device to
@@ -909,8 +873,6 @@
goto cdregisterexit;
}
- num_changers++;
-
nchanger->path_id = cgd->ccb_h.path_id;
nchanger->target_id = cgd->ccb_h.target_id;
@@ -919,8 +881,16 @@
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
@@ -982,9 +952,11 @@
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);
@@ -1000,7 +972,6 @@
struct cam_periph *periph;
struct cd_softc *softc;
int error;
- int s;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
@@ -1008,24 +979,28 @@
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
@@ -1034,11 +1009,11 @@
*/
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
@@ -1046,7 +1021,6 @@
{
struct cam_periph *periph;
struct cd_softc *softc;
- int error;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
@@ -1054,8 +1028,8 @@
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);
@@ -1069,8 +1043,9 @@
/*
* 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);
@@ -1081,9 +1056,6 @@
cdshorttimeout(void *arg)
{
struct cdchanger *changer;
- int s;
-
- s = splsoftcam();
changer = (struct cdchanger *)arg;
@@ -1099,8 +1071,6 @@
changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(changer);
}
-
- splx(s);
}
/*
@@ -1110,9 +1080,6 @@
cdschedule(struct cam_periph *periph, int priority)
{
struct cd_softc *softc;
- int s;
-
- s = splsoftcam();
softc = (struct cd_softc *)periph->softc;
@@ -1151,9 +1118,6 @@
} else if ((softc->flags & CD_FLAG_ACTIVE)
&& ((softc->flags & CD_FLAG_SCHED_ON_COMP) == 0))
xpt_schedule(periph, priority);
-
- splx(s);
-
}
static void
@@ -1162,9 +1126,6 @@
struct cd_softc *softc;
struct cdchanger *changer;
int called_from_timeout;
- int s;
-
- s = splsoftcam();
changer = (struct cdchanger *)arg;
@@ -1184,7 +1145,6 @@
/* nothing to do if the queue is empty */
if (changer->devq.entries <= 0) {
- splx(s);
return;
}
@@ -1194,29 +1154,28 @@
*/
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.
@@ -1246,12 +1205,12 @@
* 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;
}
@@ -1261,17 +1220,12 @@
* 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;
@@ -1317,18 +1271,18 @@
* 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 "
@@ -1341,7 +1295,6 @@
changer->flags &= ~CHANGER_NEED_TIMEOUT;
}
- splx(s);
}
static int
@@ -1370,14 +1323,10 @@
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.
@@ -1400,9 +1349,9 @@
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));
}
@@ -1418,7 +1367,6 @@
{
struct cam_periph *periph;
struct cd_softc *softc;
- int s;
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
if (periph == NULL) {
@@ -1426,22 +1374,16 @@
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;
}
@@ -1455,7 +1397,7 @@
error = cdcheckmedia(periph);
if (error != 0) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, error);
return;
}
@@ -1466,8 +1408,6 @@
*/
bioq_disksort(&softc->bio_queue, bp);
- splx(s);
-
/*
* Schedule ourselves for performing the work. We do things
* differently for changers.
@@ -1477,6 +1417,7 @@
else
cdschedule(periph, /* priority */ 1);
+ cam_periph_unlock(periph);
return;
}
@@ -1487,7 +1428,6 @@
struct bio *bp;
struct ccb_scsiio *csio;
struct scsi_read_capacity_data *rcap;
- int s;
softc = (struct cd_softc *)periph->softc;
@@ -1496,9 +1436,6 @@
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;
@@ -1506,10 +1443,8 @@
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);
@@ -1533,15 +1468,9 @@
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) {
@@ -1551,7 +1480,6 @@
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1565,11 +1493,11 @@
{
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
- M_TEMP,
+ M_SCSICD,
M_NOWAIT);
if (rcap == NULL) {
- xpt_print_path(periph->path);
- printf("cdstart: Couldn't malloc read_capacity data\n");
+ xpt_print(periph->path,
+ "cdstart: Couldn't malloc read_capacity data\n");
/* cd_free_periph??? */
break;
}
@@ -1605,7 +1533,6 @@
{
struct bio *bp;
int error;
- int oldspl;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
error = 0;
@@ -1629,13 +1556,9 @@
}
if (error != 0) {
- int s;
-
- xpt_print_path(periph->path);
- printf("cddone: got error %#x back\n", error);
- s = splbio();
+ xpt_print(periph->path,
+ "cddone: got error %#x back\n", error);
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
bp->bio_resid = bp->bio_bcount;
bp->bio_error = error;
bp->bio_flags |= BIO_ERROR;
@@ -1658,14 +1581,8 @@
}
}
- /*
- * 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);
@@ -1813,14 +1730,12 @@
scsi_sense_print(
&done_ccb->csio);
else {
- xpt_print_path(periph->path);
- printf("got CAM status %#x\n",
- done_ccb->ccb_h.status);
+ xpt_print(periph->path,
+ "got CAM status %#x\n",
+ done_ccb->ccb_h.status);
}
- xpt_print_path(periph->path);
- printf("fatal error, failed"
- " to attach to device\n");
-
+ xpt_print(periph->path, "fatal error, "
+ "failed to attach to device\n");
/*
* Invalidate this peripheral.
*/
@@ -1837,7 +1752,7 @@
}
}
}
- free(rdcap, M_TEMP);
+ free(rdcap, M_SCSICD);
if (announce_buf[0] != '\0') {
xpt_announce_periph(periph, announce_buf);
if (softc->flags & CD_FLAG_CHANGER)
@@ -1858,7 +1773,7 @@
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case CD_CCB_WAITING:
@@ -1911,12 +1826,13 @@
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;
@@ -1924,10 +1840,12 @@
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.
@@ -1943,10 +1861,16 @@
&& (IOCGROUP(cmd) == 'c')) {
error = cdcheckmedia(periph);
if (error != 0) {
+ cam_periph_unhold(periph);
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);
nocopyout = 0;
switch (cmd) {
@@ -1959,15 +1883,17 @@
union cd_pages *page;
params.alloc_len = sizeof(union cd_mode_data_6_10);
- params.mode_buf = malloc(params.alloc_len, M_TEMP,
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOCPLAYTRACKS\n"));
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -1975,9 +1901,11 @@
page->audio.flags &= ~CD_PA_SOTC;
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
- if (error)
+ free(params.mode_buf, M_SCSICD);
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
/*
* This was originally implemented with the PLAY
@@ -2039,6 +1967,7 @@
args->end_track,
args->end_index);
}
+ cam_periph_unlock(periph);
}
break;
case CDIOCPLAYMSF:
@@ -2049,15 +1978,17 @@
union cd_pages *page;
params.alloc_len = sizeof(union cd_mode_data_6_10);
- params.mode_buf = malloc(params.alloc_len, M_TEMP,
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOCPLAYMSF\n"));
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2065,9 +1996,11 @@
page->audio.flags &= ~CD_PA_SOTC;
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
- if (error)
+ free(params.mode_buf, M_SCSICD);
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
error = cdplaymsf(periph,
args->start_m,
args->start_s,
@@ -2075,6 +2008,7 @@
args->end_m,
args->end_s,
args->end_f);
+ cam_periph_unlock(periph);
}
break;
case CDIOCPLAYBLOCKS:
@@ -2084,16 +2018,19 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2101,10 +2038,13 @@
page->audio.flags &= ~CD_PA_SOTC;
page->audio.flags |= CD_PA_IMMED;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
- if (error)
+ free(params.mode_buf, M_SCSICD);
+ if (error) {
+ cam_periph_unlock(periph);
break;
+ }
error = cdplay(periph, args->blk, args->len);
+ cam_periph_unlock(periph);
}
break;
case CDIOCREADSUBCHANNEL_SYSSPACE:
@@ -2117,12 +2057,13 @@
struct cd_sub_channel_info *data;
u_int32_t len = args->data_len;
+ data = malloc(sizeof(struct cd_sub_channel_info),
+ M_SCSICD, M_WAITOK);
+
+ cam_periph_lock(periph);
CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
("trying to do CDIOCREADSUBCHANNEL\n"));
- data = malloc(sizeof(struct cd_sub_channel_info),
- M_TEMP, M_WAITOK);
-
if ((len > sizeof(struct cd_sub_channel_info)) ||
(len < sizeof(struct cd_sub_channel_header))) {
printf(
@@ -2130,7 +2071,8 @@
"cdioreadsubchannel: error, len=%d\n",
len);
error = EINVAL;
- free(data, M_TEMP);
+ free(data, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
@@ -2141,7 +2083,8 @@
args->data_format, args->track, data, len);
if (error) {
- free(data, M_TEMP);
+ free(data, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
if (softc->quirks & CD_Q_BCD_TRACKS)
@@ -2150,6 +2093,7 @@
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;
@@ -2157,7 +2101,7 @@
} else {
bcopy(data, args->data, len);
}
- free(data, M_TEMP);
+ free(data, M_SCSICD);
}
break;
@@ -2165,15 +2109,18 @@
{
struct ioc_toc_header *th;
+ th = malloc(sizeof(struct ioc_toc_header), M_SCSICD,
+ 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);
+ free(th, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
if (softc->quirks & CD_Q_BCD_TRACKS) {
@@ -2186,7 +2133,8 @@
}
th->len = ntohs(th->len);
bcopy(th, addr, sizeof(*th));
- free(th, M_TEMP);
+ free(th, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOREADTOCENTRYS:
@@ -2199,12 +2147,13 @@
u_int32_t len, readlen, idx, num;
u_int32_t starting_track = te->starting_track;
+ data = malloc(sizeof(*data), M_SCSICD, M_WAITOK);
+ lead = malloc(sizeof(*lead), M_SCSICD, M_WAITOK);
+
+ cam_periph_lock(periph);
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);
-
if (te->data_len < sizeof(struct cd_toc_entry)
|| (te->data_len % sizeof(struct cd_toc_entry)) != 0
|| (te->address_format != CD_MSF_FORMAT
@@ -2212,8 +2161,9 @@
error = EINVAL;
printf("scsi_cd: error in readtocentries, "
"returning EINVAL\n");
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
@@ -2221,8 +2171,9 @@
error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
sizeof (*th), /*sense_flags*/0);
if (error) {
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
@@ -2243,8 +2194,9 @@
starting_track > th->ending_track + 1) {
printf("scsi_cd: error in readtocentries, "
"returning EINVAL\n");
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
error = EINVAL;
break;
}
@@ -2264,8 +2216,9 @@
printf("scsi_cd: error in readtocentries, "
"returning EINVAL\n");
error = EINVAL;
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
num = len / sizeof(struct cd_toc_entry);
@@ -2277,8 +2230,9 @@
readlen + sizeof (*th),
/*sense_flags*/0);
if (error) {
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
}
@@ -2293,8 +2247,9 @@
sizeof(*lead),
/*sense_flags*/0);
if (error) {
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
data->entries[idx - starting_track] =
@@ -2307,9 +2262,10 @@
}
}
+ cam_periph_unlock(periph);
error = copyout(data->entries, te->data, len);
- free(data, M_TEMP);
- free(lead, M_TEMP);
+ free(data, M_SCSICD);
+ free(lead, M_SCSICD);
}
break;
case CDIOREADTOCENTRY:
@@ -2320,17 +2276,19 @@
struct ioc_toc_header *th;
u_int32_t track;
+ data = malloc(sizeof(*data), M_SCSICD, 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);
+ free(data, M_SCSICD);
error = EINVAL;
+ cam_periph_unlock(periph);
break;
}
@@ -2338,7 +2296,8 @@
error = cdreadtoc(periph, 0, 0, (u_int8_t *)th,
sizeof (*th), /*sense_flags*/0);
if (error) {
- free(data, M_TEMP);
+ free(data, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
@@ -2359,8 +2318,9 @@
track > th->ending_track + 1) {
printf("error in readtocentry, "
" returning EINVAL\n");
- free(data, M_TEMP);
+ free(data, M_SCSICD);
error = EINVAL;
+ cam_periph_unlock(periph);
break;
}
@@ -2368,7 +2328,8 @@
(u_int8_t *)data, sizeof(*data),
/*sense_flags*/0);
if (error) {
- free(data, M_TEMP);
+ free(data, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
@@ -2376,7 +2337,8 @@
data->entry.track = bcd2bin(data->entry.track);
bcopy(&data->entry, &te->entry,
sizeof(struct cd_toc_entry));
- free(data, M_TEMP);
+ free(data, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETPATCH:
@@ -2385,15 +2347,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2405,7 +2370,8 @@
page->audio.port[2].channels = arg->patch[2];
page->audio.port[3].channels = arg->patch[3];
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCGETVOL:
@@ -2414,15 +2380,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2433,7 +2402,8 @@
page->audio.port[RIGHT_PORT].volume;
arg->vol[2] = page->audio.port[2].volume;
arg->vol[3] = page->audio.port[3].volume;
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETVOL:
@@ -2442,15 +2412,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2464,7 +2437,8 @@
page->audio.port[2].volume = arg->vol[2];
page->audio.port[3].volume = arg->vol[3];
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
+ free(params.mode_buf, M_SCSICD);
}
break;
case CDIOCSETMONO:
@@ -2472,15 +2446,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2492,7 +2469,8 @@
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ cam_periph_unlock(periph);
+ free(params.mode_buf, M_SCSICD);
}
break;
case CDIOCSETSTEREO:
@@ -2500,15 +2478,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2520,7 +2501,8 @@
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETMUTE:
@@ -2528,15 +2510,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(¶ms, M_TEMP);
+ free(¶ms, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2546,7 +2531,8 @@
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETLEFT:
@@ -2554,16 +2540,18 @@
struct cd_mode_params params;
union cd_pages *page;
+ params.alloc_len = sizeof(union cd_mode_data_6_10);
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
+ M_WAITOK | M_ZERO);
+
+ cam_periph_lock(periph);
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);
-
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2573,7 +2561,8 @@
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
}
break;
case CDIOCSETRIGHT:
@@ -2581,16 +2570,18 @@
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,
+ params.mode_buf = malloc(params.alloc_len, M_SCSICD,
M_WAITOK | M_ZERO);
+ cam_periph_lock(periph);
+ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
+ ("trying to do CDIOCSETRIGHT\n"));
+
error = cdgetmode(periph, ¶ms, AUDIO_PAGE);
if (error) {
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ cam_periph_unlock(periph);
break;
}
page = cdgetpage(¶ms);
@@ -2600,32 +2591,49 @@
page->audio.port[2].channels = 0;
page->audio.port[3].channels = 0;
error = cdsetmode(periph, ¶ms);
- free(params.mode_buf, M_TEMP);
+ free(params.mode_buf, M_SCSICD);
+ 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); */
@@ -2640,10 +2648,14 @@
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: {
@@ -2651,10 +2663,12 @@
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: {
@@ -2662,21 +2676,27 @@
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);
}
@@ -2875,8 +2895,11 @@
ccb = cdgetccb(periph, /* priority */ 1);
+ /* XXX Should be M_WAITOK */
rcap_buf = malloc(sizeof(struct scsi_read_capacity_data),
- M_TEMP, M_WAITOK);
+ M_SCSICD, M_NOWAIT);
+ if (rcap_buf == NULL)
+ return (ENOMEM);
scsi_read_capacity(&ccb->csio,
/*retries*/ 1,
@@ -2904,7 +2927,7 @@
if (softc->params.blksize > 2048 && softc->params.blksize <= 2352)
softc->params.blksize = 2048;
- free(rcap_buf, M_TEMP);
+ free(rcap_buf, M_SCSICD);
*size = softc->params.disksize;
return (error);
@@ -2955,16 +2978,16 @@
* cdsetmode()!
*/
if (found == 0) {
- xpt_print_path(periph->path);
- printf("mode buffer not found in mode queue!\n");
+ xpt_print(periph->path,
+ "mode buffer not found in mode queue!\n");
return (0);
}
params->cdb_size = 10;
softc->minimum_command_size = 10;
- xpt_print_path(ccb->ccb_h.path);
- printf("%s(6) failed, increasing minimum CDB size to 10 bytes\n",
- (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT");
+ xpt_print(ccb->ccb_h.path,
+ "%s(6) failed, increasing minimum CDB size to 10 bytes\n",
+ (cdb[0] == MODE_SENSE_6) ? "MODE_SENSE" : "MODE_SELECT");
if (cdb[0] == MODE_SENSE_6) {
struct scsi_mode_sense_10 ms10;
@@ -3296,10 +3319,9 @@
* the data length incorrectly.
*/
if (data_len > data->alloc_len) {
- xpt_print_path(periph->path);
- printf("allocated modepage %d length %d < returned "
- "length %d\n", page, data->alloc_len, data_len);
-
+ xpt_print(periph->path, "allocated modepage %d length "
+ "%d < returned length %d\n", page, data->alloc_len,
+ data_len);
error = ENOSPC;
}
}
@@ -3757,9 +3779,8 @@
goto bailout;
if (ccb->csio.resid != 0) {
- xpt_print_path(periph->path);
- printf("warning, residual for report key command is %d\n",
- ccb->csio.resid);
+ xpt_print(periph->path, "warning, residual for report key "
+ "command is %d\n", ccb->csio.resid);
}
switch(authinfo->format) {
Index: scsi_target.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_target.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_target.c -L sys/cam/scsi/scsi_target.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_target.c
+++ sys/cam/scsi/scsi_target.c
@@ -28,7 +28,8 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_target.c,v 1.67.2.1 2005/08/13 21:24:15 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_target.c,v 1.73 2007/04/15 08:49:11 scottl Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
@@ -40,11 +41,13 @@
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/devicestat.h>
+#include <sys/proc.h>
#include <cam/cam.h>
#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 */
@@ -89,7 +92,6 @@
targ_state state;
struct selinfo read_select;
struct devstat device_stats;
- struct mtx mtx;
};
static d_open_t targopen;
@@ -157,27 +159,24 @@
};
PERIPHDRIVER_DECLARE(targ, targdriver);
-static struct mtx targ_mtx;
-#define TARG_LOCK(softc) mtx_lock(&(softc)->mtx)
-#define TARG_UNLOCK(softc) mtx_unlock(&(softc)->mtx)
-
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)
{
struct targ_softc *softc;
- mtx_lock(&targ_mtx);
if (dev->si_drv1 != 0) {
- mtx_unlock(&targ_mtx);
return (EBUSY);
}
/* Mark device busy before any potentially blocking operations */
dev->si_drv1 = (void *)~0;
- mtx_unlock(&targ_mtx);
/* Create the targ device, allocate its softc, initialize it */
if ((dev->si_flags & SI_NAMED) == 0) {
@@ -190,13 +189,12 @@
softc->state = TARG_STATE_OPENED;
softc->periph = NULL;
softc->path = NULL;
- mtx_init(&softc->mtx, devtoname(dev), "targ cdev", MTX_DEF);
TAILQ_INIT(&softc->pending_ccb_queue);
TAILQ_INIT(&softc->work_queue);
TAILQ_INIT(&softc->abort_queue);
TAILQ_INIT(&softc->user_ccb_queue);
- knlist_init(&softc->read_select.si_note, &softc->mtx, NULL, NULL, NULL);
+ knlist_init(&softc->read_select.si_note, NULL, NULL, NULL, NULL);
return (0);
}
@@ -206,26 +204,37 @@
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;
- TARG_LOCK(softc);
+ 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;
- mtx_lock(&targ_mtx);
if (softc->periph != NULL) {
cam_periph_invalidate(softc->periph);
softc->periph = NULL;
}
- mtx_unlock(&targ_mtx);
- TARG_UNLOCK(softc);
- mtx_destroy(&softc->mtx);
destroy_dev(dev);
FREE(softc, M_TARG);
- } else {
- TARG_UNLOCK(softc);
}
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+
return (error);
}
@@ -243,51 +252,56 @@
{
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;
}
- TARG_LOCK(softc);
+ sim = xpt_path_sim(path);
+ mtx_lock(sim->mtx);
status = targenable(softc, path, new_lun->grp6_len,
new_lun->grp7_len);
- TARG_UNLOCK(softc);
xpt_free_path(path);
+ mtx_unlock(sim->mtx);
break;
}
case TARGIOCDISABLE:
- TARG_LOCK(softc);
+ if (softc->periph == NULL) {
+ status = CAM_DEV_NOT_THERE;
+ break;
+ }
+ cam_periph_lock(softc->periph);
status = targdisable(softc);
- TARG_UNLOCK(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 */
- TARG_LOCK(softc);
- if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
- status = CAM_DEV_NOT_THERE;
- TARG_UNLOCK(softc);
- break;
- }
xpt_action((union ccb *)&cdbg);
- TARG_UNLOCK(softc);
+ cam_periph_unlock(softc->periph);
status = cdbg.ccb_h.status & CAM_STATUS_MASK;
#else
status = CAM_FUNC_NOTAVAIL;
@@ -315,15 +329,15 @@
revents = poll_events & (POLLOUT | POLLWRNORM);
if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
/* Poll for read() depends on user and abort queues. */
- TARG_LOCK(softc);
+ 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);
- TARG_UNLOCK(softc);
}
return (revents);
@@ -358,8 +372,10 @@
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);
}
@@ -380,9 +396,8 @@
xpt_action((union ccb *)&en_ccb);
status = en_ccb.ccb_h.status & CAM_STATUS_MASK;
if (status != CAM_REQ_CMP) {
- xpt_print_path(path);
- printf("%sable lun CCB rejected, status %#x\n",
- enable ? "en" : "dis", status);
+ xpt_print(path, "%sable lun CCB rejected, status %#x\n",
+ enable ? "en" : "dis", status);
}
return (status);
}
@@ -415,7 +430,6 @@
}
/* Destroy any periph on our path if it is disabled */
- mtx_lock(&targ_mtx);
periph = cam_periph_find(path, "targ");
if (periph != NULL) {
struct targ_softc *del_softc;
@@ -427,7 +441,6 @@
} else {
printf("Requested path still in use by targ%d\n",
periph->unit_number);
- mtx_unlock(&targ_mtx);
status = CAM_LUN_ALRDY_ENA;
goto enable_fail;
}
@@ -436,7 +449,6 @@
/* Create a periph instance attached to this path */
status = cam_periph_alloc(targctor, NULL, targdtor, targstart,
"targ", CAM_PERIPH_BIO, path, targasync, 0, softc);
- mtx_unlock(&targ_mtx);
if (status != CAM_REQ_CMP) {
printf("cam_periph_alloc failed, status %#x\n", status);
goto enable_fail;
@@ -559,6 +571,7 @@
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;
@@ -566,13 +579,13 @@
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("Sent ATIO/INOT (%p)\n", user_ccb));
xpt_action(ccb);
- TARG_LOCK(softc);
TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
&ccb->ccb_h,
periph_links.tqe);
- TARG_UNLOCK(softc);
+ 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",
@@ -581,10 +594,8 @@
descr->user_ccb = user_ccb;
descr->priority = priority;
descr->func_code = func_code;
- TARG_LOCK(softc);
TAILQ_INSERT_TAIL(&softc->work_queue,
descr, tqe);
- TARG_UNLOCK(softc);
xpt_schedule(softc->periph, priority);
} else {
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
@@ -600,6 +611,7 @@
targsendccb(softc, ccb, descr);
targreturnccb(softc, ccb);
}
+ cam_periph_unlock(softc->periph);
break;
}
write_len += sizeof(user_ccb);
@@ -629,29 +641,24 @@
softc = (struct targ_softc *)periph->softc;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targstart %p\n", start_ccb));
- TARG_LOCK(softc);
descr = TAILQ_FIRST(&softc->work_queue);
if (descr == NULL) {
- TARG_UNLOCK(softc);
xpt_release_ccb(start_ccb);
} else {
TAILQ_REMOVE(&softc->work_queue, descr, tqe);
next_descr = TAILQ_FIRST(&softc->work_queue);
- TARG_UNLOCK(softc);
/* Initiate a transaction using the descr and supplied CCB */
error = targusermerge(softc, descr, start_ccb);
if (error == 0)
error = targsendccb(softc, start_ccb, descr);
if (error != 0) {
- xpt_print_path(periph->path);
- printf("targsendccb failed, err %d\n", error);
+ xpt_print(periph->path,
+ "targsendccb failed, err %d\n", error);
xpt_release_ccb(start_ccb);
suword(&descr->user_ccb->ccb_h.status,
CAM_REQ_CMP_ERR);
- TARG_LOCK(softc);
TAILQ_INSERT_TAIL(&softc->abort_queue, descr, tqe);
- TARG_UNLOCK(softc);
notify_user(softc);
}
@@ -694,7 +701,6 @@
struct ccb_hdr *ccb_h;
cab = (struct ccb_abort *)ccb;
- TARG_LOCK(softc);
TAILQ_FOREACH(ccb_h, &softc->pending_ccb_queue,
periph_links.tqe) {
struct targ_cmd_descr *ab_descr;
@@ -708,7 +714,6 @@
break;
}
}
- TARG_UNLOCK(softc);
/* CCB not found, set appropriate status */
if (ccb_h == NULL) {
k_ccbh->status = CAM_PATH_INVALID;
@@ -776,10 +781,8 @@
*/
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("sendccb %p\n", ccb));
if (XPT_FC_IS_QUEUED(ccb)) {
- TARG_LOCK(softc);
TAILQ_INSERT_TAIL(&softc->pending_ccb_queue, ccb_h,
periph_links.tqe);
- TARG_UNLOCK(softc);
}
xpt_action(ccb);
@@ -795,7 +798,6 @@
CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("targdone %p\n", done_ccb));
softc = (struct targ_softc *)periph->softc;
- TARG_LOCK(softc);
TAILQ_REMOVE(&softc->pending_ccb_queue, &done_ccb->ccb_h,
periph_links.tqe);
status = done_ccb->ccb_h.status & CAM_STATUS_MASK;
@@ -803,7 +805,6 @@
/* If we're no longer enabled, throw away CCB */
if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
targfreeccb(softc, done_ccb);
- TARG_UNLOCK(softc);
return;
}
/* abort_all_pending() waits for pending queue to be empty */
@@ -817,7 +818,6 @@
case XPT_CONT_TARGET_IO:
TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,
periph_links.tqe);
- TARG_UNLOCK(softc);
notify_user(softc);
break;
default:
@@ -847,25 +847,24 @@
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
/* If no data is available, wait or return immediately */
- TARG_LOCK(softc);
+ 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 = msleep(user_queue, &softc->mtx,
- PRIBIO | PCATCH, "targrd", 0);
+ error = msleep(user_queue, softc->periph->sim->mtx,
+ PRIBIO | PCATCH, "targrd", 0);
ccb_h = TAILQ_FIRST(user_queue);
user_descr = TAILQ_FIRST(abort_queue);
if (error != 0) {
if (error == ERESTART) {
continue;
} else {
- TARG_UNLOCK(softc);
goto read_fail;
}
}
} else {
- TARG_UNLOCK(softc);
+ cam_periph_unlock(softc->periph);
return (EAGAIN);
}
}
@@ -877,7 +876,6 @@
if (uio->uio_resid < sizeof(user_ccb))
break;
TAILQ_REMOVE(user_queue, ccb_h, periph_links.tqe);
- TARG_UNLOCK(softc);
descr = (struct targ_cmd_descr *)ccb_h->targ_descr;
user_ccb = descr->user_ccb;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
@@ -885,12 +883,13 @@
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);
- TARG_LOCK(softc);
ccb_h = TAILQ_FIRST(user_queue);
}
@@ -899,21 +898,20 @@
if (uio->uio_resid < sizeof(user_ccb))
break;
TAILQ_REMOVE(abort_queue, user_descr, tqe);
- TARG_UNLOCK(softc);
user_ccb = user_descr->user_ccb;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("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);
- TARG_LOCK(softc);
user_descr = TAILQ_FIRST(abort_queue);
}
- TARG_UNLOCK(softc);
/*
* If we've successfully read some amount of data, don't report an
@@ -924,6 +922,7 @@
error = ENOSPC;
read_fail:
+ cam_periph_unlock(softc->periph);
return (error);
}
@@ -951,9 +950,8 @@
cam_periph_unmapmem(ccb, &descr->mapinfo);
error = copyout(&ccb->ccb_h + 1, u_ccbh + 1, ccb_len);
if (error != 0) {
- xpt_print_path(softc->path);
- printf("targreturnccb - CCB copyout failed (%d)\n",
- error);
+ xpt_print(softc->path,
+ "targreturnccb - CCB copyout failed (%d)\n", error);
}
/* Free CCB or send back to devq. */
targfreeccb(softc, ccb);
@@ -1020,7 +1018,6 @@
static void
targinit(void)
{
- mtx_init(&targ_mtx, "targ global", NULL, MTX_DEF);
EVENTHANDLER_REGISTER(dev_clone, targclone, 0, 1000);
}
@@ -1054,6 +1051,7 @@
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"));
@@ -1078,15 +1076,16 @@
cab.abort_ccb = (union ccb *)ccb_h;
xpt_action((union ccb *)&cab);
if (cab.ccb_h.status != CAM_REQ_CMP) {
- xpt_print_path(cab.ccb_h.path);
- printf("Unable to abort CCB, status %#x\n",
- cab.ccb_h.status);
+ xpt_print(cab.ccb_h.path,
+ "Unable to abort CCB, status %#x\n",
+ cab.ccb_h.status);
}
}
/* If we aborted at least one pending CCB ok, wait for it. */
if (cab.ccb_h.status == CAM_REQ_CMP) {
- msleep(&softc->pending_ccb_queue, &softc->mtx,
+ sim = xpt_path_sim(softc->path);
+ msleep(&softc->pending_ccb_queue, sim->mtx,
PRIBIO | PCATCH, "tgabrt", 0);
}
@@ -1105,7 +1104,7 @@
* blocking read().
*/
selwakeuppri(&softc->read_select, PRIBIO);
- KNOTE_LOCKED(&softc->read_select.si_note, 0);
+ KNOTE_UNLOCKED(&softc->read_select.si_note, 0);
wakeup(&softc->user_ccb_queue);
}
Index: scsi_all.h
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_all.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_all.h -L sys/cam/scsi/scsi_all.h -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_all.h
+++ sys/cam/scsi/scsi_all.h
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian at tfs.com) Sept 1992
*
- * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.24.2.2 2006/09/09 07:21:18 ken Exp $
+ * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.28.2.1 2007/11/15 16:27:59 scottl Exp $
*/
/*
@@ -170,8 +170,11 @@
#define SMS_PAGE_CODE 0x3F
#define SMS_VENDOR_SPECIFIC_PAGE 0x00
#define SMS_DISCONNECT_RECONNECT_PAGE 0x02
+#define SMS_CACHE_PAGE 0x08
#define SMS_PERIPHERAL_DEVICE_PAGE 0x09
#define SMS_CONTROL_MODE_PAGE 0x0A
+#define SMS_PROTO_SPECIFIC_PAGE 0x19
+#define SMS_INFO_EXCEPTIONS_PAGE 0x1C
#define SMS_ALL_PAGES_PAGE 0x3F
#define SMS_PAGE_CTRL_MASK 0xC0
#define SMS_PAGE_CTRL_CURRENT 0x00
@@ -257,6 +260,8 @@
#define SLS_ERROR_VERIFY_PAGE 0x05
#define SLS_ERROR_NONMEDIUM_PAGE 0x06
#define SLS_ERROR_LASTN_PAGE 0x07
+#define SLS_SELF_TEST_PAGE 0x10
+#define SLS_IE_PAGE 0x2f
#define SLS_PAGE_CTRL_MASK 0xC0
#define SLS_PAGE_CTRL_THRESHOLD 0x00
#define SLS_PAGE_CTRL_CUMULATIVE 0x40
@@ -329,6 +334,55 @@
u_int8_t aen_holdoff_period[2];
};
+struct scsi_cache_page {
+ u_int8_t page_code;
+#define SCHP_PAGE_SAVABLE 0x80 /* Page is savable */
+ u_int8_t page_length;
+ u_int8_t cache_flags;
+#define SCHP_FLAGS_WCE 0x04 /* Write Cache Enable */
+#define SCHP_FLAGS_MF 0x02 /* Multiplication factor */
+#define SCHP_FLAGS_RCD 0x01 /* Read Cache Disable */
+ u_int8_t rw_cache_policy;
+ u_int8_t dis_prefetch[2];
+ u_int8_t min_prefetch[2];
+ u_int8_t max_prefetch[2];
+ u_int8_t max_prefetch_ceil[2];
+};
+
+struct scsi_info_exceptions_page {
+ u_int8_t page_code;
+#define SIEP_PAGE_SAVABLE 0x80 /* Page is savable */
+ u_int8_t page_length;
+ u_int8_t info_flags;
+#define SIEP_FLAGS_PERF 0x80
+#define SIEP_FLAGS_EBF 0x20
+#define SIEP_FLAGS_EWASC 0x10
+#define SIEP_FLAGS_DEXCPT 0x08
+#define SIEP_FLAGS_TEST 0x04
+#define SIEP_FLAGS_EBACKERR 0x02
+#define SIEP_FLAGS_LOGERR 0x01
+ u_int8_t mrie;
+ u_int8_t interval_timer[4];
+ u_int8_t report_count[4];
+};
+
+struct scsi_proto_specific_page {
+ u_int8_t page_code;
+#define SPSP_PAGE_SAVABLE 0x80 /* Page is savable */
+ u_int8_t page_length;
+ u_int8_t protocol;
+#define SPSP_PROTO_FC 0x00
+#define SPSP_PROTO_SPI 0x01
+#define SPSP_PROTO_SSA 0x02
+#define SPSP_PROTO_1394 0x03
+#define SPSP_PROTO_RDMA 0x04
+#define SPSP_PROTO_ISCSI 0x05
+#define SPSP_PROTO_SAS 0x06
+#define SPSP_PROTO_ADT 0x07
+#define SPSP_PROTO_ATA 0x08
+#define SPSP_PROTO_NONE 0x0f
+};
+
struct scsi_reserve
{
u_int8_t opcode;
@@ -468,6 +522,47 @@
u_int8_t control;
};
+struct ata_pass_12 {
+ u_int8_t opcode;
+ u_int8_t protocol;
+#define AP_MULTI 0xe0
+ u_int8_t flags;
+#define AP_T_LEN 0x03
+#define AP_BB 0x04
+#define AP_T_DIR 0x08
+#define AP_CK_COND 0x20
+#define AP_OFFLINE 0x60
+ u_int8_t features;
+ u_int8_t sector_count;
+ u_int8_t lba_low;
+ u_int8_t lba_mid;
+ u_int8_t lba_high;
+ u_int8_t device;
+ u_int8_t command;
+ u_int8_t reserved;
+ u_int8_t control;
+};
+
+struct ata_pass_16 {
+ u_int8_t opcode;
+ u_int8_t protocol;
+#define AP_EXTEND 0x01
+ u_int8_t flags;
+ u_int8_t features_ext;
+ u_int8_t features;
+ u_int8_t sector_count_ext;
+ u_int8_t sector_count;
+ u_int8_t lba_low_ext;
+ u_int8_t lba_low;
+ u_int8_t lba_mid_ext;
+ u_int8_t lba_mid;
+ u_int8_t lba_high_ext;
+ u_int8_t lba_high;
+ u_int8_t device;
+ u_int8_t command;
+ u_int8_t control;
+};
+
#define SC_SCSI_1 0x01
#define SC_SCSI_2 0x03
@@ -494,6 +589,7 @@
#define WRITE_10 0x2a
#define POSITION_TO_ELEMENT 0x2b
#define SYNCHRONIZE_CACHE 0x35
+#define READ_DEFECT_DATA_10 0x37
#define WRITE_BUFFER 0x3b
#define READ_BUFFER 0x3c
#define CHANGE_DEFINITION 0x40
@@ -501,10 +597,12 @@
#define LOG_SENSE 0x4d
#define MODE_SELECT_10 0x55
#define MODE_SENSE_10 0x5A
+#define ATA_PASS_16 0x85
#define READ_16 0x88
#define WRITE_16 0x8a
#define SERVICE_ACTION_IN 0x9e
#define REPORT_LUNS 0xA0
+#define ATA_PASS_12 0xa1
#define MOVE_MEDIUM 0xa5
#define READ_12 0xa8
#define WRITE_12 0xaa
@@ -599,6 +697,9 @@
#define SID_AENC 0x80
#define SID_TrmIOP 0x40
u_int8_t additional_length;
+#define SID_ADDITIONAL_LENGTH(iqd) \
+ ((iqd)->additional_length + \
+ offsetof(struct scsi_inquiry_data, additional_length) + 1)
u_int8_t reserved;
u_int8_t spc2_flags;
#define SPC2_SID_MChngr 0x08
@@ -611,7 +712,6 @@
(((iqd)->flags & SID_CmdQue) && !((iqd)->spc2_flags & SPC2_SID_BQueue)) || \
(!((iqd)->flags & SID_CmdQue) && ((iqd)->spc2_flags & SPC2_SID_BQueue)))
-
u_int8_t flags;
#define SID_SftRe 0x01
#define SID_CmdQue 0x02
@@ -661,6 +761,17 @@
u_int8_t vendor_specific1[SID_VENDOR_SPECIFIC_1_SIZE];
};
+struct scsi_vpd_supported_page_list
+{
+ u_int8_t device;
+ u_int8_t page_code;
+#define SVPD_SUPPORTED_PAGE_LIST 0x00
+ u_int8_t reserved;
+ u_int8_t length; /* number of VPD entries */
+#define SVPD_SUPPORTED_PAGES_SIZE 251
+ u_int8_t list[SVPD_SUPPORTED_PAGES_SIZE];
+};
+
struct scsi_vpd_unit_serial_number
{
u_int8_t device;
Index: scsi_da.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_da.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/cam/scsi/scsi_da.c -L sys/cam/scsi/scsi_da.c -u -r1.2 -r1.3
--- sys/cam/scsi/scsi_da.c
+++ sys/cam/scsi/scsi_da.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_da.c,v 1.180.2.8 2006/07/26 07:48:51 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_da.c,v 1.224 2007/07/01 17:42:07 imp Exp $");
#include <sys/param.h>
@@ -37,20 +37,15 @@
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
-#endif /* _KERNEL */
-
-#include <sys/devicestat.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/conf.h>
+#include <sys/devicestat.h>
#include <sys/eventhandler.h>
#include <sys/malloc.h>
#include <sys/cons.h>
-
-#include <machine/md_var.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <geom/geom_disk.h>
+#endif /* _KERNEL */
#ifndef _KERNEL
#include <stdio.h>
@@ -61,6 +56,7 @@
#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 +129,7 @@
struct task sysctl_task;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
+ struct callout sendordered_c;
};
struct da_quirk_entry {
@@ -169,7 +166,6 @@
*/
{T_DIRECT, SIP_MEDIA_FIXED, "FUJITSU", "M2954*", "*"},
/*quirks*/ DA_Q_NO_SYNC_CACHE
-
},
{
/*
@@ -241,7 +237,7 @@
* Reported by: walter at pelissero.de
*/
{T_DIRECT, SIP_MEDIA_FIXED, "CONNER", "CP3500*", "*"},
- /*quirks*/ DA_Q_NO_SYNC_CACHE
+ /*quirks*/ DA_Q_NO_SYNC_CACHE
},
{
/*
@@ -266,7 +262,7 @@
*/
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "USB Flash Disk*",
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
- },
+ },
{
/*
* Creative Nomad MUVO mp3 player (USB)
@@ -351,8 +347,8 @@
* Kingston DataTraveler II+ USB Pen-Drive.
* Reported by: Pawel Jakub Dawidek <pjd at FreeBSD.org>
*/
- {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+", "*"},
- /*quirks*/ DA_Q_NO_SYNC_CACHE
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "Kingston" , "DataTraveler II+",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
},
{
/*
@@ -443,6 +439,102 @@
{T_DIRECT, SIP_MEDIA_REMOVABLE, "Generic*", "STORAGE DEVICE*",
"*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
},
+ {
+ /*
+ * Rekam Digital CAMERA
+ * PR: usb/98713
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "CAMERA*", "4MP-9J6*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * iRiver H10 MP3 player
+ * PR: usb/102547
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "H10*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * iRiver U10 MP3 player
+ * PR: usb/92306
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "iriver", "U10*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * X-Micro Flash Disk
+ * PR: usb/96901
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "X-Micro", "Flash Disk",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * EasyMP3 EM732X USB 2.0 Flash MP3 Player
+ * PR: usb/96546
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "EM732X", "MP3 Player*",
+ "1.0"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * Denver MP3 player
+ * PR: usb/107101
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "DENVER", "MP3 PLAYER",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * Philips USB Key Audio KEY013
+ * PR: usb/68412
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "PHILIPS", "Key*", "*"},
+ /*quirks*/ DA_Q_NO_SYNC_CACHE | DA_Q_NO_PREVENT
+ },
+ {
+ /*
+ * JNC MP3 Player
+ * PR: usb/94439
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "JNC*" , "MP3 Player*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * SAMSUNG MP0402H
+ * PR: usb/108427
+ */
+ {T_DIRECT, SIP_MEDIA_FIXED, "SAMSUNG", "MP0402H", "*"},
+ /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * I/O Magic USB flash - Giga Bank
+ * PR: usb/108810
+ */
+ {T_DIRECT, SIP_MEDIA_FIXED, "GS-Magic", "stor*", "*"},
+ /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * JoyFly 128mb USB Flash Drive
+ * PR: 96133
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "USB 2.0", "Flash Disk*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
+ {
+ /*
+ * ChipsBnk usb stick
+ * PR: 103702
+ */
+ {T_DIRECT, SIP_MEDIA_REMOVABLE, "ChipsBnk", "USB*",
+ "*"}, /*quirks*/ DA_Q_NO_SYNC_CACHE
+ },
};
static disk_strategy_t dastrategy;
@@ -475,8 +567,14 @@
#define DA_DEFAULT_RETRY 4
#endif
+#ifndef DA_DEFAULT_SEND_ORDERED
+#define DA_DEFAULT_SEND_ORDERED 1
+#endif
+
+
static int da_retry_count = DA_DEFAULT_RETRY;
static int da_default_timeout = DA_DEFAULT_TIMEOUT;
+static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
"CAM Direct Access Disk driver");
@@ -486,6 +584,9 @@
SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RW,
&da_default_timeout, 0, "Normal I/O timeout (in seconds)");
TUNABLE_INT("kern.cam.da.default_timeout", &da_default_timeout);
+SYSCTL_INT(_kern_cam_da, OID_AUTO, da_send_ordered, CTLFLAG_RW,
+ &da_send_ordered, 0, "Send Ordered Tags");
+TUNABLE_INT("kern.cam.da.da_send_ordered", &da_send_ordered);
/*
* DA_ORDEREDTAG_INTERVAL determines how often, relative
@@ -511,7 +612,7 @@
PERIPHDRIVER_DECLARE(da, dadriver);
-static SLIST_HEAD(,da_softc) softc_list;
+MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
static int
daopen(struct disk *dp)
@@ -520,34 +621,35 @@
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);
@@ -570,6 +672,7 @@
softc->flags &= ~DA_FLAG_OPEN;
cam_periph_release(periph);
}
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (error);
}
@@ -579,18 +682,21 @@
{
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;
@@ -622,11 +728,10 @@
if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
scsi_sense_print(&ccb->csio);
} else {
- xpt_print_path(periph->path);
- printf("Synchronize cache failed, status "
- "== 0x%x, scsi status == 0x%x\n",
- ccb->csio.ccb_h.status,
- ccb->csio.scsi_status);
+ xpt_print(periph->path, "Synchronize cache "
+ "failed, status == 0x%x, scsi status == "
+ "0x%x\n", ccb->csio.ccb_h.status,
+ ccb->csio.scsi_status);
}
}
@@ -653,8 +758,9 @@
}
softc->flags &= ~DA_FLAG_OPEN;
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
cam_periph_release(periph);
+ cam_periph_unlock(periph);
return (0);
}
@@ -668,7 +774,6 @@
{
struct cam_periph *periph;
struct da_softc *softc;
- int s;
periph = (struct cam_periph *)bp->bio_disk->d_drv1;
if (periph == NULL) {
@@ -676,6 +781,9 @@
return;
}
softc = (struct da_softc *)periph->softc;
+
+ cam_periph_lock(periph);
+
#if 0
/*
* check it's not too big a transfer for our adapter
@@ -688,13 +796,12 @@
* 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;
}
@@ -704,12 +811,11 @@
*/
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;
}
@@ -728,12 +834,16 @@
if (periph == NULL)
return (ENXIO);
softc = (struct da_softc *)periph->softc;
+ cam_periph_lock(periph);
secsize = softc->params.secsize;
- if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
+ if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
+ cam_periph_unlock(periph);
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,
@@ -759,10 +869,12 @@
else
printf("status == 0x%x, scsi status == 0x%x\n",
csio.ccb_h.status, csio.scsi_status);
+ periph->flags |= CAM_PERIPH_POLLED;
return(EIO);
}
+ cam_periph_unlock(periph);
return(0);
- }
+ }
/*
* Sync the disk cache contents to the physical media.
@@ -794,13 +906,15 @@
if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
scsi_sense_print(&csio);
} else {
- xpt_print_path(periph->path);
- printf("Synchronize cache failed, status "
- "== 0x%x, scsi status == 0x%x\n",
- csio.ccb_h.status, csio.scsi_status);
+ xpt_print(periph->path, "Synchronize cache "
+ "failed, status == 0x%x, scsi status == "
+ "0x%x\n", csio.ccb_h.status,
+ csio.scsi_status);
}
}
}
+ periph->flags &= ~CAM_PERIPH_POLLED;
+ cam_periph_unlock(periph);
return (0);
}
@@ -808,41 +922,17 @@
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".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_FOUND_DEVICE;
- csa.callback = daasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_FOUND_DEVICE, daasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("da: Failed to attach master async callback "
"due to status 0x%x!\n", status);
- } else {
-
- /*
- * Schedule a periodic event to occasionally send an
- * ordered tag to a device.
- */
- timeout(dasendorderedtag, NULL,
- (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
+ } else if (da_send_ordered) {
/* Register our shutdown event handler */
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
@@ -854,45 +944,26 @@
static void
daoninvalidate(struct cam_periph *periph)
{
- int s;
struct da_softc *softc;
- struct ccb_setasync csa;
softc = (struct da_softc *)periph->softc;
/*
* De-register any async callbacks.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path,
- /* priority */ 5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = 0;
- csa.callback = daasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(0, daasync, periph, periph->path);
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_path(periph->path);
- printf("lost device\n");
+ xpt_print(periph->path, "lost device\n");
}
static void
@@ -902,17 +973,19 @@
softc = (struct da_softc *)periph->softc;
- xpt_print_path(periph->path);
- printf("removing device entry\n");
+ xpt_print(periph->path, "removing device entry\n");
/*
* If we can't free the sysctl tree, oh well...
*/
if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
&& sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
- xpt_print_path(periph->path);
- printf("can't remove sysctl context\n");
+ xpt_print(periph->path, "can't remove sysctl context\n");
}
+
+ cam_periph_unlock(periph);
disk_destroy(softc->disk);
+ callout_drain(&softc->sendordered_c);
+ cam_periph_lock(periph);
free(softc, M_DEVBUF);
}
@@ -927,6 +1000,7 @@
case AC_FOUND_DEVICE:
{
struct ccb_getdev *cgd;
+ struct cam_sim *sim;
cam_status status;
cgd = (struct ccb_getdev *)arg;
@@ -943,6 +1017,7 @@
* 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,
@@ -960,10 +1035,8 @@
{
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.
@@ -971,7 +1044,6 @@
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:
@@ -988,8 +1060,10 @@
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);
@@ -1002,6 +1076,7 @@
if (softc->sysctl_tree == NULL) {
printf("dasysctlinit: unable to allocate sysctl tree\n");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
return;
}
@@ -1015,6 +1090,7 @@
"Minimum CDB size");
mtx_unlock(&Giant);
+ cam_periph_release(periph);
}
static int
@@ -1052,9 +1128,7 @@
static cam_status
daregister(struct cam_periph *periph, void *arg)
{
- int s;
struct da_softc *softc;
- struct ccb_setasync csa;
struct ccb_pathinq cpi;
struct ccb_getdev *cgd;
char tmpstr[80];
@@ -1142,17 +1216,10 @@
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;
@@ -1162,8 +1229,11 @@
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
@@ -1173,19 +1243,26 @@
* them and the only alternative would be to
* not attach the device on failure.
*/
- xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
- csa.callback = daasync;
- csa.callback_arg = periph;
- xpt_action((union ccb *)&csa);
+ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
+ daasync, periph, periph->path);
+
/*
- * 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);
}
@@ -1196,18 +1273,15 @@
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,
@@ -1216,13 +1290,10 @@
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);
@@ -1234,31 +1305,44 @@
} else {
tag_code = MSG_SIMPLE_Q_TAG;
}
- scsi_read_write(&start_ccb->csio,
- /*retries*/da_retry_count,
- /*cbfcnp*/dadone,
- /*tag_action*/tag_code,
- /*read_op*/bp->bio_cmd == BIO_READ,
- /*byte2*/0,
- softc->minimum_cmd_size,
- /*lba*/bp->bio_pblkno,
- /*block_count*/bp->bio_bcount /
- softc->params.secsize,
- /*data_ptr*/ bp->bio_data,
- /*dxfer_len*/ bp->bio_bcount,
- /*sense_len*/SSD_FULL_SIZE,
- /*timeout*/da_default_timeout*1000);
+ switch (bp->bio_cmd) {
+ case BIO_READ:
+ case BIO_WRITE:
+ scsi_read_write(&start_ccb->csio,
+ /*retries*/da_retry_count,
+ /*cbfcnp*/dadone,
+ /*tag_action*/tag_code,
+ /*read_op*/bp->bio_cmd == BIO_READ,
+ /*byte2*/0,
+ softc->minimum_cmd_size,
+ /*lba*/bp->bio_pblkno,
+ /*block_count*/bp->bio_bcount /
+ softc->params.secsize,
+ /*data_ptr*/ bp->bio_data,
+ /*dxfer_len*/ bp->bio_bcount,
+ /*sense_len*/SSD_FULL_SIZE,
+ /*timeout*/da_default_timeout*1000);
+ break;
+ case BIO_FLUSH:
+ scsi_synchronize_cache(&start_ccb->csio,
+ /*retries*/1,
+ /*cbfcnp*/dadone,
+ MSG_SIMPLE_Q_TAG,
+ /*begin_lba*/0,/* Cover the whole disk */
+ /*lb_count*/0,
+ SSD_FULL_SIZE,
+ /*timeout*/da_default_timeout*1000);
+ break;
+ }
start_ccb->ccb_h.ccb_state = DA_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 & DA_FLAG_RETRY_UA) != 0) {
@@ -1268,7 +1352,6 @@
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1284,9 +1367,8 @@
struct ccb_scsiio *csio;
struct scsi_read_capacity_data *rcap;
- rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
- M_TEMP,
- M_NOWAIT);
+ rcap = (struct scsi_read_capacity_data *)
+ malloc(sizeof(*rcap), M_SCSIDA, M_NOWAIT|M_ZERO);
if (rcap == NULL) {
printf("dastart: Couldn't malloc read_capacity data\n");
/* da_free_periph??? */
@@ -1311,7 +1393,7 @@
struct scsi_read_capacity_data_long *rcaplong;
rcaplong = (struct scsi_read_capacity_data_long *)
- malloc(sizeof(*rcaplong), M_TEMP, M_NOWAIT);
+ malloc(sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
if (rcaplong == NULL) {
printf("dastart: Couldn't malloc read_capacity data\n");
/* da_free_periph??? */
@@ -1352,9 +1434,8 @@
(*cdb != READ_6 && *cdb != WRITE_6))
return 0;
- xpt_print_path(ccb->ccb_h.path);
- printf("READ(6)/WRITE(6) not supported, "
- "increasing minimum_cmd_size to 10.\n");
+ xpt_print(ccb->ccb_h.path, "READ(6)/WRITE(6) not supported, "
+ "increasing minimum_cmd_size to 10.\n");
softc = (struct da_softc *)xpt_path_periph(ccb->ccb_h.path)->softc;
softc->minimum_cmd_size = 10;
@@ -1394,12 +1475,10 @@
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)
@@ -1417,18 +1496,17 @@
}
if (error != 0) {
- s = splbio();
-
if (error == ENXIO) {
/*
* Catastrophic error. Mark our pack as
* invalid.
*/
- /* XXX See if this is really a media
- * change first.
+ /*
+ * XXX See if this is really a media
+ * XXX change first?
*/
- xpt_print_path(periph->path);
- printf("Invalidating pack\n");
+ xpt_print(periph->path,
+ "Invalidating pack\n");
softc->flags |= DA_FLAG_PACK_INVALID;
}
@@ -1438,7 +1516,6 @@
* 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;
@@ -1466,12 +1543,10 @@
* 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;
@@ -1510,7 +1585,7 @@
*/
if (maxsector == 0xffffffff) {
softc->state = DA_STATE_PROBE2;
- free(rdcap, M_TEMP);
+ free(rdcap, M_SCSIDA);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, /*priority*/5);
return;
@@ -1519,15 +1594,30 @@
block_size = scsi_4btoul(rcaplong->length);
maxsector = scsi_8btou64(rcaplong->addr);
}
- dasetgeom(periph, block_size, maxsector);
- dp = &softc->params;
- snprintf(announce_buf, sizeof(announce_buf),
- "%juMB (%ju %u byte sectors: %dH %dS/T %dC)",
- (uintmax_t) (((uintmax_t)dp->secsize *
- dp->sectors) / (1024*1024)),
- (uintmax_t)dp->sectors,
- dp->secsize, dp->heads, dp->secs_per_track,
- dp->cylinders);
+
+ /*
+ * Because GEOM code just will panic us if we
+ * give them an 'illegal' value we'll avoid that
+ * here.
+ */
+ if (block_size >= MAXPHYS || block_size == 0) {
+ xpt_print(periph->path,
+ "unsupportable block size %ju\n",
+ (uintmax_t) block_size);
+ announce_buf[0] = '\0';
+ cam_periph_invalidate(periph);
+ } else {
+ dasetgeom(periph, block_size, maxsector);
+ dp = &softc->params;
+ snprintf(announce_buf, sizeof(announce_buf),
+ "%juMB (%ju %u byte sectors: %dH %dS/T "
+ "%dC)", (uintmax_t)
+ (((uintmax_t)dp->secsize *
+ dp->sectors) / (1024*1024)),
+ (uintmax_t)dp->sectors,
+ dp->secsize, dp->heads,
+ dp->secs_per_track, dp->cylinders);
+ }
} else {
int error;
@@ -1608,14 +1698,13 @@
scsi_sense_print(
&done_ccb->csio);
else {
- xpt_print_path(periph->path);
- printf("got CAM status %#x\n",
- done_ccb->ccb_h.status);
+ xpt_print(periph->path,
+ "got CAM status %#x\n",
+ done_ccb->ccb_h.status);
}
- xpt_print_path(periph->path);
- printf("fatal error, failed"
- " to attach to device\n");
+ xpt_print(periph->path, "fatal error, "
+ "failed to attach to device\n");
/*
* Free up resources.
@@ -1624,7 +1713,7 @@
}
}
}
- free(csio->data_ptr, M_TEMP);
+ free(csio->data_ptr, M_SCSIDA);
if (announce_buf[0] != '\0') {
xpt_announce_periph(periph, announce_buf);
/*
@@ -1643,7 +1732,7 @@
* operation.
*/
xpt_release_ccb(done_ccb);
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
return;
}
case DA_CCB_WAITING:
@@ -1753,16 +1842,22 @@
uint32_t block_len;
uint64_t maxsector;
int error;
+ u_int32_t sense_flags;
softc = (struct da_softc *)periph->softc;
block_len = 0;
maxsector = 0;
error = 0;
+ sense_flags = SF_RETRY_UA;
+ if (softc->flags & DA_FLAG_PACK_REMOVABLE)
+ sense_flags |= SF_NO_PRINT;
/* Do a read capacity */
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
- M_TEMP,
- M_WAITOK);
+ M_SCSIDA,
+ M_NOWAIT);
+ if (rcap == NULL)
+ return (ENOMEM);
ccb = cam_periph_getccb(periph, /*priority*/1);
scsi_read_capacity(&ccb->csio,
@@ -1776,7 +1871,7 @@
error = cam_periph_runccb(ccb, daerror,
/*cam_flags*/CAM_RETRY_SELTO,
- /*sense_flags*/SF_RETRY_UA,
+ sense_flags,
softc->disk->d_devstat);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@@ -1811,7 +1906,7 @@
error = cam_periph_runccb(ccb, daerror,
/*cam_flags*/CAM_RETRY_SELTO,
- /*sense_flags*/SF_RETRY_UA,
+ sense_flags,
softc->disk->d_devstat);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@@ -1833,7 +1928,7 @@
xpt_release_ccb(ccb);
- free(rcap, M_TEMP);
+ free(rcap, M_SCSIDA);
return (error);
}
@@ -1866,21 +1961,31 @@
ccg.secs_per_track = 0;
ccg.cylinders = 0;
xpt_action((union ccb*)&ccg);
- dp->heads = ccg.heads;
- dp->secs_per_track = ccg.secs_per_track;
- dp->cylinders = ccg.cylinders;
+ if ((ccg.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ /*
+ * We don't know what went wrong here- but just pick
+ * a geometry so we don't have nasty things like divide
+ * by zero.
+ */
+ dp->heads = 255;
+ dp->secs_per_track = 255;
+ dp->cylinders = dp->sectors / (255 * 255);
+ if (dp->cylinders == 0) {
+ dp->cylinders = 1;
+ }
+ } else {
+ dp->heads = ccg.heads;
+ dp->secs_per_track = ccg.secs_per_track;
+ dp->cylinders = ccg.cylinders;
+ }
}
static void
dasendorderedtag(void *arg)
{
- struct da_softc *softc;
- int s;
+ struct da_softc *softc = arg;
- for (softc = SLIST_FIRST(&softc_list);
- softc != NULL;
- softc = SLIST_NEXT(softc, links)) {
- s = splsoftcam();
+ if (da_send_ordered) {
if ((softc->ordered_tag_count == 0)
&& ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
softc->flags |= DA_FLAG_NEED_OTAG;
@@ -1889,11 +1994,11 @@
softc->flags &= ~DA_FLAG_WENT_IDLE;
softc->ordered_tag_count = 0;
- splx(s);
}
/* Queue us up again */
- timeout(dasendorderedtag, NULL,
- (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
+ callout_reset(&softc->sendordered_c,
+ (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
+ dasendorderedtag, softc);
}
/*
@@ -1908,6 +2013,8 @@
TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
union ccb ccb;
+
+ cam_periph_lock(periph);
softc = (struct da_softc *)periph->softc;
/*
@@ -1915,8 +2022,10 @@
* if the drive is capable of it..
*/
if (((softc->flags & DA_FLAG_OPEN) == 0)
- || (softc->quirks & DA_Q_NO_SYNC_CACHE))
+ || (softc->quirks & DA_Q_NO_SYNC_CACHE)) {
+ cam_periph_unlock(periph);
continue;
+ }
xpt_setup_ccb(&ccb.ccb_h, periph->path, /*priority*/1);
@@ -1945,10 +2054,10 @@
if (sense_key != SSD_KEY_ILLEGAL_REQUEST)
scsi_sense_print(&ccb.csio);
} else {
- xpt_print_path(periph->path);
- printf("Synchronize cache failed, status "
- "== 0x%x, scsi status == 0x%x\n",
- ccb.ccb_h.status, ccb.csio.scsi_status);
+ xpt_print(periph->path, "Synchronize "
+ "cache failed, status == 0x%x, scsi status "
+ "== 0x%x\n", ccb.ccb_h.status,
+ ccb.csio.scsi_status);
}
}
@@ -1958,7 +2067,7 @@
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
-
+ cam_periph_unlock(periph);
}
}
Index: scsi_targ_bh.c
===================================================================
RCS file: /home/cvs/src/sys/cam/scsi/scsi_targ_bh.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/cam/scsi/scsi_targ_bh.c -L sys/cam/scsi/scsi_targ_bh.c -u -r1.1.1.1 -r1.2
--- sys/cam/scsi/scsi_targ_bh.c
+++ sys/cam/scsi/scsi_targ_bh.c
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_targ_bh.c,v 1.22 2005/07/01 15:21:30 avatar Exp $");
+__FBSDID("$FreeBSD: src/sys/cam/scsi/scsi_targ_bh.c,v 1.25 2007/05/16 16:54:23 scottl Exp $");
#include <sys/param.h>
#include <sys/queue.h>
@@ -46,6 +46,7 @@
#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>
@@ -155,27 +156,13 @@
targbhinit(void)
{
cam_status status;
- struct cam_path *path;
/*
* Install a global async callback. This callback will
* receive async callbacks like "new path registered".
*/
- status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
-
- if (status == CAM_REQ_CMP) {
- struct ccb_setasync csa;
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_PATH_REGISTERED | AC_PATH_DEREGISTERED;
- csa.callback = targbhasync;
- csa.callback_arg = NULL;
- xpt_action((union ccb *)&csa);
- status = csa.ccb_h.status;
- xpt_free_path(path);
- }
+ status = xpt_register_async(AC_PATH_REGISTERED | AC_PATH_DEREGISTERED,
+ targbhasync, NULL, NULL);
if (status != CAM_REQ_CMP) {
printf("targbh: Failed to attach master async callback "
@@ -263,9 +250,9 @@
xpt_action(&immed_ccb);
status = immed_ccb.ccb_h.status;
if (status != CAM_REQ_CMP) {
- xpt_print_path(periph->path);
- printf("targbhenlun - Enable Lun Rejected with status 0x%x\n",
- status);
+ xpt_print(periph->path,
+ "targbhenlun - Enable Lun Rejected with status 0x%x\n",
+ status);
return (status);
}
@@ -309,9 +296,9 @@
}
if (i == 0) {
- xpt_print_path(periph->path);
- printf("targbhenlun - Could not allocate accept tio CCBs: "
- "status = 0x%x\n", status);
+ xpt_print(periph->path,
+ "targbhenlun - Could not allocate accept tio CCBs: status "
+ "= 0x%x\n", status);
targbhdislun(periph);
return (CAM_REQ_CMP_ERR);
}
@@ -345,9 +332,9 @@
}
if (i == 0) {
- xpt_print_path(periph->path);
- printf("targbhenlun - Could not allocate immediate notify "
- "CCBs: status = 0x%x\n", status);
+ xpt_print(periph->path,
+ "targbhenlun - Could not allocate immediate notify "
+ "CCBs: status = 0x%x\n", status);
targbhdislun(periph);
return (CAM_REQ_CMP_ERR);
}
@@ -447,7 +434,7 @@
/* 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 +449,22 @@
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 +525,7 @@
/*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);
More information about the Midnightbsd-cvs
mailing list