Re: Questions about probing WLUNs for UFS power management
Jaeyoon Choi <[email protected]> Thu, 25 Sep 2025 11:30:49 +0900
| Newsgroups | gmane.os.freebsd.devel.scsi |
|---|---|
| Message-ID | <CADd34gyQAv+A-+m-+Hd5tEO2O3McbrmOwADnqCjO-5Q6vnw-Bg@mail.gmail.com> |
If we go with option 1), we could add a PIM_WLUN flag to hba_misc, similar to PIM_EXTLUN, so that only device drivers configured with this flag would probe for WLUNs. Jaeyoon 2025=EB=85=84 9=EC=9B=94 24=EC=9D=BC (=EC=88=98) =EC=98=A4=EC=A0=84 11:32, = Jaeyoon Choi <[email protected]>=EB=8B=98=EC=9D=B4 =EC=9E=91=EC=84=B1: > > Hello freebsd-scsi, > > I=E2=80=99m trying to implement Well-known LUNs (WLUNs) for the UFS (Univ= ersal > Flash Storage, ufshci(4)) driver, but the current SCSI XPT doesn't probe > WLUNs, so I have a few questions. > > First, Well-known LUNs are defined in SCSI SAM-5. In UFS, 'REPORT LUNS', > 'UFS Device', 'RPMB', and 'BOOT' LUNs are treated as WLUNs. > (SAM-5 4.7.5.1 "Well-known logical unit addressing", > UFS 2.1 spec 10.8.5 "10.8.5 Well Known Logical Unit Defined in UFS") > > Because a UFS device contains multiple LUNs, power management requires > sending a START STOP UNIT(SSU) command to the 'UFS Device' WLUN. (If SSU > is sent to a non-WLUN (normal) LUN, the device power mode is not changed > and only that LUN becomes disabled.) > (UFS 2.1 spec 7.4.2 "Power Management Command: START STOP UNIT") > > In FreeBSD, the SCSI XPT logic that parses LUNs checks the 'Simple logica= l > unit addressing format' (SAM-5 Table 26) and the 8-byte 'Extended logical > unit addressing format' (SAM-5 Table 35), but it does not check the > 'Well-known logical unit extended addressing format' (SAM-5 Table 37). > In the scsi_xpt.c code below, CAM_GET_LUN reads Extended LUNs and > CAM_GET_SIMPLE_LUN reads Simple LUNs: > > ``` > sys/cam/scsi/scsi_xpt.c line:2114 > static void > scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb) > ... > while (scan_info->lunindex[target_id] < nluns) { > if (scan_info->cpi->hba_misc & PIM_EXTLUNS) { > CAM_GET_LUN(target->luns, > scan_info->lunindex[target_id], > lun_id); > break; > } > > if (CAM_CAN_GET_SIMPLE_LUN(target->luns, > scan_info->lunindex[target_id])) { > CAM_GET_SIMPLE_LUN(target->luns, > scan_info->lunindex[target_id], > lun_id); > break; > } > > scan_info->lunindex[target_id]++; > } > ``` > > Also, we can obtain the number of WLUNs via the REPORT LUNS SCSI command. > To retrieve WLUNs, the SELECT REPORT field must be set to 0x01, but > SCSI XPT currently uses 0x00 to obtain only normal LUNs. > (UFS 2.1 spec 11.3.12.2 "Report LUNS Command Select Report Field Values") > > ``` > sys/cam/scsi/scsi_xpt.c line:827 > static void > probestart(struct cam_periph *periph, union ccb *start_ccb) > ... > case PROBE_REPORT_LUNS: > ... > scsi_report_luns(csio, 5, probedone, MSG_SIMPLE_Q_TAG, > RPL_REPORT_DEFAULT, rp, periph->path->target->rpl_size, > SSD_FULL_SIZE, 60000); > ``` > ``` > sys/cam/scsi/scsi_all.h line:3020 > struct scsi_report_luns > { > uint8_t opcode; > uint8_t reserved1; > #define RPL_REPORT_DEFAULT 0x00 > #define RPL_REPORT_WELLKNOWN 0x01 > ``` > > Looking at the Linux code, Linux also does not check WLUNs at the SCSI > layer. Therefore, the Linux UFS driver explicitly registers the WLUNs > during initialization by calling __scsi_add_device() > > ``` > drivers/ufs/core/ufshcd.c line:8137 > /** > * ufshcd_scsi_add_wlus - Adds required W-LUs > * @hba: per-adapter instance > * > * UFS device specification requires the UFS devices to support 4 well kn= own > * logical units: > * "REPORT_LUNS" (address: 01h) > * "UFS Device" (address: 50h) > * "RPMB" (address: 44h) > * "BOOT" (address: 30h) > * UFS device's power management needs to be controlled by "POWER CONDITI= ON" > * field of SSU (START STOP UNIT) command. But this "power condition" fie= ld > * will take effect only when its sent to "UFS device" well known logical= unit > * hence we require the scsi_device instance to represent this logical un= it in > * order for the UFS host driver to send the SSU command for power manage= ment. > * > * We also require the scsi_device instance for "RPMB" (Replay Protected = Memory > * Block) LU so user space process can control this LU. User space may al= so > * want to have access to BOOT LU. > * > * This function adds scsi device instances for each of all well known LU= s > * (except "REPORT LUNS" LU). > * > * Return: zero on success (all required W-LUs are added successfully), > * non-zero error value on failure (if failed to add any of the required = W-LU). > */ > static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) > { > int ret =3D 0; > struct scsi_device *sdev_boot, *sdev_rpmb; > > hba->ufs_device_wlun =3D __scsi_add_device(hba->host, 0, 0, > ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL); > if (IS_ERR(hba->ufs_device_wlun)) { > ret =3D PTR_ERR(hba->ufs_device_wlun); > hba->ufs_device_wlun =3D NULL; > goto out; > } > scsi_device_put(hba->ufs_device_wlun); > > sdev_rpmb =3D __scsi_add_device(hba->host, 0, 0, > ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); > if (IS_ERR(sdev_rpmb)) { > ret =3D PTR_ERR(sdev_rpmb); > goto remove_ufs_device_wlun; > } > ufshcd_blk_pm_runtime_init(sdev_rpmb); > scsi_device_put(sdev_rpmb); > > sdev_boot =3D __scsi_add_device(hba->host, 0, 0, > ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); > if (IS_ERR(sdev_boot)) { > dev_err(hba->dev, "%s: BOOT WLUN not found\n", __func__); > } else { > ufshcd_blk_pm_runtime_init(sdev_boot); > scsi_device_put(sdev_boot); > } > goto out; > > remove_ufs_device_wlun: > scsi_remove_device(hba->ufs_device_wlun); > out: > return ret; > } > ``` > > -------------------------------------------------------------------------= -- > > My question is: which approach would be more appropriate for using WLUN > devices in UFS driver on FreeBSD? > > (1) Add support in SCSI XPT to probe WLUNs and allocate devices for them. > (2) Follow Linux: have the UFS driver explicitly probe/register WLUN > devices itself. > > If (2) is preferred, what is the recommended way for the UFSHCI driver to > probe/register WLUNs in FreeBSD? (Is there an equivalent to Linux=E2=80= =99s > __scsi_add_device()?) > > Thanks, > Jaeyoon