Re: Questions about probing WLUNs for UFS power management
Jaeyoon Choi <[email protected]> Wed, 1 Oct 2025 12:11:24 +0900
| Newsgroups | gmane.os.freebsd.devel.scsi |
|---|---|
| Message-ID | <CADd34gzEorhUPOoZ90nkf8Doep4HBB0T27DYswEERxut5kWL8w@mail.gmail.com> |
> It's easy enough to add the enumeration for (1) to scsi_xpt.c It's just a= few more states in the probe state machine (which is a bit complex, but no= t terribly so). If we treat them as separate LUNs, then a lot of the infras= tructure would just work. The key, though, is how do we keep scsi_da, etc f= rom attaching to these new nodes. And would we have generic scsi_foo.c driv= ers for them (so the devices would get their own periph drivers) or whether= there's a higher-level device that would know it could use these devices i= f it finds them and it wouldn't have a specific specialized kernel drive fo= r them, but instead use a generalized pass thru device. That's correct. Probing the WLUN isn't difficult. And being able to use the SCSI infrastructure is a huge advantage. However, as you mentioned, having the peripheral driver (scsi_da?) attached to the WLUN node seems like it could be a problem. > > I guess a lot of that would depend where things like power management is = happening. If it's in the UFS sim, that would suggest a different design th= an if this was some super generic thing that would respond to generic event= s that maybe the SIMs generate or maybe somebody else. Refer to Section 7.4.2 =E2=80=9CPower Management Command: START STOP UNIT= =E2=80=9D in the UFS 2.1 specification. The START STOP UNIT command is used to change the power mode. The SBC-5 spec also defines the SSU's POWER CONDITION field. (SBC-5 5.31 =E2=80=9CSTART STOP UNIT command=E2=80=9D) The specs seem similar, but I need to study further to understand whether UFS's power management approach is a super generic thing. I'll come back after reading more of the spec and code. Thanks, Jaeyoon On Mon, Sep 29, 2025 at 6:48=E2=80=AFAM Warner Losh <[email protected]> wrote: > > Please excuse the tardy response > > On Tue, Sep 23, 2025 at 8:32=E2=80=AFPM Jaeyoon Choi <[email protected]= > wrote: >> >> Hello freebsd-scsi, >> >> I=E2=80=99m trying to implement Well-known LUNs (WLUNs) for the UFS (Uni= versal >> 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 logic= al >> unit addressing format' (SAM-5 Table 26) and the 8-byte 'Extended logica= l >> 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 k= nown >> * 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 CONDIT= ION" >> * field of SSU (START STOP UNIT) command. But this "power condition" fi= eld >> * will take effect only when its sent to "UFS device" well known logica= l unit >> * hence we require the scsi_device instance to represent this logical u= nit in >> * order for the UFS host driver to send the SSU command for power manag= ement. >> * >> * 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 a= lso >> * want to have access to BOOT LU. >> * >> * This function adds scsi device instances for each of all well known L= Us >> * (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 t= o >> probe/register WLUNs in FreeBSD? (Is there an equivalent to Linux=E2=80= =99s >> __scsi_add_device()?) > > > [[ I didn't trim context here, since it lays out the problem nicely). ]] > > So I can make a case for either (1) or (2). > > It's easy enough to add the enumeration for (1) to scsi_xpt.c It's just a= few more states in the probe state machine (which is a bit complex, but no= t terribly so). If we treat them as separate LUNs, then a lot of the infras= tructure would just work. The key, though, is how do we keep scsi_da, etc f= rom attaching to these new nodes. And would we have generic scsi_foo.c driv= ers for them (so the devices would get their own periph drivers) or whether= there's a higher-level device that would know it could use these devices i= f it finds them and it wouldn't have a specific specialized kernel drive fo= r them, but instead use a generalized pass thru device. > > I guess a lot of that would depend where things like power management is = happening. If it's in the UFS sim, that would suggest a different design th= an if this was some super generic thing that would respond to generic event= s that maybe the SIMs generate or maybe somebody else. > > If we wanted to go with (1) heavily, we'd need new, generic periph driver= s along with some kind of way to get them to respond to, or report out even= ts in the system or with the drive. With only a couple of examples, this mi= ght be difficult to abstract properly. > > If we wanted to go with (2), then we'd likely need some extensions in xpt= around this so that the sim could discover, manage and use the WLUN device= s. > > Though the more I think about it, maybe it doesn't matter: we want to do = the WLUN probing regardless. It's who manages the cam_ed structures after t= hat. Where does the periph driver live, etc. > > I think I need to go read the UFS specs in more detail than I have time f= or this afternoon... > > Warner > > Warner