diff --git a/sys/cam/ata/ata_all.c b/sys/cam/ata/ata_all.c index 25daea4eb7f6..b2db7a03ce1a 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 8d493096bffe..3408b4fa3bbc 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 8c2e1bff3a28..1b8d9d5129ff 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 99cf31410835..bff0340b6710 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 85b02fb9cfac..88271b0684bc 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 3d85264f4c59..2b3b98cba603 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 72de56467256..4c5adba54189 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 9bac0f5a82e2..4c7502ae877e 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,21 @@ 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 -camperiphdone(struct cam_periph *periph, union ccb *done_ccb) +camperiphsensedone(struct cam_periph *periph, union ccb *done_ccb) { - union ccb *saved_ccb; + union ccb *saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; 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; + u_int sense_key; + int depth = done_ccb->ccb_h.recovery_depth; status = done_ccb->ccb_h.status; if (status & CAM_DEV_QFRZN) { @@ -996,14 +1025,83 @@ 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; + 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, *save_ccb; + cam_status status; + int frozen = 0; + struct scsi_start_stop_unit *scsi_cmd; + u_int32_t relsim_flags, timeout; + + 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; + } 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; + 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); - - 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 e207b1925ab5..33e9f7584355 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 #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 31f9bc238bf7..dd9f9a7306e7 100644 --- a/sys/cam/cam_queue.h +++ b/sys/cam/cam_queue.h @@ -34,6 +34,7 @@ #ifdef _KERNEL #include +#include /* * 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 adccfa8593ec..59148a9a4267 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 88ee30916755..d966a9fb5bd4 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; + struct cam_path *path = start_ccb->ccb_h.path; + int frozen; - 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) + 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); } @@ -4109,13 +4115,35 @@ xpt_dev_async_default(u_int32_t async_code, struct cam_eb *bus, printf("xpt_dev_async called\n"); } +u_int32_t +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); + 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) { - mtx_assert(path->bus->sim->mtx, MA_OWNED); - path->device->ccbq.queue.qfrozen_cnt += count; - return (path->device->ccbq.queue.qfrozen_cnt); + 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); +} + +void +xpt_release_devq_rl(struct cam_path *path, cam_rl rl, u_int count, int run_queue) +{ + mtx_assert(path->bus->sim->mtx, MA_OWNED); + + xpt_release_devq_device(path->device, rl, count, run_queue); } static void -xpt_release_devq_device(struct cam_ed *dev, u_int count, int run_queue) +xpt_release_devq_device(struct cam_ed *dev, 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) { - - /* - * 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; - } - - /* - * 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) +static void +xpt_boot_delay(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) -{ - 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); +} - if (busses_to_config == 0) { +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; + + 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)(); - } + 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); - /* - * 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 283cad1c34e6..61a7f3f02d20 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 146764ef7634..b1fbaafb2212 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 dbfb55eb7576..867b1c1d3813 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 e64c67c16fa1..323f786c813f 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 e6f3a7c1005a..d40a53659ecd 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 cf99eea53592..9d5dcf6c8b8d 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 2829a155d9ad..107f22b2ed9f 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 d05376ee2959..77652b2dc949 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 1cee43dca297..1b2f4f601edb 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 755189183754..9464ca21ce38 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 cae7be61ac99..7639377052b4 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 789a8aa717af..ecff8a02391b 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include /* 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 e11f84f489d3..d136d82b3265 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 2bc5e2277246..ae363d0045d4 100644 --- a/sys/dev/asr/asr.c +++ b/sys/dev/asr/asr.c @@ -130,7 +130,6 @@ #include #include #include -#include #include #include diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index f342c819ef13..1ad3c5117c16 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #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 84b44c563993..3f8e650708c3 100644 --- a/sys/dev/ata/atapi-cam.c +++ b/sys/dev/ata/atapi-cam.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -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; } @@ -821,42 +818,21 @@ 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 c5ad417e70c8..4e336a94be28 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 7218bc504425..1ea257becc33 100644 --- a/sys/dev/hptiop/hptiop.c +++ b/sys/dev/hptiop/hptiop.c @@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -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,26 +1033,17 @@ 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) - 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); - 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); + if ((ccb = xpt_alloc_ccb()) == NULL) + return(ENOMEM); + 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 bus_dmamap_callback_t hptiop_map_srb; @@ -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 78c8b60fe2e1..6bc30c22b36f 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 fb487e820b67..ec221f39b90a 100644 --- a/sys/dev/hptrr/os_bsd.h +++ b/sys/dev/hptrr/os_bsd.h @@ -91,7 +91,6 @@ #include #include #include -#include #include #include #include diff --git a/sys/dev/mly/mly.c b/sys/dev/mly/mly.c index 189f53991c96..90f2819ccbfd 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 f2faa4abdff8..8a18934d6483 100644 --- a/sys/dev/mpt/mpt_cam.h +++ b/sys/dev/mpt/mpt_cam.h @@ -102,7 +102,6 @@ #include #include #include -#include #include #include #include diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c index 5185ec0d7960..d313253fa9e9 100644 --- a/sys/dev/mpt/mpt_raid.c +++ b/sys/dev/mpt/mpt_raid.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #if __FreeBSD_version < 500000 @@ -655,14 +654,6 @@ mpt_terminate_raid_thread(struct mpt_softc *mpt) mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0); } -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) { @@ -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 673a7858d4da..02bc9b397b2e 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 6f693e4e8a2e..630ee7b44c97 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include /* 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 26ab35239e7f..e7d5aad6d77d 100644 --- a/sys/dev/trm/trm.c +++ b/sys/dev/trm/trm.c @@ -746,15 +746,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb) pccb->ccb_h.status = CAM_REQ_INVALID; 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 */ @@ -818,15 +809,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb) pccb->ccb_h.status = CAM_REQ_INVALID; 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 diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c index b7a085f19789..1d22920f291b 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,43 +567,13 @@ 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); } -/* - * 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, diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index 4e57d82a1fdc..e41e55b7f909 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 *); @@ -2144,68 +2142,6 @@ umass_cam_attach_sim(struct umass_softc *sc) return (0); } -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) { @@ -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 ). 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