Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140083144
D53923.id167340.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D53923.id167340.diff
View Options
diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c
--- a/sys/dev/ufshci/ufshci_ctrlr.c
+++ b/sys/dev/ufshci/ufshci_ctrlr.c
@@ -79,12 +79,6 @@
return;
}
- /* Initialize UFS Power Mode */
- if (ufshci_dev_init_ufs_power_mode(ctrlr) != 0) {
- ufshci_ctrlr_fail(ctrlr);
- return;
- }
-
/* Read Controller Descriptor (Device, Geometry) */
if (ufshci_dev_get_descriptor(ctrlr) != 0) {
ufshci_ctrlr_fail(ctrlr);
@@ -109,6 +103,12 @@
return;
}
+ /* Initialize UFS Power Mode */
+ if (ufshci_dev_init_ufs_power_mode(ctrlr) != 0) {
+ ufshci_ctrlr_fail(ctrlr);
+ return;
+ }
+
TSEXIT();
}
diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c
--- a/sys/dev/ufshci/ufshci_dev.c
+++ b/sys/dev/ufshci/ufshci_dev.c
@@ -455,8 +455,20 @@
int
ufshci_dev_init_ufs_power_mode(struct ufshci_controller *ctrlr)
{
- /* TODO: Need to implement */
+ ctrlr->ufs_dev.power_mode_supported = false;
+ if (ctrlr->quirks & UFSHCI_QUIRK_SKIP_WELL_KNOWN_LUNS)
+ return (0);
+
+ ctrlr->ufs_device_wlun_periph = ufshci_sim_find_periph(ctrlr,
+ UFSHCI_WLUN_UFS_DEVICE);
+ if (ctrlr->ufs_device_wlun_periph == NULL) {
+ ufshci_printf(ctrlr,
+ "Well-known LUN `UFS Device (0x50)` not found\n");
+ return (0);
+ }
+
+ ctrlr->ufs_dev.power_mode_supported = true;
return (0);
}
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -31,6 +31,8 @@
#include <machine/bus.h>
+#include <cam/cam.h>
+
#include "ufshci.h"
MALLOC_DECLARE(M_UFSHCI);
@@ -247,6 +249,9 @@
uint32_t wb_user_space_config_option;
uint8_t wb_dedicated_lu;
uint32_t write_booster_flush_threshold;
+
+ /* Power mode */
+ bool power_mode_supported;
};
/*
@@ -274,6 +279,9 @@
struct cam_sim *ufshci_sim;
struct cam_path *ufshci_path;
+ struct cam_periph *ufs_device_wlun_periph;
+ struct mtx ufs_device_wlun_mtx;
+
struct mtx sc_mtx;
uint32_t sc_unit;
uint8_t sc_name[16];
@@ -371,8 +379,14 @@
bool error);
/* SIM */
+uint8_t ufshci_sim_translate_scsi_to_ufs_lun(lun_id_t scsi_lun);
+uint64_t ufshci_sim_translate_ufs_to_scsi_lun(uint8_t ufs_lun);
int ufshci_sim_attach(struct ufshci_controller *ctrlr);
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);
/* Controller */
int ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev);
diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c
--- a/sys/dev/ufshci/ufshci_sim.c
+++ b/sys/dev/ufshci/ufshci_sim.c
@@ -10,9 +10,11 @@
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_debug.h>
+#include <cam/cam_periph.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
#include "ufshci_private.h"
@@ -76,7 +78,7 @@
* The SCSI LUN format and the UFS UPIU LUN format are different.
* This function converts the SCSI LUN format to the UFS UPIU LUN format.
*/
-static uint8_t
+uint8_t
ufshci_sim_translate_scsi_to_ufs_lun(lun_id_t scsi_lun)
{
const int address_format_offset = 8;
@@ -94,6 +96,19 @@
return (scsi_lun & UFSHCI_UPIU_UNIT_NUMBER_ID_MASK);
}
+uint64_t
+ufshci_sim_translate_ufs_to_scsi_lun(uint8_t ufs_lun)
+{
+ /* Logical unit */
+ if (!(ufs_lun & UFSHCI_UPIU_WLUN_ID_MASK)) {
+ return ufs_lun;
+ }
+
+ /* Well known logical unit */
+ return (((uint64_t)ufs_lun & ~UFSHCI_UPIU_WLUN_ID_MASK) |
+ (RPL_LUNDATA_ATYP_EXTLUN | RPL_LUNDATA_EXT_EAM_WK) << 8);
+}
+
static void
ufshchi_sim_scsiio(struct cam_sim *sim, union ccb *ccb)
{
@@ -396,3 +411,100 @@
ctrlr->ufshci_sim = NULL;
}
}
+
+struct cam_periph *
+ufshci_sim_find_periph(struct ufshci_controller *ctrlr, uint8_t wlun)
+{
+ struct cam_path *path;
+ struct cam_periph *periph = NULL;
+ uint64_t scsi_lun;
+ uint64_t timeout;
+
+ scsi_lun = ufshci_sim_translate_ufs_to_scsi_lun(wlun);
+
+ if (xpt_create_path(&path, /*periph*/ NULL,
+ cam_sim_path(ctrlr->ufshci_sim), 0, scsi_lun) != CAM_REQ_CMP) {
+ return NULL;
+ }
+
+ /* Wait for the perip device to be found */
+ timeout = ticks + MSEC_2_TICKS(ctrlr->device_init_timeout_in_ms);
+
+ while (1) {
+ xpt_path_lock(path);
+ periph = cam_periph_find(path, "pass");
+ xpt_path_unlock(path);
+
+ if (periph) {
+ xpt_free_path(path);
+ break;
+ }
+
+ if (timeout - ticks < 0) {
+ ufshci_printf(ctrlr,
+ "Failed to find the Well known LUN(0x%x)\n", wlun);
+ break;
+ }
+
+ pause_sbt("ufshci_find_periph", ustosbt(100), 0, C_PREL(1));
+ }
+
+ return periph;
+}
+
+/* This function is called during suspend/resume. */
+int
+ufshci_sim_send_ssu(struct ufshci_controller *ctrlr, bool start,
+ int power_condition, bool immed)
+{
+ struct cam_periph *periph = ctrlr->ufs_device_wlun_periph;
+ union ccb *ccb;
+ int err;
+
+ /* Acquire periph reference */
+ if (periph && cam_periph_acquire(periph) != 0) {
+ periph = NULL;
+ }
+
+ if (periph == NULL) {
+ /* If the periph device does not exist, it will try to find it
+ * again */
+ periph = ufshci_sim_find_periph(ctrlr,
+ (uint8_t)UFSHCI_WLUN_UFS_DEVICE);
+ if (periph)
+ ctrlr->ufs_device_wlun_periph = periph;
+ }
+
+ if (periph == NULL) {
+ ufshci_printf(ctrlr,
+ "Well-known LUN `UFS Device (0x50)` not found\n");
+ return ENODEV;
+ }
+ cam_periph_lock(periph);
+ ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
+ if (!ccb) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return ENOMEM;
+ }
+
+ scsi_start_stop(&ccb->csio,
+ /*retries*/ 4,
+ /*cbfcnp*/ NULL,
+ /*tag_action*/ MSG_SIMPLE_Q_TAG,
+ /*start*/ start ? 1 : 0,
+ /*load_eject*/ 0,
+ /*immediate*/ immed ? 1 : 0,
+ /*power_condition*/ power_condition, SSD_MIN_SIZE,
+ ctrlr->device_init_timeout_in_ms);
+
+ ccb->ccb_h.flags |= CAM_DIR_NONE | CAM_DEV_QFRZDIS;
+
+ err = cam_periph_runccb(ccb, NULL, 0, SF_RETRY_UA, NULL);
+
+ cam_periph_unlock(periph);
+ /* Release periph reference */
+ cam_periph_release(periph);
+
+ return (err == 0) ? 0 : EIO;
+}
diff --git a/sys/dev/ufshci/ufshci_sysctl.c b/sys/dev/ufshci/ufshci_sysctl.c
--- a/sys/dev/ufshci/ufshci_sysctl.c
+++ b/sys/dev/ufshci/ufshci_sysctl.c
@@ -197,6 +197,10 @@
&dev->wb_user_space_config_option, 0,
"WriteBooster preserve user space mode");
+ SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "power_mode_supported",
+ CTLFLAG_RD, &dev->power_mode_supported, 0,
+ "Device power mode support");
+
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",
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 21, 12:29 AM (12 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27102133
Default Alt Text
D53923.id167340.diff (6 KB)
Attached To
Mode
D53923: ufshci: Add a check for WLUN during driver initialization
Attached
Detach File
Event Timeline
Log In to Comment