summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ata/ata_all.c6
-rw-r--r--sys/cam/ata/ata_da.c2
-rw-r--r--sys/cam/ata/ata_pmp.c150
-rw-r--r--sys/cam/ata/ata_xpt.c121
-rw-r--r--sys/cam/cam.c6
-rw-r--r--sys/cam/cam.h25
-rw-r--r--sys/cam/cam_ccb.h7
-rw-r--r--sys/cam/cam_periph.c389
-rw-r--r--sys/cam/cam_periph.h6
-rw-r--r--sys/cam/cam_queue.h105
-rw-r--r--sys/cam/cam_sim.c3
-rw-r--r--sys/cam/cam_xpt.c660
-rw-r--r--sys/cam/cam_xpt.h5
-rw-r--r--sys/cam/cam_xpt_internal.h1
-rw-r--r--sys/cam/cam_xpt_periph.h3
-rw-r--r--sys/cam/cam_xpt_sim.h8
-rw-r--r--sys/cam/scsi/scsi_all.c59
-rw-r--r--sys/cam/scsi/scsi_cd.c48
-rw-r--r--sys/cam/scsi/scsi_ch.c2
-rw-r--r--sys/cam/scsi/scsi_da.c2
-rw-r--r--sys/cam/scsi/scsi_low.c36
-rw-r--r--sys/cam/scsi/scsi_pass.c12
-rw-r--r--sys/cam/scsi/scsi_xpt.c65
-rw-r--r--sys/dev/ahci/ahci.c55
-rw-r--r--sys/dev/ahci/ahci.h15
-rw-r--r--sys/dev/asr/asr.c1
-rw-r--r--sys/dev/ata/ata-all.c27
-rw-r--r--sys/dev/ata/atapi-cam.c32
-rw-r--r--sys/dev/ciss/ciss.c48
-rw-r--r--sys/dev/hptiop/hptiop.c29
-rw-r--r--sys/dev/hptrr/hptrr_osm_bsd.c32
-rw-r--r--sys/dev/hptrr/os_bsd.h1
-rw-r--r--sys/dev/mly/mly.c22
-rw-r--r--sys/dev/mpt/mpt_cam.h1
-rw-r--r--sys/dev/mpt/mpt_raid.c17
-rw-r--r--sys/dev/ppbus/vpo.c37
-rw-r--r--sys/dev/siis/siis.c35
-rw-r--r--sys/dev/trm/trm.c18
-rw-r--r--sys/dev/twa/tw_osl_cam.c59
-rw-r--r--sys/dev/usb/storage/umass.c77
40 files changed, 1047 insertions, 1180 deletions
diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c
index 25daea4..b2db7a0 100644
--- a/sys/cam/ata/ata_all.c
+++ b/sys/cam/ata/ata_all.c
@@ -198,7 +198,7 @@ ata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
{
char cmd_str[(12 * 3) + 1];
- sbuf_printf(sb, "CMD: %s: %s",
+ sbuf_printf(sb, "%s. ACB: %s",
ata_op_string(&ataio->cmd),
ata_cmd_string(&ataio->cmd, cmd_str, sizeof(cmd_str)));
@@ -212,7 +212,7 @@ int
ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
{
- sbuf_printf(sb, "ATA Status: %02x (%s%s%s%s%s%s%s%s)",
+ sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s)",
ataio->res.status,
(ataio->res.status & 0x80) ? "BSY " : "",
(ataio->res.status & 0x40) ? "DRDY " : "",
@@ -223,7 +223,7 @@ ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
(ataio->res.status & 0x02) ? "IDX " : "",
(ataio->res.status & 0x01) ? "ERR" : "");
if (ataio->res.status & 1) {
- sbuf_printf(sb, ", Error: %02x (%s%s%s%s%s%s%s%s)",
+ sbuf_printf(sb, ", error: %02x (%s%s%s%s%s%s%s%s)",
ataio->res.error,
(ataio->res.error & 0x80) ? "ICRC " : "",
(ataio->res.error & 0x40) ? "UNC " : "",
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 8d49309..3408b4f 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -689,7 +689,7 @@ adaregister(struct cam_periph *periph, void *arg)
/* Check if the SIM does not want queued commands */
bzero(&cpi, sizeof(cpi));
- xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
if (cpi.ccb_h.status != CAM_REQ_CMP ||
diff --git a/sys/cam/ata/ata_pmp.c b/sys/cam/ata/ata_pmp.c
index 8c2e1bf..1b8d9d5 100644
--- a/sys/cam/ata/ata_pmp.c
+++ b/sys/cam/ata/ata_pmp.c
@@ -98,6 +98,9 @@ struct pmp_softc {
int reset;
int frozen;
int restart;
+ int events;
+#define PMP_EV_RESET 1
+#define PMP_EV_RESCAN 2
union ccb saved_ccb;
struct task sysctl_task;
struct sysctl_ctx_list sysctl_ctx;
@@ -179,7 +182,8 @@ pmpfreeze(struct cam_periph *periph, int mask)
i, 0) == CAM_REQ_CMP) {
softc->frozen |= (1 << i);
xpt_acquire_device(dpath->device);
- cam_freeze_devq(dpath);
+ cam_freeze_devq_arg(dpath,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_BUS + 1);
xpt_free_path(dpath);
}
}
@@ -200,7 +204,8 @@ pmprelease(struct cam_periph *periph, int mask)
xpt_path_path_id(periph->path),
i, 0) == CAM_REQ_CMP) {
softc->frozen &= ~(1 << i);
- cam_release_devq(dpath, 0, 0, 0, FALSE);
+ cam_release_devq(dpath,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_BUS + 1, FALSE);
xpt_release_device(dpath->device);
xpt_free_path(dpath);
}
@@ -298,19 +303,20 @@ pmpasync(void *callback_arg, u_int32_t code,
case AC_BUS_RESET:
softc = (struct pmp_softc *)periph->softc;
cam_periph_async(periph, code, path, arg);
- if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL &&
- softc->state != PMP_STATE_SCAN)
- break;
- if (softc->state != PMP_STATE_SCAN)
- pmpfreeze(periph, softc->found);
+ if (code == AC_SCSI_AEN)
+ softc->events |= PMP_EV_RESCAN;
else
- pmpfreeze(periph, softc->found & ~(1 << softc->pm_step));
+ softc->events |= PMP_EV_RESET;
+ if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL)
+ break;
+ xpt_hold_boot();
+ pmpfreeze(periph, softc->found);
if (code == AC_SENT_BDR || code == AC_BUS_RESET)
softc->found = 0; /* We have to reset everything. */
if (softc->state == PMP_STATE_NORMAL) {
- softc->state = PMP_STATE_PORTS;
+ softc->state = PMP_STATE_PRECONFIG;
cam_periph_acquire(periph);
- xpt_schedule(periph, CAM_PRIORITY_BUS);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
} else
softc->restart = 1;
break;
@@ -353,7 +359,6 @@ static cam_status
pmpregister(struct cam_periph *periph, void *arg)
{
struct pmp_softc *softc;
- struct ccb_pathinq cpi;
struct ccb_getdev *cgd;
cgd = (struct ccb_getdev *)arg;
@@ -377,16 +382,8 @@ pmpregister(struct cam_periph *periph, void *arg)
}
periph->softc = softc;
- softc->state = PMP_STATE_PORTS;
softc->pm_pid = ((uint32_t *)&cgd->ident_data)[0];
softc->pm_prv = ((uint32_t *)&cgd->ident_data)[1];
-
- /* Check if the SIM does not want queued commands */
- bzero(&cpi, sizeof(cpi));
- xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
-
TASK_INIT(&softc->sysctl_task, 0, pmpsysctlinit, periph);
xpt_announce_periph(periph, NULL);
@@ -408,7 +405,10 @@ pmpregister(struct cam_periph *periph, void *arg)
* the end of probe.
*/
(void)cam_periph_acquire(periph);
- xpt_schedule(periph, CAM_PRIORITY_BUS);
+ xpt_hold_boot();
+ softc->state = PMP_STATE_PORTS;
+ softc->events = PMP_EV_RESCAN;
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
@@ -416,17 +416,35 @@ pmpregister(struct cam_periph *periph, void *arg)
static void
pmpstart(struct cam_periph *periph, union ccb *start_ccb)
{
+ struct ccb_trans_settings cts;
struct ccb_ataio *ataio;
struct pmp_softc *softc;
+ struct cam_path *dpath;
+ int revision = 0;
softc = (struct pmp_softc *)periph->softc;
ataio = &start_ccb->ataio;
if (softc->restart) {
softc->restart = 0;
- softc->state = PMP_STATE_PORTS;
+ softc->state = min(softc->state, PMP_STATE_PRECONFIG);
+ }
+ /* Fetch user wanted device speed. */
+ if (softc->state == PMP_STATE_RESET ||
+ softc->state == PMP_STATE_CONNECT) {
+ if (xpt_create_path(&dpath, periph,
+ xpt_path_path_id(periph->path),
+ softc->pm_step, 0) == CAM_REQ_CMP) {
+ bzero(&cts, sizeof(cts));
+ xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE);
+ cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cts.type = CTS_TYPE_USER_SETTINGS;
+ xpt_action((union ccb *)&cts);
+ if (cts.xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
+ revision = cts.xport_specific.sata.revision;
+ xpt_free_path(dpath);
+ }
}
-
switch (softc->state) {
case PMP_STATE_PORTS:
cam_fill_ataio(ataio,
@@ -460,7 +478,8 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
/*dxfer_len*/0,
pmp_default_timeout * 1000);
ata_pm_write_cmd(ataio, 2, softc->pm_step,
- (softc->found & (1 << softc->pm_step)) ? 0 : 1);
+ (revision << 4) |
+ ((softc->found & (1 << softc->pm_step)) ? 0 : 1));
break;
case PMP_STATE_CONNECT:
cam_fill_ataio(ataio,
@@ -471,7 +490,8 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
/*data_ptr*/NULL,
/*dxfer_len*/0,
pmp_default_timeout * 1000);
- ata_pm_write_cmd(ataio, 2, softc->pm_step, 0);
+ ata_pm_write_cmd(ataio, 2, softc->pm_step,
+ (revision << 4));
break;
case PMP_STATE_CHECK:
cam_fill_ataio(ataio,
@@ -519,9 +539,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
struct ccb_trans_settings cts;
struct pmp_softc *softc;
struct ccb_ataio *ataio;
- union ccb *work_ccb;
struct cam_path *path, *dpath;
u_int32_t priority, res;
+ int i;
softc = (struct pmp_softc *)periph->softc;
ataio = &done_ccb->ataio;
@@ -547,16 +567,8 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
if (softc->restart) {
softc->restart = 0;
- if (softc->state == PMP_STATE_SCAN) {
- pmpfreeze(periph, 1 << softc->pm_step);
- work_ccb = done_ccb;
- done_ccb = (union ccb*)work_ccb->ccb_h.ppriv_ptr0;
- /* Free the current request path- we're done with it. */
- xpt_free_path(work_ccb->ccb_h.path);
- xpt_free_ccb(work_ccb);
- }
xpt_release_ccb(done_ccb);
- softc->state = PMP_STATE_PORTS;
+ softc->state = min(softc->state, PMP_STATE_PRECONFIG);
xpt_schedule(periph, priority);
return;
}
@@ -645,7 +657,7 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
xpt_path_path_id(periph->path),
softc->pm_step, 0) == CAM_REQ_CMP) {
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
@@ -705,53 +717,43 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
xpt_schedule(periph, priority);
return;
case PMP_STATE_CONFIG:
- if (softc->found) {
- softc->pm_step = 0;
- softc->state = PMP_STATE_SCAN;
- work_ccb = xpt_alloc_ccb_nowait();
- if (work_ccb != NULL)
- goto do_scan;
- xpt_release_ccb(done_ccb);
+ for (i = 0; i < softc->pm_ports; i++) {
+ union ccb *ccb;
+
+ if ((softc->found & (1 << i)) == 0)
+ continue;
+ if (xpt_create_path(&dpath, periph,
+ xpt_path_path_id(periph->path),
+ i, 0) != CAM_REQ_CMP) {
+ printf("pmpdone: xpt_create_path failed"
+ ", bus scan halted\n");
+ xpt_free_ccb(done_ccb);
+ goto done;
+ }
+ /* If we did hard reset to this device, inform XPT. */
+ if ((softc->reset & softc->found & (1 << i)) != 0)
+ xpt_async(AC_SENT_BDR, dpath, NULL);
+ /* If rescan requested, scan this device. */
+ if (softc->events & PMP_EV_RESCAN) {
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ xpt_free_path(dpath);
+ goto done;
+ }
+ xpt_setup_ccb(&ccb->ccb_h, dpath, CAM_PRIORITY_XPT);
+ xpt_rescan(ccb);
+ } else
+ xpt_free_path(dpath);
}
break;
- case PMP_STATE_SCAN:
- work_ccb = done_ccb;
- done_ccb = (union ccb*)work_ccb->ccb_h.ppriv_ptr0;
- /* Free the current request path- we're done with it. */
- xpt_free_path(work_ccb->ccb_h.path);
- softc->pm_step++;
-do_scan:
- while (softc->pm_step < softc->pm_ports &&
- (softc->found & (1 << softc->pm_step)) == 0) {
- softc->pm_step++;
- }
- if (softc->pm_step >= softc->pm_ports) {
- xpt_free_ccb(work_ccb);
- break;
- }
- if (xpt_create_path(&dpath, periph,
- done_ccb->ccb_h.path_id,
- softc->pm_step, 0) != CAM_REQ_CMP) {
- printf("pmpdone: xpt_create_path failed"
- ", bus scan halted\n");
- xpt_free_ccb(work_ccb);
- break;
- }
- xpt_setup_ccb(&work_ccb->ccb_h, dpath,
- done_ccb->ccb_h.pinfo.priority);
- work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
- work_ccb->ccb_h.cbfcnp = pmpdone;
- work_ccb->ccb_h.ppriv_ptr0 = done_ccb;
- work_ccb->crcn.flags = done_ccb->crcn.flags;
- xpt_action(work_ccb);
- pmprelease(periph, 1 << softc->pm_step);
- return;
default:
break;
}
done:
xpt_release_ccb(done_ccb);
softc->state = PMP_STATE_NORMAL;
+ softc->events = 0;
+ xpt_release_boot();
pmprelease(periph, -1);
cam_periph_release_locked(periph);
}
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 99cf314..bff0340 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -130,6 +130,7 @@ typedef struct {
u_int8_t digest[16];
uint32_t pm_pid;
uint32_t pm_prv;
+ int restart;
struct cam_periph *periph;
} probe_softc;
@@ -231,15 +232,11 @@ proberegister(struct cam_periph *periph, void *arg)
if (status != CAM_REQ_CMP) {
return (status);
}
-
-
/*
- * Ensure we've waited at least a bus settle
- * delay before attempting to probe the device.
- * For HBAs that don't do bus resets, this won't make a difference.
+ * Ensure nobody slip in until probe finish.
*/
- cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
- scsi_delay);
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
probeschedule(periph);
return(CAM_REQ_CMP);
}
@@ -247,17 +244,12 @@ proberegister(struct cam_periph *periph, void *arg)
static void
probeschedule(struct cam_periph *periph)
{
- struct ccb_pathinq cpi;
union ccb *ccb;
probe_softc *softc;
softc = (probe_softc *)periph->softc;
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
- xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
-
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
periph->path->device->protocol == PROTO_SATAPM)
PROBE_SET_ACTION(softc, PROBE_RESET);
@@ -269,7 +261,7 @@ probeschedule(struct cam_periph *periph)
else
softc->flags &= ~PROBE_NO_ANNOUNCE;
- xpt_schedule(periph, ccb->ccb_h.pinfo.priority);
+ xpt_schedule(periph, CAM_PRIORITY_XPT);
}
static void
@@ -290,6 +282,14 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
csio = &start_ccb->csio;
ident_buf = &periph->path->device->ident_data;
+ if (softc->restart) {
+ softc->restart = 0;
+ if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
+ path->device->protocol == PROTO_SATAPM)
+ softc->action = PROBE_RESET;
+ else
+ softc->action = PROBE_IDENTIFY;
+ }
switch (softc->action) {
case PROBE_RESET:
cam_fill_ataio(ataio,
@@ -299,7 +299,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
0,
/*data_ptr*/NULL,
/*dxfer_len*/0,
- (start_ccb->ccb_h.target_id == 15 ? 3 : 15) * 1000);
+ 15 * 1000);
ata_reset_cmd(ataio);
break;
case PROBE_IDENTIFY:
@@ -339,7 +339,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
mode = 0;
/* Fetch user modes from SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -355,7 +355,7 @@ negotiate:
wantmode = mode = ata_max_mode(ident_buf, mode);
/* Report modes to SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
if (path->device->transport == XPORT_ATA) {
@@ -368,7 +368,7 @@ negotiate:
xpt_action((union ccb *)&cts);
/* Fetch current modes from SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -400,7 +400,7 @@ negotiate:
bytecount = 8192; /* SATA maximum */
/* Fetch user bytecount from SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -416,7 +416,7 @@ negotiate:
bytecount / ata_logical_sector_size(ident_buf)));
/* Report bytecount to SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
if (path->device->transport == XPORT_ATA) {
@@ -431,7 +431,7 @@ negotiate:
xpt_action((union ccb *)&cts);
/* Fetch current bytecount from SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -462,7 +462,7 @@ negotiate:
bytecount = 8192; /* SATA maximum */
/* Fetch user bytecount from SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -482,7 +482,7 @@ negotiate:
}
/* Report bytecount to SIM. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
if (path->device->transport == XPORT_ATA) {
@@ -560,7 +560,7 @@ proberequestdefaultnegotiation(struct cam_periph *periph)
{
struct ccb_trans_settings cts;
- xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -582,7 +582,7 @@ proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
struct ccb_trans_settings_spi *spi;
memset(&cts, 0, sizeof (cts));
- xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -739,7 +739,7 @@ noerror:
done_ccb->ccb_h.target_id == 15) {
/* Report SIM that PM is present. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.pm_present = 1;
@@ -836,7 +836,7 @@ noerror:
path->bus->sim->max_tagged_dev_openings != 0) {
/* Report SIM which tags are allowed. */
bzero(&cts, sizeof(cts));
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.tags = path->device->maxtags;
@@ -957,18 +957,23 @@ noerror:
break;
}
done:
- xpt_release_ccb(done_ccb);
- 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;
- done_ccb->ccb_h.ppriv_field1 = found;
- xpt_done(done_ccb);
- if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
- cam_periph_invalidate(periph);
- cam_periph_release_locked(periph);
- } else {
+ if (softc->restart) {
+ softc->restart = 0;
+ xpt_release_ccb(done_ccb);
probeschedule(periph);
+ return;
}
+ xpt_release_ccb(done_ccb);
+ while ((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 = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
+ xpt_done(done_ccb);
+ }
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
+ cam_periph_invalidate(periph);
+ cam_periph_release_locked(periph);
}
static void
@@ -1013,7 +1018,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
{
struct cam_path *path;
ata_scan_bus_info *scan_info;
- union ccb *work_ccb;
+ union ccb *work_ccb, *reset_ccb;
cam_status status;
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
@@ -1038,6 +1043,26 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
return;
}
+ /* We may need to reset bus first, if we haven't done it yet. */
+ if ((work_ccb->cpi.hba_inquiry &
+ (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
+ !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
+ !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) {
+ reset_ccb = xpt_alloc_ccb_nowait();
+ xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
+ CAM_PRIORITY_NONE);
+ reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
+ xpt_action(reset_ccb);
+ if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
+ request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
+ xpt_free_ccb(reset_ccb);
+ xpt_free_ccb(work_ccb);
+ xpt_done(request_ccb);
+ return;
+ }
+ xpt_free_ccb(reset_ccb);
+ }
+
/* Save some state for use while we probe for devices */
scan_info = (ata_scan_bus_info *)
malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT);
@@ -1071,7 +1096,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
/* If there is PMP... */
if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
(scan_info->counter == scan_info->cpi->max_target)) {
- if (work_ccb->ccb_h.ppriv_field1 != 0) {
+ if (work_ccb->ccb_h.status == CAM_REQ_CMP) {
/* everything else willbe probed by it */
goto done;
} else {
@@ -1141,10 +1166,9 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
struct cam_path *new_path;
struct cam_periph *old_periph;
- CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
- ("xpt_scan_lun\n"));
+ CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n"));
- xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -1182,7 +1206,7 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
free(new_path, M_CAMXPT);
return;
}
- xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
request_ccb->ccb_h.cbfcnp = xptscandone;
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->crcn.flags = flags;
@@ -1194,6 +1218,7 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
softc = (probe_softc *)old_periph->softc;
TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
periph_links.tqe);
+ softc->restart = 1;
} else {
status = cam_periph_alloc(proberegister, NULL, probecleanup,
probestart, "aprobe",
@@ -1281,7 +1306,7 @@ ata_device_transport(struct cam_path *path)
struct ata_params *ident_buf = NULL;
/* Get transport information from the SIM */
- xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -1301,7 +1326,7 @@ ata_device_transport(struct cam_path *path)
ata_version(ident_buf->version_major) : cpi.transport_version;
/* Tell the controller what we think */
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.transport = path->device->transport;
@@ -1429,7 +1454,7 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
inq_data = &device->inq_data;
scsi = &cts->proto_specific.scsi;
- xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -1450,7 +1475,7 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
* Perform sanity checking against what the
* controller and device can do.
*/
- xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cur_cts.type = cts->type;
xpt_action((union ccb *)&cur_cts);
@@ -1550,6 +1575,10 @@ ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
*/
ata_scan_lun(newpath.periph, &newpath,
CAM_EXPECT_INQ_CHANGE, NULL);
+ } else {
+ /* We need to reinitialize device after reset. */
+ ata_scan_lun(newpath.periph, &newpath,
+ 0, NULL);
}
xpt_release_path(&newpath);
} else if (async_code == AC_LOST_DEVICE &&
diff --git a/sys/cam/cam.c b/sys/cam/cam.c
index 85b02fb..88271b0 100644
--- a/sys/cam/cam.c
+++ b/sys/cam/cam.c
@@ -305,10 +305,10 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
entry = cam_fetch_status_entry(status);
if (entry == NULL)
- sbuf_printf(&sb, "CAM Status: Unknown (%#x)\n",
+ sbuf_printf(&sb, "CAM status: Unknown (%#x)\n",
ccb->ccb_h.status);
else
- sbuf_printf(&sb, "CAM Status: %s\n",
+ sbuf_printf(&sb, "CAM status: %s\n",
entry->status_text);
}
@@ -338,7 +338,7 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
if (proto_flags & CAM_ESF_PRINT_STATUS) {
sbuf_cat(&sb, path_str);
- sbuf_printf(&sb, "SCSI Status: %s\n",
+ sbuf_printf(&sb, "SCSI status: %s\n",
scsi_status_string(&ccb->csio));
}
diff --git a/sys/cam/cam.h b/sys/cam/cam.h
index 3d85264..2b3b98c 100644
--- a/sys/cam/cam.h
+++ b/sys/cam/cam.h
@@ -60,16 +60,29 @@ typedef u_int lun_id_t;
struct cam_periph;
/*
- * Priority information for a CAM structure. The generation number is
- * incremented everytime a new entry is entered into the queue giving round
- * robin per priority level scheduling.
+ * Priority information for a CAM structure.
+ */
+typedef enum {
+ CAM_RL_HOST,
+ CAM_RL_BUS,
+ CAM_RL_XPT,
+ CAM_RL_DEV,
+ CAM_RL_NORMAL,
+ CAM_RL_VALUES
+} cam_rl;
+/*
+ * The generation number is incremented everytime a new entry is entered into
+ * the queue giving round robin per priority level scheduling.
*/
typedef struct {
u_int32_t priority;
-#define CAM_PRIORITY_BUS 0
-#define CAM_PRIORITY_DEV 0
-#define CAM_PRIORITY_NORMAL 1
+#define CAM_PRIORITY_HOST ((CAM_RL_HOST << 8) + 0x80)
+#define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80)
+#define CAM_PRIORITY_XPT ((CAM_RL_XPT << 8) + 0x80)
+#define CAM_PRIORITY_DEV ((CAM_RL_DEV << 8) + 0x80)
+#define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80)
#define CAM_PRIORITY_NONE (u_int32_t)-1
+#define CAM_PRIORITY_TO_RL(x) ((x) >> 8)
u_int32_t generation;
int index;
#define CAM_UNQUEUED_INDEX -1
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 72de564..4c5adba 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -126,7 +126,7 @@ typedef enum {
XPT_PATH_INQ = 0x04,
/* Path routing inquiry */
XPT_REL_SIMQ = 0x05,
- /* Release a frozen SIM queue */
+ /* Release a frozen device queue */
XPT_SASYNC_CB = 0x06,
/* Set Asynchronous Callback Parameters */
XPT_SDEV_TYPE = 0x07,
@@ -142,6 +142,8 @@ typedef enum {
/* Path statistics (error counts, etc.) */
XPT_GDEV_STATS = 0x0c,
/* Device statistics (error counts, etc.) */
+ XPT_FREEZE_QUEUE = 0x0d,
+ /* Freeze device queue */
/* SCSI Control Functions: 0x10->0x1F */
XPT_ABORT = 0x10,
/* Abort the specified CCB */
@@ -685,8 +687,9 @@ struct ccb_relsim {
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08
+#define RELSIM_RELEASE_RUNLEVEL 0x10
u_int32_t openings;
- u_int32_t release_timeout;
+ u_int32_t release_timeout; /* Abstract argument. */
u_int32_t qfrozen_cnt;
};
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 9bac0f5..4c7502a 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -71,19 +71,20 @@ static void camperiphfree(struct cam_periph *periph);
static int camperiphscsistatuserror(union ccb *ccb,
cam_flags camflags,
u_int32_t sense_flags,
- union ccb *save_ccb,
int *openings,
u_int32_t *relsim_flags,
- u_int32_t *timeout);
+ u_int32_t *timeout,
+ const char **action_string);
static int camperiphscsisenseerror(union ccb *ccb,
cam_flags camflags,
u_int32_t sense_flags,
- union ccb *save_ccb,
int *openings,
u_int32_t *relsim_flags,
- u_int32_t *timeout);
+ u_int32_t *timeout,
+ const char **action_string);
static int nperiph_drivers;
+static int initialized = 0;
struct periph_driver **periph_drivers;
MALLOC_DEFINE(M_CAMPERIPH, "CAM periph", "CAM peripheral buffers");
@@ -99,6 +100,7 @@ TUNABLE_INT("kern.cam.periph_busy_delay", &periph_busy_delay);
void
periphdriver_register(void *data)
{
+ struct periph_driver *drv = (struct periph_driver *)data;
struct periph_driver **newdrivers, **old;
int ndrivers;
@@ -108,13 +110,30 @@ periphdriver_register(void *data)
if (periph_drivers)
bcopy(periph_drivers, newdrivers,
sizeof(*newdrivers) * nperiph_drivers);
- newdrivers[nperiph_drivers] = (struct periph_driver *)data;
+ newdrivers[nperiph_drivers] = drv;
newdrivers[nperiph_drivers + 1] = NULL;
old = periph_drivers;
periph_drivers = newdrivers;
if (old)
free(old, M_CAMPERIPH);
nperiph_drivers++;
+ /* If driver marked as early or it is late now, initialize it. */
+ if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) ||
+ initialized > 1)
+ (*drv->init)();
+}
+
+void
+periphdriver_init(int level)
+{
+ int i, early;
+
+ initialized = max(initialized, level);
+ for (i = 0; periph_drivers[i] != NULL; i++) {
+ early = (periph_drivers[i]->flags & CAM_PERIPH_DRV_EARLY) ? 1 : 2;
+ if (early == initialized)
+ (*periph_drivers[i]->init)();
+ }
}
cam_status
@@ -915,12 +934,14 @@ cam_periph_runccb(union ccb *ccb,
} while (error == ERESTART);
- if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
+ if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
cam_release_devq(ccb->ccb_h.path,
/* relsim_flags */0,
/* openings */0,
/* timeout */0,
/* getcount_only */ FALSE);
+ ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
if (ds != NULL) {
if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
@@ -950,17 +971,26 @@ cam_periph_runccb(union ccb *ccb,
void
cam_freeze_devq(struct cam_path *path)
{
- struct ccb_hdr ccb_h;
- xpt_setup_ccb(&ccb_h, path, CAM_PRIORITY_NORMAL);
- ccb_h.func_code = XPT_NOOP;
- ccb_h.flags = CAM_DEV_QFREEZE;
- xpt_action((union ccb *)&ccb_h);
+ cam_freeze_devq_arg(path, 0, 0);
+}
+
+void
+cam_freeze_devq_arg(struct cam_path *path, uint32_t flags, uint32_t arg)
+{
+ struct ccb_relsim crs;
+
+ xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NONE);
+ crs.ccb_h.func_code = XPT_FREEZE_QUEUE;
+ crs.release_flags = flags;
+ crs.openings = arg;
+ crs.release_timeout = arg;
+ xpt_action((union ccb *)&crs);
}
u_int32_t
cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
- u_int32_t openings, u_int32_t timeout,
+ u_int32_t openings, u_int32_t arg,
int getcount_only)
{
struct ccb_relsim crs;
@@ -970,22 +1000,92 @@ cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0;
crs.release_flags = relsim_flags;
crs.openings = openings;
- crs.release_timeout = timeout;
+ crs.release_timeout = arg;
xpt_action((union ccb *)&crs);
return (crs.qfrozen_cnt);
}
#define saved_ccb_ptr ppriv_ptr0
+#define recovery_depth ppriv_field1
+static void
+camperiphsensedone(struct cam_periph *periph, union ccb *done_ccb)
+{
+ union ccb *saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
+ cam_status status;
+ int frozen = 0;
+ u_int sense_key;
+ int depth = done_ccb->ccb_h.recovery_depth;
+
+ status = done_ccb->ccb_h.status;
+ if (status & CAM_DEV_QFRZN) {
+ frozen = 1;
+ /*
+ * Clear freeze flag now for case of retry,
+ * freeze will be dropped later.
+ */
+ done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
+ }
+ status &= CAM_STATUS_MASK;
+ switch (status) {
+ case CAM_REQ_CMP:
+ {
+ /*
+ * If we manually retrieved sense into a CCB and got
+ * something other than "NO SENSE" send the updated CCB
+ * back to the client via xpt_done() to be processed via
+ * the error recovery code again.
+ */
+ sense_key = saved_ccb->csio.sense_data.flags;
+ sense_key &= SSD_KEY;
+ if (sense_key != SSD_KEY_NO_SENSE) {
+ saved_ccb->ccb_h.status |=
+ CAM_AUTOSNS_VALID;
+ } else {
+ saved_ccb->ccb_h.status &=
+ ~CAM_STATUS_MASK;
+ saved_ccb->ccb_h.status |=
+ CAM_AUTOSENSE_FAIL;
+ }
+ bcopy(saved_ccb, done_ccb, sizeof(union ccb));
+ xpt_free_ccb(saved_ccb);
+ break;
+ }
+ default:
+ bcopy(saved_ccb, done_ccb, sizeof(union ccb));
+ xpt_free_ccb(saved_ccb);
+ done_ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ done_ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
+ break;
+ }
+ periph->flags &= ~CAM_PERIPH_SENSE_INPROG;
+ /*
+ * If it is the end of recovery, drop freeze, taken due to
+ * CAM_DEV_QFREEZE flag, set on recovery request.
+ */
+ if (depth == 0) {
+ cam_release_devq(done_ccb->ccb_h.path,
+ /*relsim_flags*/0,
+ /*openings*/0,
+ /*timeout*/0,
+ /*getcount_only*/0);
+ }
+ /*
+ * Copy frozen flag from recovery request if it is set there
+ * for some reason.
+ */
+ if (frozen != 0)
+ done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
+ (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
+}
+
static void
camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
{
- union ccb *saved_ccb;
+ union ccb *saved_ccb, *save_ccb;
cam_status status;
int frozen = 0;
- int sense;
struct scsi_start_stop_unit *scsi_cmd;
u_int32_t relsim_flags, timeout;
- int xpt_done_ccb = FALSE;
status = done_ccb->ccb_h.status;
if (status & CAM_DEV_QFRZN) {
@@ -996,14 +1096,12 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
*/
done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
}
- sense = (status & CAM_AUTOSNS_VALID) != 0;
- status &= CAM_STATUS_MASK;
timeout = 0;
relsim_flags = 0;
saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
- switch (status) {
+ switch (status & CAM_STATUS_MASK) {
case CAM_REQ_CMP:
{
/*
@@ -1012,57 +1110,19 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
* the inquiry information. Many devices (mostly disks)
* don't properly report their inquiry information unless
* they are spun up.
- *
- * If we manually retrieved sense into a CCB and got
- * something other than "NO SENSE" send the updated CCB
- * back to the client via xpt_done() to be processed via
- * the error recovery code again.
*/
- if (done_ccb->ccb_h.func_code == XPT_SCSI_IO) {
- scsi_cmd = (struct scsi_start_stop_unit *)
- &done_ccb->csio.cdb_io.cdb_bytes;
-
- if (scsi_cmd->opcode == START_STOP_UNIT)
- xpt_async(AC_INQ_CHANGED,
- done_ccb->ccb_h.path, NULL);
- if (scsi_cmd->opcode == REQUEST_SENSE) {
- u_int sense_key;
-
- sense_key = saved_ccb->csio.sense_data.flags;
- sense_key &= SSD_KEY;
- if (sense_key != SSD_KEY_NO_SENSE) {
- saved_ccb->ccb_h.status |=
- CAM_AUTOSNS_VALID;
-#if 0
- 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);
-#endif
- } else {
- saved_ccb->ccb_h.status &=
- ~CAM_STATUS_MASK;
- saved_ccb->ccb_h.status |=
- CAM_AUTOSENSE_FAIL;
- }
- xpt_done_ccb = TRUE;
- }
- }
- bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
- sizeof(union ccb));
-
- periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
-
- if (xpt_done_ccb == FALSE)
- xpt_action(done_ccb);
+ scsi_cmd = (struct scsi_start_stop_unit *)
+ &done_ccb->csio.cdb_io.cdb_bytes;
- break;
+ if (scsi_cmd->opcode == START_STOP_UNIT)
+ xpt_async(AC_INQ_CHANGED,
+ done_ccb->ccb_h.path, NULL);
+ goto final;
}
case CAM_SCSI_STATUS_ERROR:
scsi_cmd = (struct scsi_start_stop_unit *)
&done_ccb->csio.cdb_io.cdb_bytes;
- if (sense != 0) {
+ if (status & CAM_AUTOSNS_VALID) {
struct ccb_getdev cgd;
struct scsi_sense_data *sense;
int error_code, sense_key, asc, ascq;
@@ -1071,7 +1131,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
sense = &done_ccb->csio.sense_data;
scsi_extract_sense(sense, &error_code,
&sense_key, &asc, &ascq);
-
/*
* Grab the inquiry data for this device.
*/
@@ -1081,7 +1140,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
xpt_action((union ccb *)&cgd);
err_action = scsi_error_action(&done_ccb->csio,
&cgd.inq_data, 0);
-
/*
* If the error is "invalid field in CDB",
* and the load/eject flag is set, turn the
@@ -1091,7 +1149,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
* the load/eject flag by default for
* removable media.
*/
-
/* XXX KDM
* Should we check to see what the specific
* scsi status is?? Or does it not matter
@@ -1106,9 +1163,7 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
(done_ccb->ccb_h.retry_count > 0)) {
scsi_cmd->how &= ~SSS_LOEJ;
-
xpt_action(done_ccb);
-
} else if ((done_ccb->ccb_h.retry_count > 1)
&& ((err_action & SS_MASK) != SS_FAIL)) {
@@ -1119,53 +1174,51 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
* it another try unless this is an
* unretryable error.
*/
-
/* set the timeout to .5 sec */
relsim_flags =
RELSIM_RELEASE_AFTER_TIMEOUT;
timeout = 500;
-
xpt_action(done_ccb);
-
break;
-
} else {
/*
* Perform the final retry with the original
* CCB so that final error processing is
* performed by the owner of the CCB.
*/
- bcopy(done_ccb->ccb_h.saved_ccb_ptr,
- done_ccb, sizeof(union ccb));
-
- periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
-
- xpt_action(done_ccb);
+ goto final;
}
} else {
+ save_ccb = xpt_alloc_ccb_nowait();
+ if (save_ccb == NULL)
+ goto final;
+ bcopy(done_ccb, save_ccb, sizeof(*save_ccb));
+ periph->flags |= CAM_PERIPH_SENSE_INPROG;
/*
- * Eh?? The command failed, but we don't
- * have any sense. What's up with that?
- * Fire the CCB again to return it to the
- * caller.
+ * Send a Request Sense to the device. We
+ * assume that we are in a contingent allegiance
+ * condition so we do not tag this request.
*/
- bcopy(done_ccb->ccb_h.saved_ccb_ptr,
- done_ccb, sizeof(union ccb));
-
- periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
-
+ scsi_request_sense(&done_ccb->csio, /*retries*/1,
+ camperiphsensedone,
+ &save_ccb->csio.sense_data,
+ sizeof(save_ccb->csio.sense_data),
+ CAM_TAG_ACTION_NONE,
+ /*sense_len*/SSD_FULL_SIZE,
+ /*timeout*/5000);
+ done_ccb->ccb_h.pinfo.priority--;
+ done_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
+ done_ccb->ccb_h.saved_ccb_ptr = save_ccb;
+ done_ccb->ccb_h.recovery_depth++;
xpt_action(done_ccb);
-
}
break;
default:
- bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
- sizeof(union ccb));
-
+final:
+ bcopy(saved_ccb, done_ccb, sizeof(*done_ccb));
+ xpt_free_ccb(saved_ccb);
periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
-
xpt_action(done_ccb);
-
break;
}
@@ -1188,23 +1241,13 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
/*openings*/0,
/*timeout*/timeout,
/*getcount_only*/0);
- if (xpt_done_ccb == TRUE) {
- /*
- * Copy frozen flag from recovery request if it is set there
- * for some reason.
- */
- if (frozen != 0)
- done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
- (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
- } else {
- /* Drop freeze taken, if this recovery request got error. */
- if (frozen != 0) {
- cam_release_devq(done_ccb->ccb_h.path,
- /*relsim_flags*/0,
- /*openings*/0,
- /*timeout*/0,
- /*getcount_only*/0);
- }
+ /* Drop freeze taken, if this recovery request got error. */
+ if (frozen != 0) {
+ cam_release_devq(done_ccb->ccb_h.path,
+ /*relsim_flags*/0,
+ /*openings*/0,
+ /*timeout*/0,
+ /*getcount_only*/0);
}
}
@@ -1221,12 +1264,6 @@ cam_periph_async(struct cam_periph *periph, u_int32_t code,
case AC_LOST_DEVICE:
cam_periph_invalidate(periph);
break;
- case AC_SENT_BDR:
- case AC_BUS_RESET:
- {
- cam_periph_bus_settle(periph, scsi_delay);
- break;
- }
default:
break;
}
@@ -1271,9 +1308,9 @@ cam_periph_freeze_after_event(struct cam_periph *periph,
static int
camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
- u_int32_t sense_flags, union ccb *save_ccb,
+ u_int32_t sense_flags,
int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout)
+ u_int32_t *timeout, const char **action_string)
{
int error;
@@ -1286,13 +1323,15 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
break;
case SCSI_STATUS_CMD_TERMINATED:
case SCSI_STATUS_CHECK_COND:
+ if (bootverbose)
+ xpt_print(ccb->ccb_h.path, "SCSI status error\n");
error = camperiphscsisenseerror(ccb,
camflags,
sense_flags,
- save_ccb,
openings,
relsim_flags,
- timeout);
+ timeout,
+ action_string);
break;
case SCSI_STATUS_QUEUE_FULL:
{
@@ -1347,7 +1386,7 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
*timeout = 0;
error = ERESTART;
if (bootverbose) {
- xpt_print(ccb->ccb_h.path, "Queue Full\n");
+ xpt_print(ccb->ccb_h.path, "Queue full\n");
}
break;
}
@@ -1359,7 +1398,7 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
* command completes or a 1 second timeout.
*/
if (bootverbose) {
- xpt_print(ccb->ccb_h.path, "Device Busy\n");
+ xpt_print(ccb->ccb_h.path, "Device busy\n");
}
if (ccb->ccb_h.retry_count > 0) {
ccb->ccb_h.retry_count--;
@@ -1372,11 +1411,11 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
}
break;
case SCSI_STATUS_RESERV_CONFLICT:
- xpt_print(ccb->ccb_h.path, "Reservation Conflict\n");
+ xpt_print(ccb->ccb_h.path, "Reservation conflict\n");
error = EIO;
break;
default:
- xpt_print(ccb->ccb_h.path, "SCSI Status 0x%x\n",
+ xpt_print(ccb->ccb_h.path, "SCSI status 0x%x\n",
ccb->csio.scsi_status);
error = EIO;
break;
@@ -1386,16 +1425,17 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
static int
camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
- u_int32_t sense_flags, union ccb *save_ccb,
+ u_int32_t sense_flags,
int *openings, u_int32_t *relsim_flags,
- u_int32_t *timeout)
+ u_int32_t *timeout, const char **action_string)
{
struct cam_periph *periph;
+ union ccb *orig_ccb = ccb;
int error;
periph = xpt_path_periph(ccb->ccb_h.path);
- if (periph->flags & CAM_PERIPH_RECOVERY_INPROG) {
-
+ if (periph->flags &
+ (CAM_PERIPH_RECOVERY_INPROG | CAM_PERIPH_SENSE_INPROG)) {
/*
* If error recovery is already in progress, don't attempt
* to process this error, but requeue it unconditionally
@@ -1413,17 +1453,6 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
} else {
scsi_sense_action err_action;
struct ccb_getdev cgd;
- const char *action_string;
- union ccb* print_ccb;
-
- /* A description of the error recovery action performed */
- action_string = NULL;
-
- /*
- * The location of the orignal ccb
- * for sense printing purposes.
- */
- print_ccb = ccb;
/*
* Grab the inquiry data for this device.
@@ -1451,7 +1480,7 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
if (ccb->ccb_h.retry_count > 0)
ccb->ccb_h.retry_count--;
else {
- action_string = "Retries Exhausted";
+ *action_string = "Retries exhausted";
goto sense_error_done;
}
}
@@ -1461,8 +1490,9 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
* Do common portions of commands that
* use recovery CCBs.
*/
- if (save_ccb == NULL) {
- action_string = "No recovery CCB supplied";
+ orig_ccb = xpt_alloc_ccb_nowait();
+ if (orig_ccb == NULL) {
+ *action_string = "Can't allocate recovery CCB";
goto sense_error_done;
}
/*
@@ -1470,22 +1500,20 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
* this freeze will be dropped as part of ERESTART.
*/
ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
- bcopy(ccb, save_ccb, sizeof(*save_ccb));
- print_ccb = save_ccb;
- periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
+ bcopy(ccb, orig_ccb, sizeof(*orig_ccb));
}
switch (err_action & SS_MASK) {
case SS_NOP:
- action_string = "No Recovery Action Needed";
+ *action_string = "No recovery action needed";
error = 0;
break;
case SS_RETRY:
- action_string = "Retrying Command (per Sense Data)";
+ *action_string = "Retrying command (per sense data)";
error = ERESTART;
break;
case SS_FAIL:
- action_string = "Unretryable error";
+ *action_string = "Unretryable error";
break;
case SS_START:
{
@@ -1495,7 +1523,8 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
* Send a start unit command to the device, and
* then retry the command.
*/
- action_string = "Attempting to Start Unit";
+ *action_string = "Attempting to start unit";
+ periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
/*
* Check for removable media and set
@@ -1530,12 +1559,13 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
int retries;
if ((err_action & SSQ_MANY) != 0) {
- action_string = "Polling device for readiness";
+ *action_string = "Polling device for readiness";
retries = 120;
} else {
- action_string = "Testing device for readiness";
+ *action_string = "Testing device for readiness";
retries = 1;
}
+ periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
scsi_test_unit_ready(&ccb->csio,
retries,
camperiphdone,
@@ -1553,15 +1583,17 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
}
case SS_REQSENSE:
{
+ *action_string = "Requesting SCSI sense data";
+ periph->flags |= CAM_PERIPH_SENSE_INPROG;
/*
* Send a Request Sense to the device. We
* assume that we are in a contingent allegiance
* condition so we do not tag this request.
*/
scsi_request_sense(&ccb->csio, /*retries*/1,
- camperiphdone,
- &save_ccb->csio.sense_data,
- sizeof(save_ccb->csio.sense_data),
+ camperiphsensedone,
+ &orig_ccb->csio.sense_data,
+ sizeof(orig_ccb->csio.sense_data),
CAM_TAG_ACTION_NONE,
/*sense_len*/SSD_FULL_SIZE,
/*timeout*/5000);
@@ -1580,21 +1612,17 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
* the proper order before we release normal
* transactions to the device.
*/
- ccb->ccb_h.pinfo.priority = CAM_PRIORITY_DEV;
+ ccb->ccb_h.pinfo.priority--;
ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
- ccb->ccb_h.saved_ccb_ptr = save_ccb;
+ ccb->ccb_h.saved_ccb_ptr = orig_ccb;
+ ccb->ccb_h.recovery_depth = 0;
error = ERESTART;
}
sense_error_done:
if ((err_action & SSQ_PRINT_SENSE) != 0
- && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) {
- cam_error_print(print_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
- xpt_print_path(ccb->ccb_h.path);
- if (bootverbose)
- scsi_sense_print(&print_ccb->csio);
- printf("%s\n", action_string);
- }
+ && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
+ cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
}
return (error);
}
@@ -1630,19 +1658,18 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
error = camperiphscsistatuserror(ccb,
camflags,
sense_flags,
- save_ccb,
&openings,
&relsim_flags,
- &timeout);
+ &timeout,
+ &action_string);
break;
case CAM_AUTOSENSE_FAIL:
- xpt_print(ccb->ccb_h.path, "AutoSense Failed\n");
+ xpt_print(ccb->ccb_h.path, "AutoSense failed\n");
error = EIO; /* we have to kill the command */
break;
case CAM_ATA_STATUS_ERROR:
if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path,
- "Request completed with CAM_ATA_STATUS_ERROR\n");
+ xpt_print(ccb->ccb_h.path, "ATA status error\n");
cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
printed++;
}
@@ -1669,13 +1696,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
case CAM_UNCOR_PARITY:
if (bootverbose && printed == 0) {
xpt_print(ccb->ccb_h.path,
- "Uncorrected Parity Error\n");
+ "Uncorrected parity error\n");
printed++;
}
/* FALLTHROUGH */
case CAM_DATA_RUN_ERR:
if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Data Overrun\n");
+ xpt_print(ccb->ccb_h.path, "Data overrun\n");
printed++;
}
error = EIO; /* we have to kill the command */
@@ -1684,7 +1711,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
ccb->ccb_h.retry_count--;
error = ERESTART;
} else {
- action_string = "Retries Exhausted";
+ action_string = "Retries exhausted";
error = EIO;
}
break;
@@ -1705,7 +1732,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
error = ERESTART;
if (bootverbose && printed == 0) {
xpt_print(ccb->ccb_h.path,
- "Selection Timeout\n");
+ "Selection timeout\n");
printed++;
}
@@ -1767,7 +1794,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
/* Unconditional requeue */
error = ERESTART;
if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "Request Requeued\n");
+ xpt_print(ccb->ccb_h.path, "Request requeued\n");
printed++;
}
break;
@@ -1788,13 +1815,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
ccb->ccb_h.retry_count--;
error = ERESTART;
if (bootverbose && printed == 0) {
- xpt_print(ccb->ccb_h.path, "CAM Status 0x%x\n",
+ xpt_print(ccb->ccb_h.path, "CAM status 0x%x\n",
status);
printed++;
}
} else {
error = EIO;
- action_string = "Retries Exhausted";
+ action_string = "Retries exhausted";
}
break;
}
@@ -1807,11 +1834,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
!(status == CAM_SEL_TIMEOUT && (camflags & CAM_RETRY_SELTO) == 0)) {
if (error != ERESTART) {
if (action_string == NULL)
- action_string = "Unretryable Error";
- xpt_print(ccb->ccb_h.path, "error %d\n", error);
+ action_string = "Unretryable error";
+ xpt_print(ccb->ccb_h.path, "Error %d, %s\n",
+ error, action_string);
+ } else if (action_string != NULL)
xpt_print(ccb->ccb_h.path, "%s\n", action_string);
- } else
- xpt_print(ccb->ccb_h.path, "Retrying Command\n");
+ else
+ xpt_print(ccb->ccb_h.path, "Retrying command\n");
}
/* Attempt a retry */
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index e207b19..33e9f75 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -42,6 +42,7 @@ extern struct cam_periph *xpt_periph;
extern struct periph_driver **periph_drivers;
void periphdriver_register(void *);
+void periphdriver_init(int level);
#include <sys/module.h>
#define PERIPHDRIVER_DECLARE(name, driver) \
@@ -117,6 +118,7 @@ struct cam_periph {
#define CAM_PERIPH_INVALID 0x08
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
#define CAM_PERIPH_RECOVERY_INPROG 0x20
+#define CAM_PERIPH_SENSE_INPROG 0x40
u_int32_t immediate_priority;
u_int32_t refcount;
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
@@ -165,8 +167,10 @@ int cam_periph_ioctl(struct cam_periph *periph, u_long cmd,
cam_flags camflags,
u_int32_t sense_flags));
void cam_freeze_devq(struct cam_path *path);
+void cam_freeze_devq_arg(struct cam_path *path, u_int32_t flags,
+ uint32_t arg);
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
- u_int32_t opening_reduction, u_int32_t timeout,
+ u_int32_t opening_reduction, u_int32_t arg,
int getcount_only);
void cam_periph_async(struct cam_periph *periph, u_int32_t code,
struct cam_path *path, void *arg);
diff --git a/sys/cam/cam_queue.h b/sys/cam/cam_queue.h
index 31f9bc2..dd9f9a7 100644
--- a/sys/cam/cam_queue.h
+++ b/sys/cam/cam_queue.h
@@ -34,6 +34,7 @@
#ifdef _KERNEL
#include <sys/queue.h>
+#include <cam/cam.h>
/*
* This structure implements a heap based priority queue. The queue
@@ -47,7 +48,7 @@ struct camq {
int array_size;
int entries;
u_int32_t generation;
- u_int32_t qfrozen_cnt;
+ u_int32_t qfrozen_cnt[CAM_RL_VALUES];
};
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr);
@@ -140,6 +141,10 @@ cam_pinfo *camq_remove(struct camq *queue, int index);
/* Index the first element in the heap */
#define CAMQ_GET_HEAD(camq) ((camq)->queue_array[CAMQ_HEAD])
+/* Get the first element priority. */
+#define CAMQ_GET_PRIO(camq) (((camq)->entries > 0) ? \
+ ((camq)->queue_array[CAMQ_HEAD]->priority) : 0)
+
/*
* camq_change_priority: Raise or lower the priority of an entry
* maintaining queue order.
@@ -153,10 +158,10 @@ cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq);
static __inline void
cam_ccbq_take_opening(struct cam_ccbq *ccbq);
-static __inline void
+static __inline int
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb);
-static __inline void
+static __inline int
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb);
static __inline union ccb *
@@ -185,17 +190,31 @@ cam_ccbq_take_opening(struct cam_ccbq *ccbq)
ccbq->held++;
}
-static __inline void
+static __inline int
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
{
ccbq->held--;
camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo);
+ if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
+ new_ccb->ccb_h.pinfo.priority)] > 0) {
+ ccbq->devq_openings++;
+ ccbq->held++;
+ return (1);
+ } else
+ return (0);
}
-static __inline void
+static __inline int
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
{
camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index);
+ if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
+ ccb->ccb_h.pinfo.priority)] > 0) {
+ ccbq->devq_openings--;
+ ccbq->held--;
+ return (1);
+ } else
+ return (0);
}
static __inline union ccb *
@@ -229,5 +248,81 @@ cam_ccbq_release_opening(struct cam_ccbq *ccbq)
ccbq->devq_openings++;
}
+static __inline int
+cam_ccbq_freeze(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
+{
+ int i, frozen = 0;
+ cam_rl p, n;
+
+ /* Find pevious run level. */
+ for (p = 0; p < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[p] == 0; p++);
+ /* Find new run level. */
+ n = min(rl, p);
+ /* Apply new run level. */
+ for (i = rl; i < CAM_RL_VALUES; i++)
+ ccbq->queue.qfrozen_cnt[i] += cnt;
+ /* Update ccbq statistics. */
+ if (n == p)
+ return (0);
+ for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
+ cam_rl rrl =
+ CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
+ if (rrl < n)
+ continue;
+ if (rrl >= p)
+ break;
+ ccbq->devq_openings++;
+ ccbq->held++;
+ frozen++;
+ }
+ return (frozen);
+}
+
+static __inline int
+cam_ccbq_release(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
+{
+ int i, released = 0;
+ cam_rl p, n;
+
+ /* Apply new run level. */
+ for (i = rl; i < CAM_RL_VALUES; i++)
+ ccbq->queue.qfrozen_cnt[i] -= cnt;
+ /* Find new run level. */
+ for (n = 0; n < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[n] == 0; n++);
+ /* Find previous run level. */
+ p = min(rl, n);
+ /* Update ccbq statistics. */
+ if (n == p)
+ return (0);
+ for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
+ cam_rl rrl =
+ CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
+ if (rrl < p)
+ continue;
+ if (rrl >= n)
+ break;
+ ccbq->devq_openings--;
+ ccbq->held--;
+ released++;
+ }
+ return (released);
+}
+
+static __inline u_int32_t
+cam_ccbq_frozen(struct cam_ccbq *ccbq, cam_rl rl)
+{
+
+ return (ccbq->queue.qfrozen_cnt[rl]);
+}
+
+static __inline u_int32_t
+cam_ccbq_frozen_top(struct cam_ccbq *ccbq)
+{
+ cam_rl rl;
+
+ rl = CAM_PRIORITY_TO_RL(CAMQ_GET_PRIO(&ccbq->queue));
+ return (ccbq->queue.qfrozen_cnt[rl]);
+}
+
#endif /* _KERNEL */
#endif /* _CAM_CAM_QUEUE_H */
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index adccfa8..59148a9 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -69,7 +69,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
return (NULL);
sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
- M_CAMSIM, M_NOWAIT);
+ M_CAMSIM, M_ZERO | M_NOWAIT);
if (sim == NULL)
return (NULL);
@@ -86,6 +86,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->flags = 0;
sim->refcount = 1;
sim->devq = queue;
+ sim->max_ccbs = 8; /* Reserve for management purposes. */
sim->mtx = mtx;
if (mtx == &Giant) {
sim->flags |= 0;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 88ee309..d966a9f 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -102,6 +102,8 @@ struct xpt_softc {
/* queue for handling async rescan requests. */
TAILQ_HEAD(, ccb_hdr) ccb_scanq;
+ int buses_to_config;
+ int buses_config_done;
/* Registered busses */
TAILQ_HEAD(,cam_eb) xpt_busses;
@@ -109,6 +111,9 @@ struct xpt_softc {
struct intr_config_hook *xpt_config_hook;
+ int boot_delay;
+ struct callout boot_callout;
+
struct mtx xpt_topo_lock;
struct mtx xpt_lock;
};
@@ -145,6 +150,10 @@ typedef int xpt_pdrvfunc_t (struct periph_driver **pdrv, void *arg);
/* Transport layer configuration information */
static struct xpt_softc xsoftc;
+TUNABLE_INT("kern.cam.boot_delay", &xsoftc.boot_delay);
+SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
+ &xsoftc.boot_delay, 0, "Bus registration wait time");
+
/* Queues for our software interrupt handler */
typedef TAILQ_HEAD(cam_isrq, ccb_hdr) cam_isrq_t;
typedef TAILQ_HEAD(cam_simq, cam_sim) cam_simq_t;
@@ -210,11 +219,12 @@ static path_id_t xptnextfreepathid(void);
static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus);
static union ccb *xpt_get_ccb(struct cam_ed *device);
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 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);
+static void xpt_release_devq_device(struct cam_ed *dev, cam_rl rl,
+ u_int count, int run_queue);
static struct cam_et*
xpt_alloc_target(struct cam_eb *bus, target_id_t target_id);
static void xpt_release_target(struct cam_et *target);
@@ -224,11 +234,8 @@ static struct cam_et*
xpt_find_target(struct cam_eb *bus, target_id_t target_id);
static struct cam_ed*
xpt_find_device(struct cam_et *target, lun_id_t lun_id);
-static xpt_busfunc_t xptconfigbuscountfunc;
-static xpt_busfunc_t xptconfigfunc;
static void xpt_config(void *arg);
static xpt_devicefunc_t xptpassannouncefunc;
-static void xpt_finishconfig(struct cam_periph *periph, union ccb *ccb);
static void xptaction(struct cam_sim *sim, union ccb *work_ccb);
static void xptpoll(struct cam_sim *sim);
static void camisr(void *);
@@ -270,6 +277,7 @@ static xpt_busfunc_t xptdefbusfunc;
static xpt_targetfunc_t xptdeftargetfunc;
static xpt_devicefunc_t xptdefdevicefunc;
static xpt_periphfunc_t xptdefperiphfunc;
+static void xpt_finishconfig_task(void *context, int pending);
static int xpt_for_all_busses(xpt_busfunc_t *tr_func, void *arg);
static int xpt_for_all_devices(xpt_devicefunc_t *tr_func,
void *arg);
@@ -285,19 +293,19 @@ static xpt_devicefunc_t xptsetasyncfunc;
static xpt_busfunc_t xptsetasyncbusfunc;
static cam_status xptregister(struct cam_periph *periph,
void *arg);
-static __inline int xpt_schedule_dev_allocq(struct cam_eb *bus,
- struct cam_ed *dev);
static __inline int periph_is_queued(struct cam_periph *periph);
static __inline int device_is_alloc_queued(struct cam_ed *device);
static __inline int device_is_send_queued(struct cam_ed *device);
-static __inline int dev_allocq_is_runnable(struct cam_devq *devq);
static __inline int
xpt_schedule_dev_allocq(struct cam_eb *bus, struct cam_ed *dev)
{
int retval;
- if (dev->ccbq.devq_openings > 0) {
+ if ((dev->drvq.entries > 0) &&
+ (dev->ccbq.devq_openings > 0) &&
+ (cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
+ CAMQ_GET_PRIO(&dev->drvq))) == 0)) {
/*
* The priority of a device waiting for CCB resources
* is that of the the highest priority peripheral driver
@@ -305,7 +313,7 @@ xpt_schedule_dev_allocq(struct cam_eb *bus, struct cam_ed *dev)
*/
retval = xpt_schedule_dev(&bus->sim->devq->alloc_queue,
&dev->alloc_ccb_entry.pinfo,
- CAMQ_GET_HEAD(&dev->drvq)->priority);
+ CAMQ_GET_PRIO(&dev->drvq));
} else {
retval = 0;
}
@@ -318,7 +326,9 @@ xpt_schedule_dev_sendq(struct cam_eb *bus, struct cam_ed *dev)
{
int retval;
- if (dev->ccbq.dev_openings > 0) {
+ if ((dev->ccbq.queue.entries > 0) &&
+ (dev->ccbq.dev_openings > 0) &&
+ (cam_ccbq_frozen_top(&dev->ccbq) == 0)) {
/*
* The priority of a device waiting for controller
* resources is that of the the highest priority CCB
@@ -327,7 +337,7 @@ xpt_schedule_dev_sendq(struct cam_eb *bus, struct cam_ed *dev)
retval =
xpt_schedule_dev(&bus->sim->devq->send_queue,
&dev->send_ccb_entry.pinfo,
- CAMQ_GET_HEAD(&dev->ccbq.queue)->priority);
+ CAMQ_GET_PRIO(&dev->ccbq.queue));
} else {
retval = 0;
}
@@ -352,19 +362,6 @@ device_is_send_queued(struct cam_ed *device)
return (device->send_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX);
}
-static __inline int
-dev_allocq_is_runnable(struct cam_devq *devq)
-{
- /*
- * Have work to do.
- * Have space to do more work.
- * Allowed to do work.
- */
- return ((devq->alloc_queue.qfrozen_cnt == 0)
- && (devq->alloc_queue.entries > 0)
- && (devq->alloc_openings > 0));
-}
-
static void
xpt_periph_init()
{
@@ -818,45 +815,42 @@ cam_module_event_handler(module_t mod, int what, void *arg)
return 0;
}
+static void
+xpt_rescan_done(struct cam_periph *periph, union ccb *done_ccb)
+{
+
+ if (done_ccb->ccb_h.ppriv_ptr1 == NULL) {
+ xpt_free_path(done_ccb->ccb_h.path);
+ xpt_free_ccb(done_ccb);
+ } else {
+ done_ccb->ccb_h.cbfcnp = done_ccb->ccb_h.ppriv_ptr1;
+ (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
+ }
+ xpt_release_boot();
+}
+
/* thread to handle bus rescans */
static void
xpt_scanner_thread(void *dummy)
{
- cam_isrq_t queue;
union ccb *ccb;
struct cam_sim *sim;
+ xpt_lock_buses();
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();
if (TAILQ_EMPTY(&xsoftc.ccb_scanq))
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);
+ if ((ccb = (union ccb *)TAILQ_FIRST(&xsoftc.ccb_scanq)) != NULL) {
+ TAILQ_REMOVE(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+ xpt_unlock_buses();
sim = ccb->ccb_h.path->bus->sim;
CAM_SIM_LOCK(sim);
-
- if( ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD )
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- else
- ccb->ccb_h.func_code = XPT_SCAN_LUN;
- ccb->ccb_h.cbfcnp = xptdone;
- xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL);
- cam_periph_runccb(ccb, NULL, 0, 0, NULL);
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
+ xpt_action(ccb);
CAM_SIM_UNLOCK(sim);
+
+ xpt_lock_buses();
}
}
}
@@ -866,21 +860,30 @@ xpt_rescan(union ccb *ccb)
{
struct ccb_hdr *hdr;
- /*
- * Don't make duplicate entries for the same paths.
- */
+ /* Prepare request */
+ if(ccb->ccb_h.path->target->target_id == CAM_TARGET_WILDCARD)
+ ccb->ccb_h.func_code = XPT_SCAN_BUS;
+ else
+ ccb->ccb_h.func_code = XPT_SCAN_LUN;
+ ccb->ccb_h.ppriv_ptr1 = ccb->ccb_h.cbfcnp;
+ ccb->ccb_h.cbfcnp = xpt_rescan_done;
+ xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, CAM_PRIORITY_XPT);
+ /* 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) {
- wakeup(&xsoftc.ccb_scanq);
- 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;
+ if (ccb->ccb_h.ppriv_ptr1 == NULL) {
+ TAILQ_FOREACH(hdr, &xsoftc.ccb_scanq, sim_links.tqe) {
+ if (xpt_path_comp(hdr->path, ccb->ccb_h.path) == 0) {
+ wakeup(&xsoftc.ccb_scanq);
+ 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);
+ xsoftc.buses_to_config++;
wakeup(&xsoftc.ccb_scanq);
xpt_unlock_buses();
}
@@ -923,10 +926,9 @@ xpt_init(void *dummy)
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) {
+ mtx_unlock(&xsoftc.xpt_lock);
printf("xpt_init: xpt_bus_register failed with status %#x,"
" failing attach\n", status);
return (EINVAL);
@@ -940,6 +942,7 @@ xpt_init(void *dummy)
if ((status = xpt_create_path(&path, NULL, CAM_XPT_PATH_ID,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD)) != CAM_REQ_CMP) {
+ mtx_unlock(&xsoftc.xpt_lock);
printf("xpt_init: xpt_create_path failed with status %#x,"
" failing attach\n", status);
return (EINVAL);
@@ -949,7 +952,8 @@ xpt_init(void *dummy)
path, NULL, 0, xpt_sim);
xpt_free_path(path);
mtx_unlock(&xsoftc.xpt_lock);
-
+ /* Install our software interrupt handlers */
+ swi_add(NULL, "cambio", camisr, NULL, SWI_CAMBIO, INTR_MPSAFE, &cambio_ih);
/*
* Register a callback for when interrupts are enabled.
*/
@@ -961,7 +965,6 @@ xpt_init(void *dummy)
"- failing attach\n");
return (ENOMEM);
}
-
xsoftc.xpt_config_hook->ich_func = xpt_config;
if (config_intrhook_establish(xsoftc.xpt_config_hook) != 0) {
free (xsoftc.xpt_config_hook, M_CAMXPT);
@@ -969,13 +972,6 @@ xpt_init(void *dummy)
"- failing attach\n");
}
- /* fire up rescan thread */
- if (kproc_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, NULL, SWI_CAMBIO, INTR_MPSAFE, &cambio_ih);
-
return (0);
}
@@ -2481,6 +2477,9 @@ xpt_action(union ccb *start_ccb)
CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_action\n"));
start_ccb->ccb_h.status = CAM_REQ_INPROG;
+ /* Compatibility for RL-unaware code. */
+ if (CAM_PRIORITY_TO_RL(start_ccb->ccb_h.pinfo.priority) == 0)
+ start_ccb->ccb_h.pinfo.priority += CAM_PRIORITY_NORMAL - 1;
(*(start_ccb->ccb_h.path->bus->xport->action))(start_ccb);
}
@@ -2546,17 +2545,14 @@ xpt_action_default(union ccb *start_ccb)
case XPT_RESET_DEV:
case XPT_ENG_EXEC:
{
- struct cam_path *path;
- int runq;
-
- path = start_ccb->ccb_h.path;
-
- cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
- if (path->device->ccbq.queue.qfrozen_cnt == 0)
- runq = xpt_schedule_dev_sendq(path->bus, path->device);
- else
- runq = 0;
- if (runq != 0)
+ struct cam_path *path = start_ccb->ccb_h.path;
+ int frozen;
+
+ frozen = cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
+ path->device->sim->devq->alloc_openings += frozen;
+ if (frozen > 0)
+ xpt_run_dev_allocq(path->bus);
+ if (xpt_schedule_dev_sendq(path->bus, path->device))
xpt_run_dev_sendq(path->bus);
break;
}
@@ -2601,9 +2597,12 @@ xpt_action_default(union ccb *start_ccb)
if (abort_ccb->ccb_h.pinfo.index >= 0) {
struct cam_ccbq *ccbq;
+ struct cam_ed *device;
- ccbq = &abort_ccb->ccb_h.path->device->ccbq;
- cam_ccbq_remove_ccb(ccbq, abort_ccb);
+ device = abort_ccb->ccb_h.path->device;
+ ccbq = &device->ccbq;
+ device->sim->devq->alloc_openings -=
+ cam_ccbq_remove_ccb(ccbq, abort_ccb);
abort_ccb->ccb_h.status =
CAM_REQ_ABORTED|CAM_DEV_QFRZN;
xpt_freeze_devq(abort_ccb->ccb_h.path, 1);
@@ -3008,11 +3007,12 @@ xpt_action_default(union ccb *start_ccb)
}
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) == 0) {
-
- xpt_release_devq(crs->ccb_h.path, /*count*/1,
- /*run_queue*/TRUE);
+ xpt_release_devq_rl(crs->ccb_h.path, /*runlevel*/
+ (crs->release_flags & RELSIM_RELEASE_RUNLEVEL) ?
+ crs->release_timeout : 0,
+ /*count*/1, /*run_queue*/TRUE);
}
- start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt;
+ start_ccb->crs.qfrozen_cnt = dev->ccbq.queue.qfrozen_cnt[0];
start_ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@@ -3049,6 +3049,16 @@ xpt_action_default(union ccb *start_ccb)
#endif /* CAMDEBUG */
break;
}
+ case XPT_FREEZE_QUEUE:
+ {
+ struct ccb_relsim *crs = &start_ccb->crs;
+
+ xpt_freeze_devq_rl(crs->ccb_h.path, /*runlevel*/
+ (crs->release_flags & RELSIM_RELEASE_RUNLEVEL) ?
+ crs->release_timeout : 0, /*count*/1);
+ start_ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
case XPT_NOOP:
if ((start_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0)
xpt_freeze_devq(start_ccb->ccb_h.path, 1);
@@ -3129,7 +3139,7 @@ void
xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
{
struct cam_ed *device;
- int runq;
+ int runq = 0;
mtx_assert(perph->sim->mtx, MA_OWNED);
@@ -3143,8 +3153,8 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
camq_change_priority(&device->drvq,
perph->pinfo.index,
new_priority);
+ runq = xpt_schedule_dev_allocq(perph->path->bus, device);
}
- runq = 0;
} else {
/* New entry on the queue */
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
@@ -3192,8 +3202,9 @@ xpt_schedule_dev(struct camq *queue, cam_pinfo *pinfo,
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
("changed priority to %d\n",
new_priority));
- }
- retval = 0;
+ retval = 1;
+ } else
+ retval = 0;
} else {
/* New entry on the queue */
if (new_priority < old_priority)
@@ -3219,15 +3230,15 @@ xpt_run_dev_allocq(struct cam_eb *bus)
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
(" qfrozen_cnt == 0x%x, entries == %d, "
"openings == %d, active == %d\n",
- devq->alloc_queue.qfrozen_cnt,
+ devq->alloc_queue.qfrozen_cnt[0],
devq->alloc_queue.entries,
devq->alloc_openings,
devq->alloc_active));
- devq->alloc_queue.qfrozen_cnt++;
+ devq->alloc_queue.qfrozen_cnt[0]++;
while ((devq->alloc_queue.entries > 0)
&& (devq->alloc_openings > 0)
- && (devq->alloc_queue.qfrozen_cnt <= 1)) {
+ && (devq->alloc_queue.qfrozen_cnt[0] <= 1)) {
struct cam_ed_qinfo *qinfo;
struct cam_ed *device;
union ccb *work_ccb;
@@ -3237,7 +3248,6 @@ xpt_run_dev_allocq(struct cam_eb *bus)
qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->alloc_queue,
CAMQ_HEAD);
device = qinfo->device;
-
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
("running device %p\n", device));
@@ -3271,15 +3281,13 @@ xpt_run_dev_allocq(struct cam_eb *bus)
break;
}
- if (drvq->entries > 0) {
- /* We have more work. Attempt to reschedule */
- xpt_schedule_dev_allocq(bus, device);
- }
+ /* We may have more work. Attempt to reschedule. */
+ xpt_schedule_dev_allocq(bus, device);
}
- devq->alloc_queue.qfrozen_cnt--;
+ devq->alloc_queue.qfrozen_cnt[0]--;
}
-void
+static void
xpt_run_dev_sendq(struct cam_eb *bus)
{
struct cam_devq *devq;
@@ -3288,10 +3296,10 @@ xpt_run_dev_sendq(struct cam_eb *bus)
devq = bus->sim->devq;
- devq->send_queue.qfrozen_cnt++;
+ devq->send_queue.qfrozen_cnt[0]++;
while ((devq->send_queue.entries > 0)
&& (devq->send_openings > 0)
- && (devq->send_queue.qfrozen_cnt <= 1)) {
+ && (devq->send_queue.qfrozen_cnt[0] <= 1)) {
struct cam_ed_qinfo *qinfo;
struct cam_ed *device;
union ccb *work_ccb;
@@ -3300,15 +3308,6 @@ xpt_run_dev_sendq(struct cam_eb *bus)
qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->send_queue,
CAMQ_HEAD);
device = qinfo->device;
-
- /*
- * If the device has been "frozen", don't attempt
- * to run it.
- */
- if (device->ccbq.queue.qfrozen_cnt > 0) {
- continue;
- }
-
CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
("running device %p\n", device));
@@ -3328,7 +3327,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
* the device queue until we have a slot
* available.
*/
- device->ccbq.queue.qfrozen_cnt++;
+ xpt_freeze_devq(work_ccb->ccb_h.path, 1);
STAILQ_INSERT_TAIL(&xsoftc.highpowerq,
&work_ccb->ccb_h,
xpt_links.stqe);
@@ -3350,15 +3349,14 @@ xpt_run_dev_sendq(struct cam_eb *bus)
devq->send_openings--;
devq->send_active++;
- if (device->ccbq.queue.entries > 0)
- xpt_schedule_dev_sendq(bus, device);
+ xpt_schedule_dev_sendq(bus, device);
if (work_ccb && (work_ccb->ccb_h.flags & CAM_DEV_QFREEZE) != 0){
/*
* The client wants to freeze the queue
* after this CCB is sent.
*/
- device->ccbq.queue.qfrozen_cnt++;
+ xpt_freeze_devq(work_ccb->ccb_h.path, 1);
}
/* In Target mode, the peripheral driver knows best... */
@@ -3383,7 +3381,7 @@ xpt_run_dev_sendq(struct cam_eb *bus)
sim = work_ccb->ccb_h.path->bus->sim;
(*(sim->sim_action))(sim, work_ccb);
}
- devq->send_queue.qfrozen_cnt--;
+ devq->send_queue.qfrozen_cnt[0]--;
}
/*
@@ -3789,13 +3787,9 @@ xpt_release_ccb(union ccb *free_ccb)
}
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)) {
+ if (device_is_alloc_queued(device) == 0)
xpt_schedule_dev_allocq(bus, device);
- }
- if (dev_allocq_is_runnable(sim->devq))
- xpt_run_dev_allocq(bus);
+ xpt_run_dev_allocq(bus);
}
/* Functions accessed by SIM drivers */
@@ -3821,7 +3815,7 @@ 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;
- struct cam_path path;
+ struct cam_path *path;
cam_status status;
mtx_assert(sim->mtx, MA_OWNED);
@@ -3833,6 +3827,11 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
/* Couldn't satisfy request */
return (CAM_RESRC_UNAVAIL);
}
+ path = (struct cam_path *)malloc(sizeof(*path), M_CAMXPT, M_NOWAIT);
+ if (path == NULL) {
+ free(new_bus, M_CAMXPT);
+ return (CAM_RESRC_UNAVAIL);
+ }
if (strcmp(sim->sim_name, "xpt") != 0) {
sim->path_id =
@@ -3867,13 +3866,12 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
*/
new_bus->xport = &xport_default;
- bzero(&path, sizeof(path));
- status = xpt_compile_path(&path, /*periph*/NULL, sim->path_id,
+ status = xpt_compile_path(path, /*periph*/NULL, sim->path_id,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP)
printf("xpt_compile_path returned %d\n", status);
- xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -3899,9 +3897,17 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
/* Notify interested parties */
if (sim->path_id != CAM_XPT_PATH_ID) {
- xpt_async(AC_PATH_REGISTERED, &path, &cpi);
- }
- xpt_release_path(&path);
+ union ccb *scan_ccb;
+
+ xpt_async(AC_PATH_REGISTERED, path, &cpi);
+ /* Initiate bus rescan. */
+ scan_ccb = xpt_alloc_ccb_nowait();
+ scan_ccb->ccb_h.path = path;
+ scan_ccb->ccb_h.func_code = XPT_SCAN_BUS;
+ scan_ccb->crcn.flags = 0;
+ xpt_rescan(scan_ccb);
+ } else
+ xpt_free_path(path);
return (CAM_SUCCESS);
}
@@ -4110,12 +4116,34 @@ xpt_dev_async_default(u_int32_t async_code, struct cam_eb *bus,
}
u_int32_t
-xpt_freeze_devq(struct cam_path *path, u_int count)
+xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl, u_int count)
{
+ struct cam_ed *dev = path->device;
mtx_assert(path->bus->sim->mtx, MA_OWNED);
- path->device->ccbq.queue.qfrozen_cnt += count;
- return (path->device->ccbq.queue.qfrozen_cnt);
+ dev->sim->devq->alloc_openings +=
+ cam_ccbq_freeze(&dev->ccbq, rl, count);
+ /* Remove frozen device from allocq. */
+ if (device_is_alloc_queued(dev) &&
+ cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
+ CAMQ_GET_PRIO(&dev->drvq)))) {
+ camq_remove(&dev->sim->devq->alloc_queue,
+ dev->alloc_ccb_entry.pinfo.index);
+ }
+ /* Remove frozen device from sendq. */
+ if (device_is_send_queued(dev) &&
+ cam_ccbq_frozen_top(&dev->ccbq)) {
+ camq_remove(&dev->sim->devq->send_queue,
+ dev->send_ccb_entry.pinfo.index);
+ }
+ return (dev->ccbq.queue.qfrozen_cnt[rl]);
+}
+
+u_int32_t
+xpt_freeze_devq(struct cam_path *path, u_int count)
+{
+
+ return (xpt_freeze_devq_rl(path, 0, count));
}
u_int32_t
@@ -4123,8 +4151,8 @@ xpt_freeze_simq(struct cam_sim *sim, u_int count)
{
mtx_assert(sim->mtx, MA_OWNED);
- sim->devq->send_queue.qfrozen_cnt += count;
- return (sim->devq->send_queue.qfrozen_cnt);
+ sim->devq->send_queue.qfrozen_cnt[0] += count;
+ return (sim->devq->send_queue.qfrozen_cnt[0]);
}
static void
@@ -4134,7 +4162,7 @@ xpt_release_devq_timeout(void *arg)
device = (struct cam_ed *)arg;
- xpt_release_devq_device(device, /*count*/1, /*run_queue*/TRUE);
+ xpt_release_devq_device(device, /*rl*/0, /*count*/1, /*run_queue*/TRUE);
}
void
@@ -4142,51 +4170,59 @@ xpt_release_devq(struct cam_path *path, u_int count, int run_queue)
{
mtx_assert(path->bus->sim->mtx, MA_OWNED);
- xpt_release_devq_device(path->device, count, run_queue);
+ xpt_release_devq_device(path->device, /*rl*/0, count, run_queue);
}
-static void
-xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue)
+void
+xpt_release_devq_rl(struct cam_path *path, cam_rl rl, u_int count, int run_queue)
{
- int rundevq;
-
- rundevq = 0;
- if (dev->ccbq.queue.qfrozen_cnt > 0) {
-
- count = (count > dev->ccbq.queue.qfrozen_cnt) ?
- dev->ccbq.queue.qfrozen_cnt : count;
- dev->ccbq.queue.qfrozen_cnt -= count;
- if (dev->ccbq.queue.qfrozen_cnt == 0) {
+ mtx_assert(path->bus->sim->mtx, MA_OWNED);
- /*
- * No longer need to wait for a successful
- * command completion.
- */
- dev->flags &= ~CAM_DEV_REL_ON_COMPLETE;
+ xpt_release_devq_device(path->device, rl, count, run_queue);
+}
- /*
- * Remove any timeouts that might be scheduled
- * to release this queue.
- */
- if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) {
- callout_stop(&dev->callout);
- dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING;
- }
+static void
+xpt_release_devq_device(struct cam_ed *dev, cam_rl rl, u_int count, int run_queue)
+{
- /*
- * Now that we are unfrozen schedule the
- * device so any pending transactions are
- * run.
- */
- if ((dev->ccbq.queue.entries > 0)
- && (xpt_schedule_dev_sendq(dev->target->bus, dev))
- && (run_queue != 0)) {
- rundevq = 1;
- }
+ if (count > dev->ccbq.queue.qfrozen_cnt[rl]) {
+#ifdef INVARIANTS
+ printf("xpt_release_devq(%d): requested %u > present %u\n",
+ rl, count, dev->ccbq.queue.qfrozen_cnt[rl]);
+#endif
+ count = dev->ccbq.queue.qfrozen_cnt[rl];
+ }
+ dev->sim->devq->alloc_openings -=
+ cam_ccbq_release(&dev->ccbq, rl, count);
+ if (cam_ccbq_frozen(&dev->ccbq, CAM_PRIORITY_TO_RL(
+ CAMQ_GET_PRIO(&dev->drvq))) == 0) {
+ if (xpt_schedule_dev_allocq(dev->target->bus, dev))
+ xpt_run_dev_allocq(dev->target->bus);
+ }
+ if (cam_ccbq_frozen_top(&dev->ccbq) == 0) {
+ /*
+ * No longer need to wait for a successful
+ * command completion.
+ */
+ dev->flags &= ~CAM_DEV_REL_ON_COMPLETE;
+ /*
+ * Remove any timeouts that might be scheduled
+ * to release this queue.
+ */
+ if ((dev->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0) {
+ callout_stop(&dev->callout);
+ dev->flags &= ~CAM_DEV_REL_TIMEOUT_PENDING;
}
+ if (run_queue == 0)
+ return;
+ /*
+ * Now that we are unfrozen schedule the
+ * device so any pending transactions are
+ * run.
+ */
+ if (xpt_schedule_dev_sendq(dev->target->bus, dev))
+ xpt_run_dev_sendq(dev->target->bus);
}
- if (rundevq != 0)
- xpt_run_dev_sendq(dev->target->bus);
}
void
@@ -4195,32 +4231,33 @@ xpt_release_simq(struct cam_sim *sim, int run_queue)
struct camq *sendq;
mtx_assert(sim->mtx, MA_OWNED);
-
sendq = &(sim->devq->send_queue);
- if (sendq->qfrozen_cnt > 0) {
+ if (sendq->qfrozen_cnt[0] <= 0) {
+#ifdef INVARIANTS
+ printf("xpt_release_simq: requested 1 > present %u\n",
+ sendq->qfrozen_cnt[0]);
+#endif
+ } else
+ sendq->qfrozen_cnt[0]--;
+ if (sendq->qfrozen_cnt[0] == 0) {
+ /*
+ * If there is a timeout scheduled to release this
+ * sim queue, remove it. The queue frozen count is
+ * already at 0.
+ */
+ if ((sim->flags & CAM_SIM_REL_TIMEOUT_PENDING) != 0){
+ callout_stop(&sim->callout);
+ sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING;
+ }
+ if (run_queue) {
+ struct cam_eb *bus;
- sendq->qfrozen_cnt--;
- if (sendq->qfrozen_cnt == 0) {
/*
- * If there is a timeout scheduled to release this
- * sim queue, remove it. The queue frozen count is
- * already at 0.
+ * Now that we are unfrozen run the send queue.
*/
- if ((sim->flags & CAM_SIM_REL_TIMEOUT_PENDING) != 0){
- callout_stop(&sim->callout);
- sim->flags &= ~CAM_SIM_REL_TIMEOUT_PENDING;
- }
-
- if (run_queue) {
- struct cam_eb *bus;
-
- /*
- * Now that we are unfrozen run the send queue.
- */
- bus = xpt_find_bus(sim->path_id);
- xpt_run_dev_sendq(bus);
- xpt_release_bus(bus);
- }
+ bus = xpt_find_bus(sim->path_id);
+ xpt_run_dev_sendq(bus);
+ xpt_release_bus(bus);
}
}
}
@@ -4399,7 +4436,7 @@ xpt_alloc_device_default(struct cam_eb *bus, struct cam_et *target,
device->mintags = 1;
device->maxtags = 1;
- bus->sim->max_ccbs = device->ccbq.devq_openings;
+ bus->sim->max_ccbs += device->ccbq.devq_openings;
cur_device = TAILQ_FIRST(&target->ed_entries);
while (cur_device != NULL && cur_device->lun_id < lun_id)
cur_device = TAILQ_NEXT(cur_device, links);
@@ -4629,104 +4666,16 @@ xpt_stop_tags(struct cam_path *path)
xpt_action((union ccb *)&crs);
}
-static int busses_to_config;
-static int busses_to_reset;
-
-static int
-xptconfigbuscountfunc(struct cam_eb *bus, void *arg)
-{
-
- mtx_assert(bus->sim->mtx, MA_OWNED);
-
- if (bus->path_id != CAM_XPT_PATH_ID) {
- struct cam_path path;
- struct ccb_pathinq cpi;
- int can_negotiate;
-
- busses_to_config++;
- xpt_compile_path(&path, NULL, bus->path_id,
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
- xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL);
- cpi.ccb_h.func_code = XPT_PATH_INQ;
- xpt_action((union ccb *)&cpi);
- can_negotiate = cpi.hba_inquiry;
- can_negotiate &= (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE);
- if ((cpi.hba_misc & PIM_NOBUSRESET) == 0
- && can_negotiate)
- busses_to_reset++;
- xpt_release_path(&path);
- }
-
- return(1);
-}
-
-static int
-xptconfigfunc(struct cam_eb *bus, void *arg)
+static void
+xpt_boot_delay(void *arg)
{
- struct cam_path *path;
- union ccb *work_ccb;
- mtx_assert(bus->sim->mtx, MA_OWNED);
-
- if (bus->path_id != CAM_XPT_PATH_ID) {
- cam_status status;
- int can_negotiate;
-
- work_ccb = xpt_alloc_ccb_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){
- printf("xptconfigfunc: xpt_create_path failed with "
- "status %#x for scbus%d\n", status, bus->path_id);
- printf("xptconfigfunc: halting bus configuration\n");
- xpt_free_ccb(work_ccb);
- busses_to_config--;
- xpt_finishconfig(xpt_periph, NULL);
- return(0);
- }
- xpt_setup_ccb(&work_ccb->ccb_h, path, CAM_PRIORITY_NORMAL);
- work_ccb->ccb_h.func_code = XPT_PATH_INQ;
- xpt_action(work_ccb);
- if (work_ccb->ccb_h.status != CAM_REQ_CMP) {
- printf("xptconfigfunc: CPI failed on scbus%d "
- "with status %d\n", bus->path_id,
- work_ccb->ccb_h.status);
- xpt_finishconfig(xpt_periph, work_ccb);
- return(1);
- }
-
- can_negotiate = work_ccb->cpi.hba_inquiry;
- can_negotiate &= (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE);
- if ((work_ccb->cpi.hba_misc & PIM_NOBUSRESET) == 0
- && (can_negotiate != 0)) {
- xpt_setup_ccb(&work_ccb->ccb_h, path, CAM_PRIORITY_NORMAL);
- work_ccb->ccb_h.func_code = XPT_RESET_BUS;
- work_ccb->ccb_h.cbfcnp = NULL;
- CAM_DEBUG(path, CAM_DEBUG_SUBTRACE,
- ("Resetting Bus\n"));
- xpt_action(work_ccb);
- xpt_finishconfig(xpt_periph, work_ccb);
- } else {
- /* Act as though we performed a successful BUS RESET */
- work_ccb->ccb_h.func_code = XPT_RESET_BUS;
- xpt_finishconfig(xpt_periph, work_ccb);
- }
- }
-
- return(1);
+ xpt_release_boot();
}
static void
xpt_config(void *arg)
{
- struct periph_driver **p_drv;
- int i;
-
/*
* Now that interrupts are enabled, go find our devices
*/
@@ -4760,28 +4709,43 @@ xpt_config(void *arg)
#endif /* CAM_DEBUG_BUS */
#endif /* CAMDEBUG */
- /* Register early 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++) {
- if ((p_drv[i]->flags & CAM_PERIPH_DRV_EARLY) != 0)
- (*p_drv[i]->init)();
+ periphdriver_init(1);
+ xpt_hold_boot();
+ callout_init(&xsoftc.boot_callout, 1);
+ callout_reset(&xsoftc.boot_callout, hz * xsoftc.boot_delay / 1000,
+ xpt_boot_delay, NULL);
+ /* Fire up rescan thread. */
+ if (kproc_create(xpt_scanner_thread, NULL, NULL, 0, 0, "xpt_thrd")) {
+ printf("xpt_init: failed to create rescan thread\n");
}
- /*
- * Scan all installed busses.
- */
- xpt_for_all_busses(xptconfigbuscountfunc, NULL);
+}
+
+void
+xpt_hold_boot(void)
+{
+ xpt_lock_buses();
+ xsoftc.buses_to_config++;
+ xpt_unlock_buses();
+}
+
+void
+xpt_release_boot(void)
+{
+ xpt_lock_buses();
+ xsoftc.buses_to_config--;
+ if (xsoftc.buses_to_config == 0 && xsoftc.buses_config_done == 0) {
+ struct xpt_task *task;
- if (busses_to_config == 0) {
+ xsoftc.buses_config_done = 1;
+ xpt_unlock_buses();
/* Call manually because we don't have any busses */
- xpt_finishconfig(xpt_periph, NULL);
- } else {
- if (busses_to_reset > 0 && scsi_delay >= 2000) {
- printf("Waiting %d seconds for SCSI "
- "devices to settle\n", scsi_delay/1000);
+ 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);
}
- xpt_for_all_busses(xptconfigfunc, NULL);
- }
+ } else
+ xpt_unlock_buses();
}
/*
@@ -4809,72 +4773,23 @@ xptpassannouncefunc(struct cam_ed *device, void *arg)
static void
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++) {
- if ((p_drv[i]->flags & CAM_PERIPH_DRV_EARLY) == 0)
- (*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);
+ periphdriver_init(2);
+ /*
+ * 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;
- }
+ /* 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"));
- switch(done_ccb->ccb_h.func_code) {
- case XPT_RESET_BUS:
- if (done_ccb->ccb_h.status == CAM_REQ_CMP) {
- done_ccb->ccb_h.func_code = XPT_SCAN_BUS;
- done_ccb->ccb_h.cbfcnp = xpt_finishconfig;
- done_ccb->crcn.flags = 0;
- xpt_action(done_ccb);
- return;
- }
- /* FALLTHROUGH */
- case XPT_SCAN_BUS:
- default:
- xpt_free_path(done_ccb->ccb_h.path);
- busses_to_config--;
- break;
- }
- }
-
- if (busses_to_config == 0) {
- task = malloc(sizeof(struct xpt_task), M_CAMXPT, M_NOWAIT);
- if (task != NULL) {
- TASK_INIT(&task->task, 0, xpt_finishconfig_task, task);
- taskqueue_enqueue(taskqueue_thread, &task->task);
- }
- }
-
- if (done_ccb != NULL)
- xpt_free_ccb(done_ccb);
-}
-
cam_status
xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg,
struct cam_path *path)
@@ -4894,7 +4809,7 @@ xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg,
xptpath = 1;
}
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
+ xpt_setup_ccb(&csa.ccb_h, path, CAM_PRIORITY_NORMAL);
csa.ccb_h.func_code = XPT_SASYNC_CB;
csa.event_enable = event;
csa.callback = cbfunc;
@@ -5047,26 +4962,19 @@ camisr_runqueue(void *V_queue)
cam_ccbq_ccb_done(&dev->ccbq, (union ccb *)ccb_h);
ccb_h->path->bus->sim->devq->send_active--;
ccb_h->path->bus->sim->devq->send_openings++;
+ runq = TRUE;
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
&& (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
|| ((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0
&& (dev->ccbq.dev_active == 0))) {
-
xpt_release_devq(ccb_h->path, /*count*/1,
- /*run_queue*/TRUE);
+ /*run_queue*/FALSE);
}
if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
&& (--dev->tag_delay_count == 0))
xpt_start_tags(ccb_h->path);
-
- if ((dev->ccbq.queue.entries > 0)
- && (dev->ccbq.queue.qfrozen_cnt == 0)
- && (device_is_send_queued(dev) == 0)) {
- runq = xpt_schedule_dev_sendq(ccb_h->path->bus,
- dev);
- }
}
if (ccb_h->status & CAM_RELEASE_SIMQ) {
diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h
index 283cad1..61a7f3f 100644
--- a/sys/cam/cam_xpt.h
+++ b/sys/cam/cam_xpt.h
@@ -87,6 +87,9 @@ SLIST_HEAD(periph_list, cam_periph);
void xpt_action(union ccb *new_ccb);
void xpt_action_default(union ccb *new_ccb);
+union ccb *xpt_alloc_ccb(void);
+union ccb *xpt_alloc_ccb_nowait(void);
+void xpt_free_ccb(union ccb *free_ccb);
void xpt_setup_ccb(struct ccb_hdr *ccb_h,
struct cam_path *path,
u_int32_t priority);
@@ -115,6 +118,8 @@ struct cam_periph *xpt_path_periph(struct cam_path *path);
void xpt_async(u_int32_t async_code, struct cam_path *path,
void *async_arg);
void xpt_rescan(union ccb *ccb);
+void xpt_hold_boot(void);
+void xpt_release_boot(void);
void xpt_lock_buses(void);
void xpt_unlock_buses(void);
cam_status xpt_register_async(int event, ac_callback_t *cbfunc,
diff --git a/sys/cam/cam_xpt_internal.h b/sys/cam/cam_xpt_internal.h
index 146764e..b1fbaaf 100644
--- a/sys/cam/cam_xpt_internal.h
+++ b/sys/cam/cam_xpt_internal.h
@@ -172,7 +172,6 @@ struct cam_ed * xpt_alloc_device(struct cam_eb *bus,
lun_id_t lun_id);
void xpt_acquire_device(struct cam_ed *device);
void xpt_release_device(struct cam_ed *device);
-void xpt_run_dev_sendq(struct cam_eb *bus);
int xpt_schedule_dev(struct camq *queue, cam_pinfo *dev_pinfo,
u_int32_t new_priority);
u_int32_t xpt_dev_ccbq_resize(struct cam_path *path, int newopenings);
diff --git a/sys/cam/cam_xpt_periph.h b/sys/cam/cam_xpt_periph.h
index dbfb55e..867b1c1 100644
--- a/sys/cam/cam_xpt_periph.h
+++ b/sys/cam/cam_xpt_periph.h
@@ -39,9 +39,6 @@
/* Functions accessed by the peripheral drivers */
#ifdef _KERNEL
void xpt_polled_action(union ccb *ccb);
-union ccb *xpt_alloc_ccb(void);
-union ccb *xpt_alloc_ccb_nowait(void);
-void xpt_free_ccb(union ccb *free_ccb);
void xpt_release_ccb(union ccb *released_ccb);
void xpt_schedule(struct cam_periph *perph, u_int32_t new_priority);
int32_t xpt_add_periph(struct cam_periph *periph);
diff --git a/sys/cam/cam_xpt_sim.h b/sys/cam/cam_xpt_sim.h
index e64c67c..323f786 100644
--- a/sys/cam/cam_xpt_sim.h
+++ b/sys/cam/cam_xpt_sim.h
@@ -43,8 +43,12 @@ 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);
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
-void xpt_release_devq(struct cam_path *path, u_int count,
- int run_queue);
+u_int32_t xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl,
+ u_int count);
+void xpt_release_devq(struct cam_path *path,
+ u_int count, int run_queue);
+void xpt_release_devq_rl(struct cam_path *path, cam_rl rl,
+ u_int count, int run_queue);
int xpt_sim_opened(struct cam_sim *sim);
void xpt_done(union ccb *done_ccb);
#endif
diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c
index e6f3a7c..d40a536 100644
--- a/sys/cam/scsi/scsi_all.c
+++ b/sys/cam/scsi/scsi_all.c
@@ -2880,7 +2880,7 @@ scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
}
}
}
-#ifdef KERNEL
+#ifdef _KERNEL
if (bootverbose)
sense_flags |= SF_PRINT_ALWAYS;
#endif
@@ -2995,27 +2995,29 @@ scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
struct scsi_inquiry_data *inq_data;
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
#ifdef _KERNEL
- struct ccb_getdev cgd;
+ struct ccb_getdev *cgd;
#endif /* _KERNEL */
#ifdef _KERNEL
+ if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
+ return(-1);
/*
* Get the device information.
*/
- xpt_setup_ccb(&cgd.ccb_h,
+ xpt_setup_ccb(&cgd->ccb_h,
csio->ccb_h.path,
CAM_PRIORITY_NORMAL);
- cgd.ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action((union ccb *)&cgd);
+ cgd->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)cgd);
/*
* If the device is unconfigured, just pretend that it is a hard
* drive. scsi_op_desc() needs this.
*/
- if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
- cgd.inq_data.device = T_DIRECT;
+ if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
+ cgd->inq_data.device = T_DIRECT;
- inq_data = &cgd.inq_data;
+ inq_data = &cgd->inq_data;
#else /* !_KERNEL */
@@ -3055,7 +3057,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
struct scsi_sense_data *sense;
struct scsi_inquiry_data *inq_data;
#ifdef _KERNEL
- struct ccb_getdev cgd;
+ struct ccb_getdev *cgd;
#endif /* _KERNEL */
u_int32_t info;
int error_code;
@@ -3083,23 +3085,25 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
#endif /* _KERNEL/!_KERNEL */
#ifdef _KERNEL
+ if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
+ return(-1);
/*
* Get the device information.
*/
- xpt_setup_ccb(&cgd.ccb_h,
+ xpt_setup_ccb(&cgd->ccb_h,
csio->ccb_h.path,
CAM_PRIORITY_NORMAL);
- cgd.ccb_h.func_code = XPT_GDEV_TYPE;
- xpt_action((union ccb *)&cgd);
+ cgd->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)cgd);
/*
* If the device is unconfigured, just pretend that it is a hard
* drive. scsi_op_desc() needs this.
*/
- if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
- cgd.inq_data.device = T_DIRECT;
+ if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
+ cgd->inq_data.device = T_DIRECT;
- inq_data = &cgd.inq_data;
+ inq_data = &cgd->inq_data;
#else /* !_KERNEL */
@@ -3125,9 +3129,12 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
* If the sense data is a physical pointer, forget it.
*/
if (csio->ccb_h.flags & CAM_SENSE_PTR) {
- if (csio->ccb_h.flags & CAM_SENSE_PHYS)
+ if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
+#ifdef _KERNEL
+ xpt_free_ccb((union ccb*)cgd);
+#endif /* _KERNEL/!_KERNEL */
return(-1);
- else {
+ } else {
/*
* bcopy the pointer to avoid unaligned access
* errors on finicky architectures. We don't
@@ -3145,9 +3152,12 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
* dumped on one of the bogus pointer deferences above
* already.)
*/
- if (csio->ccb_h.flags & CAM_SENSE_PHYS)
+ if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
+#ifdef _KERNEL
+ xpt_free_ccb((union ccb*)cgd);
+#endif /* _KERNEL/!_KERNEL */
return(-1);
- else
+ } else
sense = &csio->sense_data;
}
@@ -3157,9 +3167,10 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
error_code = sense->error_code & SSD_ERRCODE;
sense_key = sense->flags & SSD_KEY;
+ sbuf_printf(sb, "SCSI sense: ");
switch (error_code) {
case SSD_DEFERRED_ERROR:
- sbuf_printf(sb, "Deferred Error: ");
+ sbuf_printf(sb, "Deferred error: ");
/* FALLTHROUGH */
case SSD_CURRENT_ERROR:
@@ -3212,8 +3223,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
}
}
- sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq,
- path_str, asc_desc);
+ sbuf_printf(sb, " asc:%x,%x (%s)", asc, ascq, asc_desc);
if (sense->extra_len >= 7 && sense->fru) {
sbuf_printf(sb, " field replaceable unit: %x",
@@ -3265,7 +3275,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
}
default:
- sbuf_printf(sb, "Sense Error Code 0x%x", sense->error_code);
+ sbuf_printf(sb, "Error code 0x%x", sense->error_code);
if (sense->error_code & SSD_ERRCODE_VALID) {
sbuf_printf(sb, " at block no. %d (decimal)",
info = scsi_4btoul(sense->info));
@@ -3274,6 +3284,9 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
sbuf_printf(sb, "\n");
+#ifdef _KERNEL
+ xpt_free_ccb((union ccb*)cgd);
+#endif /* _KERNEL/!_KERNEL */
return(0);
}
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index cf99eea..9d5dcf6 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -433,7 +433,7 @@ cdcleanup(struct cam_periph *periph)
callout_stop(&softc->changer->short_handle);
softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
}
- softc->changer->devq.qfrozen_cnt--;
+ softc->changer->devq.qfrozen_cnt[0]--;
softc->changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(softc->changer);
}
@@ -972,9 +972,9 @@ cdregisterexit:
(void)cam_periph_hold(periph, PRIBIO);
if ((softc->flags & CD_FLAG_CHANGER) == 0)
- xpt_schedule(periph, /*priority*/5);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
else
- cdschedule(periph, /*priority*/ 5);
+ cdschedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
@@ -1167,13 +1167,13 @@ cdrunchangerqueue(void *arg)
* If the changer queue is frozen, that means we have an active
* device.
*/
- if (changer->devq.qfrozen_cnt > 0) {
+ if (changer->devq.qfrozen_cnt[0] > 0) {
/*
* We always need to reset the frozen count and clear the
* active flag.
*/
- changer->devq.qfrozen_cnt--;
+ changer->devq.qfrozen_cnt[0]--;
changer->cur_device->flags &= ~CD_FLAG_ACTIVE;
changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP;
@@ -1208,7 +1208,7 @@ cdrunchangerqueue(void *arg)
changer->cur_device = softc;
- changer->devq.qfrozen_cnt++;
+ changer->devq.qfrozen_cnt[0]++;
softc->flags |= CD_FLAG_ACTIVE;
/* Just in case this device is waiting */
@@ -1465,7 +1465,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
bioq_remove(&softc->bio_queue, bp);
scsi_read_write(&start_ccb->csio,
- /*retries*/cd_retry_count,
+ /*retries*/ cd_retry_count,
/* cbfcnp */ cddone,
MSG_SIMPLE_Q_TAG,
/* read */bp->bio_cmd == BIO_READ,
@@ -1516,7 +1516,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
}
csio = &start_ccb->csio;
scsi_read_capacity(csio,
- /*retries*/1,
+ /*retries*/ cd_retry_count,
cddone,
MSG_SIMPLE_Q_TAG,
rcap,
@@ -2733,7 +2733,7 @@ cdprevent(struct cam_periph *periph, int action)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_prevent(&ccb->csio,
- /*retries*/ 1,
+ /*retries*/ cd_retry_count,
cddone,
MSG_SIMPLE_Q_TAG,
action,
@@ -2911,7 +2911,7 @@ cdsize(struct cam_periph *periph, u_int32_t *size)
return (ENOMEM);
scsi_read_capacity(&ccb->csio,
- /*retries*/ 1,
+ /*retries*/ cd_retry_count,
cddone,
MSG_SIMPLE_Q_TAG,
rcap_buf,
@@ -3159,7 +3159,7 @@ cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start,
csio = &ccb->csio;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_IN,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3206,7 +3206,7 @@ cdreadsubchannel(struct cam_periph *periph, u_int32_t mode,
csio = &ccb->csio;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_IN,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3267,7 +3267,7 @@ cdgetmode(struct cam_periph *periph, struct cd_mode_params *data,
param_len = min(param_len, data->alloc_len);
scsi_mode_sense_len(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* dbd */ 0,
@@ -3410,7 +3410,7 @@ cdsetmode(struct cam_periph *periph, struct cd_mode_params *data)
param_len = min(param_len, data->alloc_len);
scsi_mode_select_len(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* scsi_page_fmt */ 1,
@@ -3472,7 +3472,7 @@ cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len)
cdb_len = sizeof(*scsi_cmd);
}
cam_fill_csio(csio,
- /*retries*/2,
+ /*retries*/ cd_retry_count,
cddone,
/*flags*/CAM_DIR_NONE,
MSG_SIMPLE_Q_TAG,
@@ -3506,7 +3506,7 @@ cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts,
csio = &ccb->csio;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_NONE,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3552,7 +3552,7 @@ cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex,
csio = &ccb->csio;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_NONE,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3594,7 +3594,7 @@ cdpause(struct cam_periph *periph, u_int32_t go)
csio = &ccb->csio;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_NONE,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3629,7 +3629,7 @@ cdstartunit(struct cam_periph *periph, int load)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_start_stop(&ccb->csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* start */ TRUE,
@@ -3657,7 +3657,7 @@ cdstopunit(struct cam_periph *periph, u_int32_t eject)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_start_stop(&ccb->csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* start */ FALSE,
@@ -3693,7 +3693,7 @@ cdsetspeed(struct cam_periph *periph, u_int32_t rdspeed, u_int32_t wrspeed)
wrspeed *= 177;
cam_fill_csio(csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* flags */ CAM_DIR_NONE,
/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -3768,7 +3768,7 @@ cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_report_key(&ccb->csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* lba */ lba,
@@ -3946,7 +3946,7 @@ cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_send_key(&ccb->csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* agid */ authinfo->agid,
@@ -4050,7 +4050,7 @@ cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
scsi_read_dvd_structure(&ccb->csio,
- /* retries */ 1,
+ /* retries */ cd_retry_count,
/* cbfcnp */ cddone,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* lba */ address,
diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c
index 2829a15..107f22b 100644
--- a/sys/cam/scsi/scsi_ch.c
+++ b/sys/cam/scsi/scsi_ch.c
@@ -376,7 +376,7 @@ chregister(struct cam_periph *periph, void *arg)
* This first call can't block
*/
(void)cam_periph_hold(periph, PRIBIO);
- xpt_schedule(periph, /*priority*/5);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
return(CAM_REQ_CMP);
}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index d05376e..77652b2 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1272,7 +1272,7 @@ daregister(struct cam_periph *periph, void *arg)
* the end of probe.
*/
(void)cam_periph_hold(periph, PRIBIO);
- xpt_schedule(periph, /*priority*/5);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
/*
* Schedule a periodic event to occasionally send an
diff --git a/sys/cam/scsi/scsi_low.c b/sys/cam/scsi/scsi_low.c
index 1cee43d..1b2f4f6 100644
--- a/sys/cam/scsi/scsi_low.c
+++ b/sys/cam/scsi/scsi_low.c
@@ -895,8 +895,6 @@ scsi_low_target_open(link, cf)
#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb()
static void scsi_low_poll_cam(struct cam_sim *);
-static void scsi_low_cam_rescan_callback(struct cam_periph *, union ccb *);
-static void scsi_low_rescan_bus_cam(struct scsi_low_softc *);
void scsi_low_scsi_action_cam(struct cam_sim *, union ccb *);
static int scsi_low_attach_cam(struct scsi_low_softc *);
@@ -954,38 +952,6 @@ scsi_low_poll_cam(sim)
}
}
-static void
-scsi_low_cam_rescan_callback(periph, ccb)
- struct cam_periph *periph;
- union ccb *ccb;
-{
-
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
-}
-
-static void
-scsi_low_rescan_bus_cam(slp)
- struct scsi_low_softc *slp;
-{
- struct cam_path *path;
- union ccb *ccb;
- cam_status status;
-
- status = xpt_create_path(&path, xpt_periph,
- cam_sim_path(slp->sl_si.sim), -1, 0);
- if (status != CAM_REQ_CMP)
- return;
-
- ccb = xpt_alloc_ccb();
- bzero(ccb, sizeof(union ccb));
- xpt_setup_ccb(&ccb->ccb_h, path, 5);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = scsi_low_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
-}
-
void
scsi_low_scsi_action_cam(sim, ccb)
struct cam_sim *sim;
@@ -1376,8 +1342,6 @@ scsi_low_world_start_cam(slp)
struct scsi_low_softc *slp;
{
- if (!cold)
- scsi_low_rescan_bus_cam(slp);
return 0;
}
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 7551891..9464ca2 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -563,12 +563,10 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
* that request. Otherwise, it's up to the user to perform any
* error recovery.
*/
- error = cam_periph_runccb(ccb,
- (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
- passerror : NULL,
- /* cam_flags */ CAM_RETRY_SELTO,
- /* sense_flags */SF_RETRY_UA,
- softc->device_stats);
+ cam_periph_runccb(ccb,
+ (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? passerror : NULL,
+ /* cam_flags */ CAM_RETRY_SELTO, /* sense_flags */SF_RETRY_UA,
+ softc->device_stats);
if (need_unmap != 0)
cam_periph_unmapmem(ccb, &mapinfo);
@@ -577,7 +575,7 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
bcopy(ccb, inccb, sizeof(union ccb));
- return(error);
+ return(0);
}
static int
diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c
index cae7be6..7639377 100644
--- a/sys/cam/scsi/scsi_xpt.c
+++ b/sys/cam/scsi/scsi_xpt.c
@@ -616,6 +616,11 @@ proberegister(struct cam_periph *periph, void *arg)
*/
cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
scsi_delay);
+ /*
+ * Ensure nobody slip in until probe finish.
+ */
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
probeschedule(periph);
return(CAM_REQ_CMP);
}
@@ -630,7 +635,7 @@ probeschedule(struct cam_periph *periph)
softc = (probe_softc *)periph->softc;
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
- xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -668,7 +673,7 @@ probeschedule(struct cam_periph *periph)
else
softc->flags &= ~PROBE_NO_ANNOUNCE;
- xpt_schedule(periph, ccb->ccb_h.pinfo.priority);
+ xpt_schedule(periph, CAM_PRIORITY_XPT);
}
static void
@@ -881,7 +886,7 @@ proberequestdefaultnegotiation(struct cam_periph *periph)
{
struct ccb_trans_settings cts;
- xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -903,7 +908,7 @@ proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
struct ccb_trans_settings_spi *spi;
memset(&cts, 0, sizeof (cts));
- xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
@@ -1420,6 +1425,8 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
done_ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(done_ccb);
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
cam_periph_invalidate(periph);
cam_periph_release_locked(periph);
} else {
@@ -1491,7 +1498,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
case XPT_SCAN_BUS:
{
scsi_scan_bus_info *scan_info;
- union ccb *work_ccb;
+ union ccb *work_ccb, *reset_ccb;
struct cam_path *path;
u_int i;
u_int max_target;
@@ -1526,6 +1533,26 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
return;
}
+ /* We may need to reset bus first, if we haven't done it yet. */
+ if ((work_ccb->cpi.hba_inquiry &
+ (PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
+ !(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
+ !timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) {
+ reset_ccb = xpt_alloc_ccb_nowait();
+ xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
+ CAM_PRIORITY_NONE);
+ reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
+ xpt_action(reset_ccb);
+ if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
+ request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
+ xpt_free_ccb(reset_ccb);
+ xpt_free_ccb(work_ccb);
+ xpt_done(request_ccb);
+ return;
+ }
+ xpt_free_ccb(reset_ccb);
+ }
+
/* Save some state for use while we probe for devices */
scan_info = (scsi_scan_bus_info *)
malloc(sizeof(scsi_scan_bus_info), M_CAMXPT, M_NOWAIT);
@@ -1756,10 +1783,9 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
struct cam_path *new_path;
struct cam_periph *old_periph;
- CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
- ("scsi_scan_lun\n"));
+ CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n"));
- xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -1809,7 +1835,7 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
free(new_path, M_CAMXPT);
return;
}
- xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
request_ccb->ccb_h.cbfcnp = xptscandone;
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
request_ccb->crcn.flags = flags;
@@ -1907,7 +1933,7 @@ scsi_devise_transport(struct cam_path *path)
struct scsi_inquiry_data *inq_buf;
/* Get transport information from the SIM */
- xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -1967,7 +1993,7 @@ scsi_devise_transport(struct cam_path *path)
*/
/* Tell the controller what we think */
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.transport = path->device->transport;
@@ -2095,7 +2121,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
inq_data = &device->inq_data;
scsi = &cts->proto_specific.scsi;
- xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
@@ -2116,7 +2142,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
* Perform sanity checking against what the
* controller and device can do.
*/
- xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cur_cts.type = cts->type;
xpt_action((union ccb *)&cur_cts);
@@ -2300,7 +2326,7 @@ scsi_toggle_tags(struct cam_path *path)
&& (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) {
struct ccb_trans_settings cts;
- xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+ xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.protocol = PROTO_SCSI;
cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
cts.transport = XPORT_UNSPECIFIED;
@@ -2350,11 +2376,18 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
/*
* Allow transfer negotiation to occur in a
- * tag free environment.
+ * tag free environment and after settle delay.
*/
if (async_code == AC_SENT_BDR
- || async_code == AC_BUS_RESET)
+ || async_code == AC_BUS_RESET) {
+ cam_freeze_devq(&newpath);
+ cam_release_devq(&newpath,
+ RELSIM_RELEASE_AFTER_TIMEOUT,
+ /*reduction*/0,
+ /*timeout*/scsi_delay,
+ /*getcount_only*/0);
scsi_toggle_tags(&newpath);
+ }
if (async_code == AC_INQ_CHANGED) {
/*
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 789a8aa..ecff8a0 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
/* local prototypes */
@@ -86,7 +85,7 @@ static void ahci_start_fr(device_t dev);
static void ahci_stop_fr(device_t dev);
static int ahci_sata_connect(struct ahci_channel *ch);
-static int ahci_sata_phy_reset(device_t dev, int quick);
+static int ahci_sata_phy_reset(device_t dev);
static void ahci_issue_read_log(device_t dev);
static void ahci_process_read_log(device_t dev, union ccb *ccb);
@@ -348,6 +347,8 @@ ahci_attach(device_t dev)
ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
if (version >= 0x00010020)
ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
+ if (ctlr->caps & AHCI_CAP_EMS)
+ ctlr->capsem = ATA_INL(ctlr->r_mem, AHCI_EM_CTL);
ctlr->ichannels = ATA_INL(ctlr->r_mem, AHCI_PI);
if (ctlr->quirks & AHCI_Q_1CH) {
ctlr->caps &= ~AHCI_CAP_NPMASK;
@@ -417,6 +418,17 @@ ahci_attach(device_t dev)
(ctlr->caps2 & AHCI_CAP2_NVMP) ? " NVMP":"",
(ctlr->caps2 & AHCI_CAP2_BOH) ? " BOH":"");
}
+ if (bootverbose && (ctlr->caps & AHCI_CAP_EMS)) {
+ device_printf(dev, "EM Caps: %s%s%s%s%s%s%s%s\n",
+ (ctlr->capsem & AHCI_EM_PM) ? " PM":"",
+ (ctlr->capsem & AHCI_EM_ALHD) ? " ALHD":"",
+ (ctlr->capsem & AHCI_EM_XMT) ? " XMT":"",
+ (ctlr->capsem & AHCI_EM_SMB) ? " SMB":"",
+ (ctlr->capsem & AHCI_EM_SGPIO) ? " SGPIO":"",
+ (ctlr->capsem & AHCI_EM_SES2) ? " SES-2":"",
+ (ctlr->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"",
+ (ctlr->capsem & AHCI_EM_LED) ? " LED":"");
+ }
/* Attach all channels on this controller */
for (unit = 0; unit < ctlr->channels; unit++) {
if ((ctlr->ichannels & (1 << unit)) == 0)
@@ -1131,6 +1143,8 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
if ((serr & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
u_int32_t status = ATA_INL(ch->r_mem, AHCI_P_SSTS);
+ union ccb *ccb;
+
if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
@@ -1142,6 +1156,15 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
device_printf(dev, "DISCONNECT requested\n");
ch->devices = 0;
}
+ if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
+ return;
+ if (xpt_create_path(&ccb->ccb_h.path, NULL,
+ cam_sim_path(ch->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_rescan(ccb);
}
}
@@ -1511,6 +1534,13 @@ ahci_execute_transaction(struct ahci_slot *slot)
if (timeout && (count >= timeout)) {
device_printf(ch->dev,
"Poll timeout on slot %d\n", slot->slot);
+ device_printf(dev, "is %08x cs %08x ss %08x "
+ "rs %08x tfd %02x serr %08x\n",
+ ATA_INL(ch->r_mem, AHCI_P_IS),
+ ATA_INL(ch->r_mem, AHCI_P_CI),
+ ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
+ ATA_INL(ch->r_mem, AHCI_P_TFD),
+ ATA_INL(ch->r_mem, AHCI_P_SERR));
et = AHCI_ERR_TIMEOUT;
}
if (et != AHCI_ERR_NONE) {
@@ -1935,7 +1965,7 @@ ahci_wait_ready(device_t dev, int t)
(ATA_S_BUSY | ATA_S_DRQ)) {
DELAY(1000);
if (timeout++ > t) {
- device_printf(dev, "port is not ready (timeout %dms) "
+ device_printf(dev, "device is not ready (timeout %dms) "
"tfd = %08x\n", t, val);
return (EBUSY);
}
@@ -1952,6 +1982,7 @@ ahci_reset(device_t dev)
struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
int i;
+ xpt_freeze_simq(ch->sim, 1);
if (bootverbose)
device_printf(dev, "AHCI reset...\n");
/* Requeue freezed command. */
@@ -1986,7 +2017,7 @@ ahci_reset(device_t dev)
/* Disable port interrupts */
ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
/* Reset and reconnect PHY, */
- if (!ahci_sata_phy_reset(dev, 0)) {
+ if (!ahci_sata_phy_reset(dev)) {
if (bootverbose)
device_printf(dev,
"AHCI reset done: phy reset found no device\n");
@@ -1994,13 +2025,12 @@ ahci_reset(device_t dev)
/* Enable wanted port interrupts */
ATA_OUTL(ch->r_mem, AHCI_P_IE,
(AHCI_P_IX_CPD | AHCI_P_IX_PRC | AHCI_P_IX_PC));
+ xpt_release_simq(ch->sim, TRUE);
return;
}
/* Wait for clearing busy status. */
- if (ahci_wait_ready(dev, 10000)) {
- device_printf(dev, "device ready timeout\n");
+ if (ahci_wait_ready(dev, 15000))
ahci_clo(dev);
- }
ahci_start(dev);
ch->devices = 1;
/* Enable wanted port interrupts */
@@ -2012,6 +2042,7 @@ ahci_reset(device_t dev)
AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
if (bootverbose)
device_printf(dev, "AHCI reset done: device found\n");
+ xpt_release_simq(ch->sim, TRUE);
}
static int
@@ -2104,20 +2135,12 @@ ahci_sata_connect(struct ahci_channel *ch)
}
static int
-ahci_sata_phy_reset(device_t dev, int quick)
+ahci_sata_phy_reset(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
int sata_rev;
uint32_t val;
- if (quick) {
- val = ATA_INL(ch->r_mem, AHCI_P_SCTL);
- if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
- return (ahci_sata_connect(ch));
- }
-
- if (bootverbose)
- device_printf(dev, "hardware reset ...\n");
sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
if (sata_rev == 1)
val = ATA_SC_SPD_SPEED_GEN1;
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index e11f84f..d136d82 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -186,6 +186,20 @@
#define AHCI_CCCC_EN 0x00000001
#define AHCI_CCCP 0x18
+#define AHCI_EM_LOC 0x1C
+#define AHCI_EM_CTL 0x20
+#define AHCI_EM_MR 0x00000001
+#define AHCI_EM_TM 0x00000100
+#define AHCI_EM_RST 0x00000200
+#define AHCI_EM_LED 0x00010000
+#define AHCI_EM_SAFTE 0x00020000
+#define AHCI_EM_SES2 0x00040000
+#define AHCI_EM_SGPIO 0x00080000
+#define AHCI_EM_SMB 0x01000000
+#define AHCI_EM_XMT 0x02000000
+#define AHCI_EM_ALHD 0x04000000
+#define AHCI_EM_PM 0x08000000
+
#define AHCI_CAP2 0x24
#define AHCI_CAP2_BOH 0x00000001
#define AHCI_CAP2_NVMP 0x00000002
@@ -402,6 +416,7 @@ struct ahci_controller {
} irqs[16];
uint32_t caps; /* Controller capabilities */
uint32_t caps2; /* Controller capabilities */
+ uint32_t capsem; /* Controller capabilities */
int quirks;
int numirqs;
int channels;
diff --git a/sys/dev/asr/asr.c b/sys/dev/asr/asr.c
index 2bc5e22..ae363d0 100644
--- a/sys/dev/asr/asr.c
+++ b/sys/dev/asr/asr.c
@@ -130,7 +130,6 @@
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index f342c81..1ad3c51 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
#endif
@@ -289,12 +288,26 @@ ata_detach(device_t dev)
static void
ata_conn_event(void *context, int dummy)
{
- device_t dev = (device_t)context;
- struct ata_channel *ch = device_get_softc(dev);
+ device_t dev = (device_t)context;
+ struct ata_channel *ch = device_get_softc(dev);
+#ifdef ATA_CAM
+ union ccb *ccb;
+#endif
- mtx_lock(&ch->state_mtx);
- ata_reinit(dev);
- mtx_unlock(&ch->state_mtx);
+ mtx_lock(&ch->state_mtx);
+ ata_reinit(dev);
+ mtx_unlock(&ch->state_mtx);
+#ifdef ATA_CAM
+ if ((ccb = xpt_alloc_ccb()) == NULL)
+ return;
+ if (xpt_create_path(&ccb->ccb_h.path, NULL,
+ cam_sim_path(ch->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_rescan(ccb);
+#endif
}
int
@@ -390,6 +403,7 @@ ata_reinit(device_t dev)
/* kick off requests on the queue */
ata_start(dev);
#else
+ xpt_freeze_simq(ch->sim, 1);
if ((request = ch->running)) {
ch->running = NULL;
if (ch->state == ATA_ACTIVE)
@@ -404,6 +418,7 @@ ata_reinit(device_t dev)
ATA_RESET(dev);
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
+ xpt_release_simq(ch->sim, TRUE);
#endif
return(0);
}
diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c
index 84b44c5..3f8e650 100644
--- a/sys/dev/ata/atapi-cam.c
+++ b/sys/dev/ata/atapi-cam.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
@@ -109,7 +108,6 @@ static int atapi_cam_event_handler(module_t mod, int what, void *arg);
/* internal functions */
static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason);
static void setup_async_cb(struct atapi_xpt_softc *, uint32_t);
-static void cam_rescan_callback(struct cam_periph *, union ccb *);
static void cam_rescan(struct cam_sim *);
static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t);
static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *);
@@ -315,6 +313,7 @@ reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
switch (reason) {
case BOOT_ATTACH:
+ case ATTACH:
break;
case RESET:
xpt_async(AC_BUS_RESET, scp->path, NULL);
@@ -322,8 +321,6 @@ reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
if (!dev_changed)
break;
- /*FALLTHROUGH*/
- case ATTACH:
cam_rescan(scp->sim);
break;
}
@@ -822,41 +819,20 @@ atapi_async(void *callback_arg, u_int32_t code,
}
static void
-cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
- if (ccb->ccb_h.status != CAM_REQ_CMP) {
- CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
- ("Rescan failed, 0x%04x\n", ccb->ccb_h.status));
- } else {
- CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
- ("Rescan succeeded\n"));
- }
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
-}
-
-static void
cam_rescan(struct cam_sim *sim)
{
- struct cam_path *path;
union ccb *ccb;
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL)
return;
-
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(sim),
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_free_ccb(ccb);
return;
}
-
- CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
- xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
+ xpt_rescan(ccb);
/* scan is in progress now */
}
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index c5ad417..4e336a9 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -173,8 +173,6 @@ static void ciss_unmap_request(struct ciss_request *cr);
static int ciss_cam_init(struct ciss_softc *sc);
static void ciss_cam_rescan_target(struct ciss_softc *sc,
int bus, int target);
-static void ciss_cam_rescan_all(struct ciss_softc *sc);
-static void ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
static void ciss_cam_action(struct cam_sim *sim, union ccb *ccb);
static int ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
static int ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio);
@@ -2863,13 +2861,6 @@ ciss_cam_init(struct ciss_softc *sc)
mtx_unlock(&sc->ciss_mtx);
}
- /*
- * Initiate a rescan of the bus.
- */
- mtx_lock(&sc->ciss_mtx);
- ciss_cam_rescan_all(sc);
- mtx_unlock(&sc->ciss_mtx);
-
return(0);
}
@@ -2879,53 +2870,26 @@ ciss_cam_init(struct ciss_softc *sc)
static void
ciss_cam_rescan_target(struct ciss_softc *sc, int bus, int target)
{
- struct cam_path *path;
union ccb *ccb;
debug_called(1);
- if ((ccb = malloc(sizeof(union ccb), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) {
+ if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
ciss_printf(sc, "rescan failed (can't allocate CCB)\n");
return;
}
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->ciss_cam_sim[bus]),
- target, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+ cam_sim_path(sc->ciss_cam_sim[bus]),
+ target, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
ciss_printf(sc, "rescan failed (can't create path)\n");
- free(ccb, CISS_MALLOC_CLASS);
+ xpt_free_ccb(ccb);
return;
}
-
- xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = ciss_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
-
+ xpt_rescan(ccb);
/* scan is now in progress */
}
-static void
-ciss_cam_rescan_all(struct ciss_softc *sc)
-{
- int i;
-
- /* Rescan the logical buses */
- for (i = 0; i < sc->ciss_max_logical_bus; i++)
- ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD);
- /* Rescan the physical buses */
- for (i = CISS_PHYSICAL_BASE; i < sc->ciss_max_physical_bus +
- CISS_PHYSICAL_BASE; i++)
- ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD);
-}
-
-static void
-ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, CISS_MALLOC_CLASS);
-}
-
/************************************************************************
* Handle requests coming from CAM
*/
diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c
index 7218bc5..1ea257b 100644
--- a/sys/dev/hptiop/hptiop.c
+++ b/sys/dev/hptiop/hptiop.c
@@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_periph.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
@@ -105,7 +104,6 @@ static int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
struct hpt_iop_ioctl_param *pParams);
static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
struct hpt_iop_ioctl_param *pParams);
-static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
static int hptiop_rescan_bus(struct hpt_iop_hba *hba);
static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
@@ -1035,28 +1033,19 @@ invalid:
static int hptiop_rescan_bus(struct hpt_iop_hba * hba)
{
- struct cam_path *path;
union ccb *ccb;
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(hba->sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
- return(EIO);
- if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
+
+ if ((ccb = xpt_alloc_ccb()) == NULL)
return(ENOMEM);
- bzero(ccb, sizeof(union ccb));
- xpt_setup_ccb(&ccb->ccb_h, path, 5);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = hptiop_bus_scan_cb;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(hba->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return(EIO);
+ }
+ xpt_rescan(ccb);
return(0);
}
-static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
-{
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, M_TEMP);
-}
-
static bus_dmamap_callback_t hptiop_map_srb;
static bus_dmamap_callback_t hptiop_post_scsi_command;
static bus_dmamap_callback_t hptiop_mv_map_ctlcfg;
@@ -1539,8 +1528,6 @@ static int hptiop_attach(device_t dev)
hba->ioctl_dev->si_drv1 = hba;
#endif
- hptiop_rescan_bus(hba);
-
return 0;
diff --git a/sys/dev/hptrr/hptrr_osm_bsd.c b/sys/dev/hptrr/hptrr_osm_bsd.c
index 78c8b60..6bc30c2 100644
--- a/sys/dev/hptrr/hptrr_osm_bsd.c
+++ b/sys/dev/hptrr/hptrr_osm_bsd.c
@@ -989,7 +989,6 @@ static void hpt_stop_tasks(PVBUS_EXT vbus_ext)
static d_open_t hpt_open;
static d_close_t hpt_close;
static d_ioctl_t hpt_ioctl;
-static void hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
static int hpt_rescan_bus(void);
static struct cdevsw hpt_cdevsw = {
@@ -1381,7 +1380,6 @@ invalid:
static int hpt_rescan_bus(void)
{
- struct cam_path *path;
union ccb *ccb;
PVBUS vbus;
PVBUS_EXT vbus_ext;
@@ -1391,17 +1389,15 @@ static int hpt_rescan_bus(void)
#endif
ldm_for_each_vbus(vbus, vbus_ext) {
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(vbus_ext->sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
- return(EIO);
- if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
+ if ((ccb = xpt_alloc_ccb()) == NULL)
return(ENOMEM);
- bzero(ccb, sizeof(union ccb));
- xpt_setup_ccb(&ccb->ccb_h, path, 5);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = hpt_bus_scan_cb;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+ cam_sim_path(vbus_ext->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return(EIO);
+ }
+ xpt_rescan(ccb);
}
#if (__FreeBSD_version >= 500000)
@@ -1410,15 +1406,3 @@ static int hpt_rescan_bus(void)
return(0);
}
-
-static void hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
-{
- if (ccb->ccb_h.status != CAM_REQ_CMP)
- KdPrint(("cam_scan_callback: failure status = %x",ccb->ccb_h.status));
- else
- KdPrint(("Scan bus successfully!"));
-
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, M_TEMP);
- return;
-}
diff --git a/sys/dev/hptrr/os_bsd.h b/sys/dev/hptrr/os_bsd.h
index fb487e8..ec221f3 100644
--- a/sys/dev/hptrr/os_bsd.h
+++ b/sys/dev/hptrr/os_bsd.h
@@ -91,7 +91,6 @@
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_periph.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
diff --git a/sys/dev/mly/mly.c b/sys/dev/mly/mly.c
index 189f539..90f2819 100644
--- a/sys/dev/mly/mly.c
+++ b/sys/dev/mly/mly.c
@@ -101,7 +101,6 @@ static void mly_unmap_command(struct mly_command *mc);
static int mly_cam_attach(struct mly_softc *sc);
static void mly_cam_detach(struct mly_softc *sc);
static void mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target);
-static void mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
static void mly_cam_action(struct cam_sim *sim, union ccb *ccb);
static int mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
static void mly_cam_poll(struct cam_sim *sim);
@@ -2017,29 +2016,18 @@ mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target)
debug_called(1);
- if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
+ if ((ccb = xpt_alloc_ccb()) == NULL) {
mly_printf(sc, "rescan failed (can't allocate CCB)\n");
return;
}
-
- if (xpt_create_path(&sc->mly_cam_path, xpt_periph,
- cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+ cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
mly_printf(sc, "rescan failed (can't create path)\n");
- free(ccb, M_TEMP);
+ xpt_free_ccb(ccb);
return;
}
- xpt_setup_ccb(&ccb->ccb_h, sc->mly_cam_path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_LUN;
- ccb->ccb_h.cbfcnp = mly_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
debug(1, "rescan target %d:%d", bus, target);
- xpt_action(ccb);
-}
-
-static void
-mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
- free(ccb, M_TEMP);
+ xpt_rescan(ccb);
}
/********************************************************************************
diff --git a/sys/dev/mpt/mpt_cam.h b/sys/dev/mpt/mpt_cam.h
index f2faa4a..8a18934 100644
--- a/sys/dev/mpt/mpt_cam.h
+++ b/sys/dev/mpt/mpt_cam.h
@@ -102,7 +102,6 @@
#include <cam/cam_sim.h>
#include <cam/cam_xpt.h>
#include <cam/cam_periph.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
index 5185ec0..d313253 100644
--- a/sys/dev/mpt/mpt_raid.c
+++ b/sys/dev/mpt/mpt_raid.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_sim.h>
#if __FreeBSD_version < 500000
@@ -656,14 +655,6 @@ mpt_terminate_raid_thread(struct mpt_softc *mpt)
}
static void
-mpt_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
-
- xpt_free_path(ccb->ccb_h.path);
- xpt_free_ccb(ccb);
-}
-
-static void
mpt_raid_thread(void *arg)
{
struct mpt_softc *mpt;
@@ -715,13 +706,7 @@ mpt_raid_thread(void *arg)
xpt_free_ccb(ccb);
mpt_prt(mpt, "Unable to rescan RAID Bus!\n");
} else {
- xpt_setup_ccb(&ccb->ccb_h, path, 5);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = mpt_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- MPTLOCK_2_CAMLOCK(mpt);
- xpt_action(ccb);
- CAMLOCK_2_MPTLOCK(mpt);
+ xpt_rescan(ccb);
}
}
}
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index 673a785..02bc9b3 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -83,9 +83,6 @@ struct vpo_data {
/* cam related functions */
static void vpo_action(struct cam_sim *sim, union ccb *ccb);
static void vpo_poll(struct cam_sim *sim);
-static void vpo_cam_rescan_callback(struct cam_periph *periph,
- union ccb *ccb);
-static void vpo_cam_rescan(struct vpo_data *vpo);
static void
vpo_identify(driver_t *driver, device_t parent)
@@ -176,44 +173,10 @@ vpo_attach(device_t dev)
return (ENXIO);
}
ppb_unlock(ppbus);
- vpo_cam_rescan(vpo); /* have CAM rescan the bus */
return (0);
}
-static void
-vpo_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
-
- free(ccb, M_TEMP);
-}
-
-static void
-vpo_cam_rescan(struct vpo_data *vpo)
-{
- device_t ppbus = device_get_parent(vpo->vpo_dev);
- struct cam_path *path;
- union ccb *ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO);
-
- ppb_lock(ppbus);
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(vpo->sim), 0, 0)
- != CAM_REQ_CMP) {
- /* A failure is benign as the user can do a manual rescan */
- ppb_unlock(ppbus);
- free(ccb, M_TEMP);
- return;
- }
-
- xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = vpo_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
- ppb_unlock(ppbus);
-
- /* The scan is in progress now. */
-}
-
/*
* vpo_intr()
*/
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 6f693e4..630ee7b 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
-#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
/* local prototypes */
@@ -740,6 +739,8 @@ siis_phy_check_events(device_t dev)
/* If we have a connection event, deal with it */
if (ch->pm_level == 0) {
u_int32_t status = ATA_INL(ch->r_mem, SIIS_P_SSTS);
+ union ccb *ccb;
+
if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
@@ -751,6 +752,15 @@ siis_phy_check_events(device_t dev)
device_printf(dev, "DISCONNECT requested\n");
ch->devices = 0;
}
+ if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
+ return;
+ if (xpt_create_path(&ccb->ccb_h.path, NULL,
+ cam_sim_path(ch->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
+ return;
+ }
+ xpt_rescan(ccb);
}
}
@@ -1025,6 +1035,13 @@ siis_execute_transaction(struct siis_slot *slot)
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
ctp->control |= htole16(SIIS_PRB_PACKET_WRITE);
}
+ /* Special handling for Soft Reset command. */
+ if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
+ (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
+ (ccb->ataio.cmd.control & ATA_A_RESET)) {
+ /* Kick controller into sane state */
+ siis_portinit(dev);
+ }
/* Setup the FIS for this request */
if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) {
device_printf(ch->dev, "Setting up SATA FIS failed\n");
@@ -1081,10 +1098,11 @@ siis_timeout(struct siis_slot *slot)
if (slot->state < SIIS_SLOT_RUNNING)
return;
device_printf(dev, "Timeout on slot %d\n", slot->slot);
-device_printf(dev, "%s is %08x ss %08x rs %08x es %08x sts %08x serr %08x\n",
- __func__, ATA_INL(ch->r_mem, SIIS_P_IS), ATA_INL(ch->r_mem, SIIS_P_SS), ch->rslots,
- ATA_INL(ch->r_mem, SIIS_P_CMDERR), ATA_INL(ch->r_mem, SIIS_P_STS),
- ATA_INL(ch->r_mem, SIIS_P_SERR));
+ device_printf(dev, "%s is %08x ss %08x rs %08x es %08x sts %08x serr %08x\n",
+ __func__, ATA_INL(ch->r_mem, SIIS_P_IS),
+ ATA_INL(ch->r_mem, SIIS_P_SS), ch->rslots,
+ ATA_INL(ch->r_mem, SIIS_P_CMDERR), ATA_INL(ch->r_mem, SIIS_P_STS),
+ ATA_INL(ch->r_mem, SIIS_P_SERR));
if (ch->toslots == 0)
xpt_freeze_simq(ch->sim, 1);
@@ -1368,8 +1386,6 @@ siis_devreset(device_t dev)
return (EBUSY);
}
}
- if (bootverbose)
- device_printf(dev, "device reset time=%dms\n", timeout);
return (0);
}
@@ -1389,8 +1405,6 @@ siis_wait_ready(device_t dev, int t)
return (EBUSY);
}
}
- if (bootverbose)
- device_printf(dev, "ready wait time=%dms\n", timeout);
return (0);
}
@@ -1401,6 +1415,7 @@ siis_reset(device_t dev)
int i, retry = 0, sata_rev;
uint32_t val;
+ xpt_freeze_simq(ch->sim, 1);
if (bootverbose)
device_printf(dev, "SIIS reset...\n");
if (!ch->readlog && !ch->recovery)
@@ -1466,6 +1481,7 @@ retry:
"SIIS reset done: phy reset found no device\n");
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
+ xpt_release_simq(ch->sim, TRUE);
return;
}
/* Wait for clearing busy status. */
@@ -1496,6 +1512,7 @@ retry:
device_printf(dev, "SIIS reset done: devices=%08x\n", ch->devices);
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
+ xpt_release_simq(ch->sim, TRUE);
}
static int
diff --git a/sys/dev/trm/trm.c b/sys/dev/trm/trm.c
index 26ab352..e7d5aad 100644
--- a/sys/dev/trm/trm.c
+++ b/sys/dev/trm/trm.c
@@ -747,15 +747,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb)
xpt_done(pccb);
break;
/*
- * (Re)Scan the SCSI Bus
- * Rescan the given bus, or bus/target/lun
- */
- case XPT_SCAN_BUS:
- TRM_DPRINTF(" XPT_SCAN_BUS \n");
- pccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(pccb);
- break;
- /*
* Get EDT entries matching the given pattern
*/
case XPT_DEV_MATCH:
@@ -819,15 +810,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb)
xpt_done(pccb);
break;
/*
- * Scan Logical Unit
- */
- case XPT_SCAN_LUN:
- TRM_DPRINTF(" XPT_SCAN_LUN \n");
- pccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(pccb);
- break;
-
- /*
* Get/Set transfer rate/width/disconnection/tag queueing
* settings
* (GET) default/user transfer settings for the target
diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c
index b7a085f..1d22920 100644
--- a/sys/dev/twa/tw_osl_cam.c
+++ b/sys/dev/twa/tw_osl_cam.c
@@ -56,7 +56,6 @@
static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb);
static TW_VOID twa_poll(struct cam_sim *sim);
static TW_VOID twa_timeout(TW_VOID *arg);
-static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
union ccb *ccb);
@@ -76,7 +75,6 @@ TW_INT32
tw_osli_cam_attach(struct twa_softc *sc)
{
struct cam_devq *devq;
- TW_INT32 error;
tw_osli_dbg_dprintf(3, sc, "entered");
@@ -149,23 +147,8 @@ tw_osli_cam_attach(struct twa_softc *sc)
mtx_unlock(sc->sim_lock);
return(ENXIO);
}
-
- tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
mtx_unlock(sc->sim_lock);
- tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
- /*
- * Request a bus scan, so that CAM gets to know of
- * the logical units that we control.
- */
- if ((error = tw_osli_request_bus_scan(sc)))
- tw_osli_printf(sc, "error = %d",
- TW_CL_SEVERITY_ERROR_STRING,
- TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
- 0x2104,
- "Bus scan request to CAM failed",
- error);
-
tw_osli_dbg_dprintf(3, sc, "exiting");
return(0);
}
@@ -561,7 +544,6 @@ twa_timeout(TW_VOID *arg)
TW_INT32
tw_osli_request_bus_scan(struct twa_softc *sc)
{
- struct cam_path *path;
union ccb *ccb;
tw_osli_dbg_dprintf(3, sc, "entering");
@@ -569,13 +551,12 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
/* If we get here before sc->sim is initialized, return an error. */
if (!(sc->sim))
return(ENXIO);
- if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
+ if ((ccb = xpt_alloc_ccb()) == NULL)
return(ENOMEM);
- bzero(ccb, sizeof(union ccb));
mtx_lock(sc->sim_lock);
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- free(ccb, M_TEMP);
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ xpt_free_ccb(ccb);
mtx_unlock(sc->sim_lock);
return(EIO);
}
@@ -586,11 +567,7 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
}
- xpt_setup_ccb(&ccb->ccb_h, path, 5);
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
+ xpt_rescan(ccb);
mtx_unlock(sc->sim_lock);
return(0);
}
@@ -598,32 +575,6 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
/*
- * Function name: twa_bus_scan_cb
- * Description: Callback from CAM on a bus scan request.
- *
- * Input: periph -- we don't use this
- * ccb -- bus scan request ccb that we sent to CAM
- * Output: None
- * Return value: None
- */
-static TW_VOID
-twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
-{
- tw_osli_dbg_printf(3, "entering");
-
- if (ccb->ccb_h.status != CAM_REQ_CMP)
- printf("cam_scan_callback: failure status = %x\n",
- ccb->ccb_h.status);
- else
- tw_osli_dbg_printf(3, "success");
-
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, M_TEMP);
-}
-
-
-
-/*
* Function name: tw_osli_allow_new_requests
* Description: Sets the appropriate status bits in a ccb such that,
* when the ccb is completed by a call to xpt_done,
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 4e57d82..e41e55b 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -469,8 +469,6 @@ static void umass_cbi_start_status(struct umass_softc *);
static void umass_t_cbi_data_clear_stall_callback(struct usb_xfer *,
uint8_t, uint8_t, usb_error_t);
static int umass_cam_attach_sim(struct umass_softc *);
-static void umass_cam_rescan_callback(struct cam_periph *, union ccb *);
-static void umass_cam_rescan(struct umass_softc *);
static void umass_cam_attach(struct umass_softc *);
static void umass_cam_detach_sim(struct umass_softc *);
static void umass_cam_action(struct cam_sim *, union ccb *);
@@ -2145,68 +2143,6 @@ umass_cam_attach_sim(struct umass_softc *sc)
}
static void
-umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
-{
-#if USB_DEBUG
- struct umass_softc *sc = NULL;
-
- if (ccb->ccb_h.status != CAM_REQ_CMP) {
- DPRINTF(sc, UDMASS_SCSI, "%s:%d Rescan failed, 0x%04x\n",
- periph->periph_name, periph->unit_number,
- ccb->ccb_h.status);
- } else {
- DPRINTF(sc, UDMASS_SCSI, "%s%d: Rescan succeeded\n",
- periph->periph_name, periph->unit_number);
- }
-#endif
-
- xpt_free_path(ccb->ccb_h.path);
- free(ccb, M_USBDEV);
-}
-
-static void
-umass_cam_rescan(struct umass_softc *sc)
-{
- struct cam_path *path;
- union ccb *ccb;
-
- DPRINTF(sc, UDMASS_SCSI, "scbus%d: scanning for %d:%d:%d\n",
- cam_sim_path(sc->sc_sim),
- cam_sim_path(sc->sc_sim),
- sc->sc_unit, CAM_LUN_WILDCARD);
-
- ccb = malloc(sizeof(*ccb), M_USBDEV, M_WAITOK | M_ZERO);
-
- if (ccb == NULL) {
- return;
- }
-#if (__FreeBSD_version >= 700037)
- mtx_lock(&sc->sc_mtx);
-#endif
-
- if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sc_sim),
- CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)
- != CAM_REQ_CMP) {
-#if (__FreeBSD_version >= 700037)
- mtx_unlock(&sc->sc_mtx);
-#endif
- free(ccb, M_USBDEV);
- return;
- }
- xpt_setup_ccb(&ccb->ccb_h, path, 5 /* priority (low) */ );
- ccb->ccb_h.func_code = XPT_SCAN_BUS;
- ccb->ccb_h.cbfcnp = &umass_cam_rescan_callback;
- ccb->crcn.flags = CAM_FLAG_NONE;
- xpt_action(ccb);
-
-#if (__FreeBSD_version >= 700037)
- mtx_unlock(&sc->sc_mtx);
-#endif
-
- /* The scan is in progress now. */
-}
-
-static void
umass_cam_attach(struct umass_softc *sc)
{
#ifndef USB_DEBUG
@@ -2216,19 +2152,6 @@ umass_cam_attach(struct umass_softc *sc)
sc->sc_name, cam_sim_path(sc->sc_sim),
sc->sc_unit, CAM_LUN_WILDCARD,
cam_sim_path(sc->sc_sim));
-
- if (!cold) {
- /*
- * Notify CAM of the new device after a short delay. Any
- * failure is benign, as the user can still do it by hand
- * (camcontrol rescan <busno>). Only do this if we are not
- * booting, because CAM does a scan after booting has
- * completed, when interrupts have been enabled.
- */
-
- /* scan the new sim */
- umass_cam_rescan(sc);
- }
}
/* umass_cam_detach
OpenPOWER on IntegriCloud