Index: sys/cam/cam_ccb.h =================================================================== --- sys/cam/cam_ccb.h +++ sys/cam/cam_ccb.h @@ -245,6 +245,8 @@ XPT_REPROBE_LUN = 0x38 | XPT_FC_QUEUED | XPT_FC_USER_CCB, /* Query device capacity and notify GEOM */ +/* Autocomplete after ccb_hdr->timeout */ + XPT_TIMEOUT = 0x40 | XPT_FC_DEV_QUEUED, /* Vendor Unique codes: 0x80->0x8F */ XPT_VUNIQUE = 0x80 } xpt_opcode; Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -329,6 +329,9 @@ static xpt_busfunc_t xptsetasyncbusfunc; static cam_status xptregister(struct cam_periph *periph, void *arg); + +void xpt_signal_timeout_passed(void *arg); + static __inline int device_is_queued(struct cam_ed *device); static __inline int @@ -2635,6 +2638,15 @@ (*(start_ccb->ccb_h.path->bus->xport->ops->action))(start_ccb); } +void xpt_signal_timeout_passed(void *arg) { + union ccb *finish_ccb = (union ccb*) arg; + + CAM_DEBUG(finish_ccb->ccb_h.path, CAM_DEBUG_TRACE, + ("xpt_signal_timeout_passed: time is up\n")); + finish_ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(finish_ccb); +} + void xpt_action_default(union ccb *start_ccb) { @@ -3189,6 +3201,16 @@ xpt_done(start_ccb); } break; + case XPT_TIMEOUT: { + struct cam_ed *dev; + + dev = path->device; + callout_reset_sbt(&dev->timeout_callout, + SBT_1MS * start_ccb->ccb_h.timeout, 0, + xpt_signal_timeout_passed, start_ccb, 0); + start_ccb->ccb_h.status = CAM_REQ_INPROG; + break; + } } CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_action_default: func= %#x %s status %#x\n", @@ -4911,6 +4933,7 @@ device->refcount = 1; mtx_init(&device->device_mtx, "CAM device lock", NULL, MTX_DEF); callout_init_mtx(&device->callout, &devq->send_mtx, 0); + callout_init_mtx(&device->timeout_callout, &device->device_mtx, 0); TASK_INIT(&device->device_destroy_task, 0, xpt_destroy_device, device); /* * Hold a reference to our parent bus so it @@ -5559,6 +5582,7 @@ { XPT_NOTIFY_ACK, "XPT_NOTIFY_ACK" }, { XPT_IMMEDIATE_NOTIFY, "XPT_IMMEDIATE_NOTIFY" }, { XPT_NOTIFY_ACKNOWLEDGE, "XPT_NOTIFY_ACKNOWLEDGE" }, + { XPT_TIMEOUT, "XPT_TIMEOUT" }, { 0, 0 } }; Index: sys/cam/cam_xpt_internal.h =================================================================== --- sys/cam/cam_xpt_internal.h +++ sys/cam/cam_xpt_internal.h @@ -155,6 +155,7 @@ struct task device_destroy_task; const struct nvme_controller_data *nvme_cdata; const struct nvme_namespace_data *nvme_data; + struct callout timeout_callout; }; /* Index: sys/cam/mmc/mmc_xpt.c =================================================================== --- sys/cam/mmc/mmc_xpt.c +++ sys/cam/mmc/mmc_xpt.c @@ -86,7 +86,8 @@ typedef enum { PROBE_RESET, - PROBE_IDENTIFY, + PROBE_IDENTIFY_POWER_OFF, + PROBE_IDENTIFY_POWER_UP, PROBE_SDIO_RESET, PROBE_SEND_IF_COND, PROBE_SDIO_INIT, @@ -102,7 +103,8 @@ static char *probe_action_text[] = { "PROBE_RESET", - "PROBE_IDENTIFY", + "PROBE_IDENTIFY_POWER_OFF", + "PROBE_IDENTIFY_POWER_UP", "PROBE_SDIO_RESET", "PROBE_SEND_IF_COND", "PROBE_SDIO_INIT", @@ -503,7 +505,7 @@ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) PROBE_SET_ACTION(softc, PROBE_RESET); else - PROBE_SET_ACTION(softc, PROBE_IDENTIFY); + PROBE_SET_ACTION(softc, PROBE_IDENTIFY_POWER_OFF); /* This will kick the ball */ xpt_schedule(periph, CAM_PRIORITY_XPT); @@ -556,7 +558,7 @@ if (path->device->flags & CAM_DEV_UNCONFIGURED) softc->action = PROBE_RESET; else - softc->action = PROBE_IDENTIFY; + softc->action = PROBE_IDENTIFY_POWER_OFF; } @@ -564,7 +566,7 @@ switch (softc->action) { case PROBE_RESET: /* FALLTHROUGH */ - case PROBE_IDENTIFY: + case PROBE_IDENTIFY_POWER_OFF: init_standard_ccb(start_ccb, XPT_PATH_INQ); xpt_action(start_ccb); @@ -573,8 +575,15 @@ cts->ios.power_mode = power_off; cts->ios_valid = MMC_PM; xpt_action(start_ccb); - mtx_sleep(periph, p_mtx, 0, "mmcios", 100); +// mtx_sleep(periph, p_mtx, 0, "mmcios", 100); + start_ccb->ccb_h.func_code = XPT_TIMEOUT; + start_ccb->ccb_h.timeout = 5000; + start_ccb->ccb_h.cbfcnp = mmcprobe_done; + CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("SCHEDULE TIMEOUT\n")); + xpt_action(start_ccb); + break; + case PROBE_IDENTIFY_POWER_UP: /* mmc_power_up */ /* Get the host OCR */ init_standard_ccb(start_ccb, XPT_GET_TRAN_SETTINGS); @@ -754,7 +763,11 @@ switch (softc->action) { case PROBE_RESET: /* FALLTHROUGH */ - case PROBE_IDENTIFY: + case PROBE_IDENTIFY_POWER_OFF: + printf("Transition POWER_OFF -> POWER_UP after timeout\n"); + PROBE_SET_ACTION(softc, PROBE_IDENTIFY_POWER_UP); + break; + case PROBE_IDENTIFY_POWER_UP: { printf("Starting completion of PROBE_RESET\n"); CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_PROBE, ("done with PROBE_RESET\n"));