#include #include "ufshci.h" @@ -233,6 +235,30 @@ struct ufshci_req_queue { bus_dmamap_t ucdmem_map; }; +enum ufshci_dev_pwr { + UFSHCI_DEV_PWR_ACTIVE = 0, + UFSHCI_DEV_PWR_SLEEP, + UFSHCI_DEV_PWR_POWERDOWN, + UFSHCI_DEV_PWR_DEEPSLEEP, + UFSHCI_DEV_PWR_COUNT, +}; + +struct ufshci_power_entry { + enum ufshci_dev_pwr dev_pwr; + uint8_t ssu_pc; /* SSU Power Condition */ +}; + +/* SSU Power Condition 0x40 is defined in the UFS specification */ +static const struct ufshci_power_entry power_map[POWER_STYPE_COUNT] = { + [POWER_STYPE_AWAKE] = { UFSHCI_DEV_PWR_ACTIVE, SSS_PC_ACTIVE }, + [POWER_STYPE_STANDBY] = { UFSHCI_DEV_PWR_SLEEP, SSS_PC_IDLE }, + [POWER_STYPE_SUSPEND_TO_MEM] = { UFSHCI_DEV_PWR_POWERDOWN, + SSS_PC_STANDBY }, + [POWER_STYPE_SUSPEND_TO_IDLE] = { UFSHCI_DEV_PWR_SLEEP, SSS_PC_IDLE }, + [POWER_STYPE_HIBERNATE] = { UFSHCI_DEV_PWR_DEEPSLEEP, 0x40 }, + [POWER_STYPE_POWEROFF] = { UFSHCI_DEV_PWR_POWERDOWN, SSS_PC_STANDBY }, +}; + struct ufshci_device { uint32_t max_lun_count; @@ -252,6 +278,7 @@ struct ufshci_device { /* Power mode */ bool power_mode_supported; + enum ufshci_dev_pwr power_mode; }; /* @@ -386,12 +413,16 @@ void ufshci_sim_detach(struct ufshci_controller *ctrlr); struct cam_periph *ufshci_sim_find_periph(struct ufshci_controller *ctrlr, uint8_t wlun); int ufshci_sim_send_ssu(struct ufshci_controller *ctrlr, bool start, - int pwr_cond, bool immed); + uint8_t pwr_cond, bool immed); /* Controller */ int ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev); void ufshci_ctrlr_destruct(struct ufshci_controller *ctrlr, device_t dev); void ufshci_ctrlr_reset(struct ufshci_controller *ctrlr); +int ufshci_ctrlr_suspend(struct ufshci_controller *ctrlr, + enum power_stype stype); +int ufshci_ctrlr_resume(struct ufshci_controller *ctrlr, + enum power_stype stype); /* ctrlr defined as void * to allow use with config_intrhook. */ void ufshci_ctrlr_start_config_hook(void *arg); void ufshci_ctrlr_poll(struct ufshci_controller *ctrlr); @@ -415,6 +446,8 @@ int ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr); int ufshci_dev_init_ufs_power_mode(struct ufshci_controller *ctrlr); int ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr); int ufshci_dev_config_write_booster(struct ufshci_controller *ctrlr); +int ufshci_dev_get_current_power_mode(struct ufshci_controller *ctrlr, + uint8_t *power_mode); /* Controller Command */ void ufshci_ctrlr_cmd_send_task_mgmt_request(struct ufshci_controller *ctrlr, diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c index 7aa164d00bec..df7e4b159278 100644 --- a/sys/dev/ufshci/ufshci_req_queue.c +++ b/sys/dev/ufshci/ufshci_req_queue.c @@ -147,7 +147,8 @@ ufshci_req_queue_response_is_error(struct ufshci_req_queue *req_queue, /* Check response UPIU header */ if (response->header.response != UFSHCI_RESPONSE_CODE_TARGET_SUCCESS) { ufshci_printf(req_queue->ctrlr, - "Invalid response code = 0x%x\n", + "Function(0x%x) Invalid response code = 0x%x\n", + response->header.ext_iid_or_function, response->header.response); is_error = true; } diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c index 0cd691de47e2..1589e7475ad4 100644 --- a/sys/dev/ufshci/ufshci_sim.c +++ b/sys/dev/ufshci/ufshci_sim.c @@ -46,6 +46,11 @@ ufshci_sim_scsiio_done(void *ccb_arg, const struct ufshci_completion *cpl, ccb->ccb_h.status &= ~CAM_SIM_QUEUED; if (error) { + printf("ufshci: SCSI command completion error, Status(0x%x)" + " Key(0x%x), ASC(0x%x), ASCQ(0x%x)\n", + cpl->response_upiu.cmd_response_upiu.header + .ext_iid_or_status, + sense_data[2], sense_data[12], sense_data[13]); ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); } else { @@ -455,7 +460,7 @@ ufshci_sim_find_periph(struct ufshci_controller *ctrlr, uint8_t wlun) /* This function is called during suspend/resume. */ int ufshci_sim_send_ssu(struct ufshci_controller *ctrlr, bool start, - int power_condition, bool immed) + uint8_t power_condition, bool immed) { struct cam_periph *periph = ctrlr->ufs_device_wlun_periph; union ccb *ccb; diff --git a/sys/dev/ufshci/ufshci_sysctl.c b/sys/dev/ufshci/ufshci_sysctl.c index 3ec4ea935464..30b0ccaeed13 100644 --- a/sys/dev/ufshci/ufshci_sysctl.c +++ b/sys/dev/ufshci/ufshci_sysctl.c @@ -201,6 +201,9 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) CTLFLAG_RD, &dev->power_mode_supported, 0, "Device power mode support"); + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "power_mode", + CTLFLAG_RD, &dev->power_mode, 0, "Current device power mode"); + SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, "timeout_period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, &ctrlr->timeout_period, 0, ufshci_sysctl_timeout_period, "IU",