Re: Questions about probing WLUNs for UFS power management

Jaeyoon Choi <[email protected]> Tue, 14 Oct 2025 19:23:35 +0900
Newsgroups gmane.os.freebsd.devel.scsi
Message-ID <CADd34gy2PipwYemxE37VYtUvEV5Xg+yXOmY-T68L6QFCE6zUAQ@mail.gmail.com>
I looked through the code again and re-thought the design.

1) We need to control the suspend/resume order between normal LUNs and
WLUNs, so the power-management logic has to live in the UFS driver
(WLUN should suspend only after all normal LUNs are suspended).
Because of this, I think we should call
EVENTHANDLER_REGISTER(suspend/resume) in the UFS driver.
2) Since the power-management logic is in the UFS driver, the UFS
driver should build the START STOP UNIT CCB and call xpt_action().
3) If suspend/resume(power-management logic) is handled inside the UFS
driver, the WLUN periph would only probe WLUNs.

So we need to choose:
(1) do we implement a WLUN periph and let SCSI XPT own the cam_ed, or
(2) do we have the UFS driver call xpt_alloc_device() and own the
cam_ed directly?

Given that power management is implemented in the UFS SIM/driver,
option (2) seems more suitable to me. What do you think?

Jaeyoon

On Thu, Oct 2, 2025 at 5:13=E2=80=AFPM Jaeyoon Choi <[email protected]> w=
rote:
>
> Hi Warner,
>
> I=E2=80=99m not fully sure this is the best path yet, but I looked more i=
nto option (1).
> Below are the questions I had and the answers I found.
>
> Q. Are the semantics of START STOP UNIT (SSU) in the UFS spec the same
> as in SBC-5?
> A. Yes. SBC-5 defines SSU in a flexible way, and the UFS spec defines
> its SSU usage to be compliant with SBC-5.
>
> Q. Where is SSU used in (linux) UFS driver?
> A. Power management. During suspend the driver sends 'UFS-Sleep (POWER
> CONDITION =3D 0x2)' or 'UFS-PowerDown (0x3)', and during resume the
> driver sends 'Active (0x1)'.
>
> Q. Can we reuse an existing periph driver?
> A. No. Existing periph drivers aren=E2=80=99t suitable for WLUNs. The pas=
s
> thru device also doesn't implement suspend/resume.
>
> Q. How do we register handlers for suspend/resume in FreeBSD?
> A. A periph driver can register handlers at init time with
> EVENTHANDLER_REGISTER(power_suspend, ...) and
> EVENTHANDLER_REGISTER(power_resume, ...).
>
> Now that those questions have been clarified, I fully understand your com=
ments.
>
> At this point, it seems we need to create a periph driver like
> `scsi_wlun.c` for attaching WLUNs, and implement suspend/resume
> function within it.
> In suspend/resume, we should issue the SSU command.
>
> Planned tasks:
> 1) Define a `PIM_WLUN` flag so only drivers that want WLUNs discover them=
.
> 2) Use `REPORT LUNS` with `SELECT REPORT` =3D 0x01 to obtain the WLUN lis=
t first.
> 3) Add a `CAM_GET_WLUN()` macro to parse the WLUN list.
> 4) When `CAM_GET_WLUN()` finds a match, automatically attach the WLUN per=
iph.
> 5) In `scsi_wlun.c` 'wluninit()', register power handlers
> (EVENTHANDLER_REGISTER(power_suspend, wlunsuspend, ...),
> EVENTHANDLER_REGISTER(power_resume, wlunresume, ...)).
> 6) In `wlunsuspend() / wlunresume()`, issue SSU commands to the UFS Devic=
e WLUN.
> 7) The order between LUN periph (da) and WLUN periph must be guaranteed.
>    (Ensure that the WLUN SSU is issued last during suspension and
> first during resumption.)
>
> It's Korean Thanksgiving day until October 10. I'll take a short break
> and then start prototyping this right after.
> If I've misunderstood anything, please let me know.
>
> Jaeyoon
>
> On Wed, Oct 1, 2025 at 12:11=E2=80=AFPM Jaeyoon Choi <[email protected]=
> wrote:
> >
> > > It's easy enough to add the enumeration for (1) to scsi_xpt.c It's ju=
st a few more states in the probe state machine (which is a bit complex, bu=
t not terribly so). If we treat them as separate LUNs, then a lot of the in=
frastructure would just work. The key, though, is how do we keep scsi_da, e=
tc from attaching to these new nodes. And would we have generic scsi_foo.c =
drivers for them (so the devices would get their own periph drivers) or whe=
ther there's a higher-level device that would know it could use these devic=
es if it finds them and it wouldn't have a specific specialized kernel driv=
e for 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 desig=
n than if this was some super generic thing that would respond to generic e=
vents that maybe the SIMs generate or maybe somebody else.
> >
> > Refer to Section 7.4.2 =E2=80=9CPower Management Command: START STOP UN=
IT=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]> wr=
ote:
> > >
> > > Please excuse the tardy response
> > >
> > > On Tue, Sep 23, 2025 at 8:32=E2=80=AFPM Jaeyoon Choi <jaeyoon@freebsd=
.org> wrote:
> > >>
> > >> Hello freebsd-scsi,
> > >>
> > >> I=E2=80=99m trying to implement Well-known LUNs (WLUNs) for the UFS =
(Universal
> > >> Flash Storage, ufshci(4)) driver, but the current SCSI XPT doesn't p=
robe
> > >> WLUNs, so I have a few questions.
> > >>
> > >> First, Well-known LUNs are defined in SCSI SAM-5. In UFS, 'REPORT LU=
NS',
> > >> '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 requir=
es
> > >> 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 cha=
nged
> > >> 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 l=
ogical
> > >> unit addressing format' (SAM-5 Table 26) and the 8-byte 'Extended lo=
gical
> > >> 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 com=
mand.
> > >> 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 Val=
ues")
> > >>
> > >> ```
> > >> 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 SC=
SI
> > >> layer. Therefore, the Linux UFS driver explicitly registers the WLUN=
s
> > >> 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 we=
ll known
> > >>  * 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 CO=
NDITION"
> > >>  * field of SSU (START STOP UNIT) command. But this "power condition=
" field
> > >>  * will take effect only when its sent to "UFS device" well known lo=
gical unit
> > >>  * hence we require the scsi_device instance to represent this logic=
al unit in
> > >>  * order for the UFS host driver to send the SSU command for power m=
anagement.
> > >>  *
> > >>  * We also require the scsi_device instance for "RPMB" (Replay Prote=
cted Memory
> > >>  * Block) LU so user space process can control this LU. User space m=
ay also
> > >>  * want to have access to BOOT LU.
> > >>  *
> > >>  * This function adds scsi device instances for each of all well kno=
wn LUs
> > >>  * (except "REPORT LUNS" LU).
> > >>  *
> > >>  * Return: zero on success (all required W-LUs are added successfull=
y),
> > >>  * non-zero error value on failure (if failed to add any of the requ=
ired 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), NUL=
L);
> > >>     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 W=
LUN
> > >> 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 driv=
er to
> > >> 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 ju=
st a few more states in the probe state machine (which is a bit complex, bu=
t not terribly so). If we treat them as separate LUNs, then a lot of the in=
frastructure would just work. The key, though, is how do we keep scsi_da, e=
tc from attaching to these new nodes. And would we have generic scsi_foo.c =
drivers for them (so the devices would get their own periph drivers) or whe=
ther there's a higher-level device that would know it could use these devic=
es if it finds them and it wouldn't have a specific specialized kernel driv=
e for 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 desig=
n than if this was some super generic thing that would respond to generic e=
vents that maybe the SIMs generate or maybe somebody else.
> > >
> > > If we wanted to go with (1) heavily, we'd need new, generic periph dr=
ivers along with some kind of way to get them to respond to, or report out =
events in the system or with the drive. With only a couple of examples, thi=
s might 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 de=
vices.
> > >
> > > 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 aft=
er that. Where does the periph driver live, etc.
> > >
> > > I think I need to go read the UFS specs in more detail than I have ti=
me for this afternoon...
> > >
> > > Warner
> > >
> > > Warner