| ae31f292 | 15-Sep-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: add a passthrough ioctl
This ioctl is for a port of ufs-utils: https://github.com/SanDisk-Open-Source/ufs-utils
The driver only exposed a CAM SIM. Reading a descriptor, an attribute or a fl
ufshci: add a passthrough ioctl
This ioctl is for a port of ufs-utils: https://github.com/SanDisk-Open-Source/ufs-utils
The driver only exposed a CAM SIM. Reading a descriptor, an attribute or a flag needs a query request, and a UniPro attribute needs a DME command. The driver built both only for its own setup, so userland could reach neither.
Add two ioctls on the control node. UFSHCI_PASSTHROUGH_CMD sends a UPIU the caller built, sizes the request from its transaction code, and copies the response UPIU back. UFSHCI_PASSTHROUGH_UIC carries the four attribute commands and refuses the rest, which can drop the link or power the device off. It keeps the raw argument2 so the caller can read the result code the device reported, not just a failure.
Validate the input and bound it by what the controller can map. The descriptor has no request length, so the controller reads it from the UPIU header, and a header that declares more than was copied in would reach past the descriptor. The ioctl layer copies output back only on a zero return. So a command that reached the device is a success even when it was refused. The caller reads the reason from the response header, and an answerless failure comes back as EIO. Clear the response before use so no stale bytes read as a device answer.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D59559
show more ...
|
| 28fefc44 | 15-Sep-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: add a control device node
The driver only exposed a CAM SIM. Userland had no way to reach the device for anything that is not a SCSI command, so reading a descriptor or an attribute was impo
ufshci: add a control device node
The driver only exposed a CAM SIM. Userland had no way to reach the device for anything that is not a SCSI command, so reading a descriptor or an attribute was impossible.
Add /dev/ufshci%d as a root only node and the ioctl ABI header for it. The node answers no ioctl yet. The header pulls in ufshci.h, which declares bool only under _KERNEL, so include stdbool.h for userland the way nvme.h already does.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D59558
show more ...
|
| 99301502 | 02-Sep-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: skip the reinit when the new link works
UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH always rebuilt the link after the gear switch. It threw away a working HS link and ended up in PWM. The rein
ufshci: skip the reinit when the new link works
UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH always rebuilt the link after the gear switch. It threw away a working HS link and ended up in PWM. The reinit is only needed for a dead link. There the local side reports HS and the peer never answers. A local readback cannot tell the two apart. Peer traffic can.
Probe the peer with DME_PEER_GET after the switch. Skip the reinit when the probe succeeds. Log it when the probe fails.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D59299
show more ...
|
| c09daa33 | 02-Sep-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: set HS series per platform and adapt type per gear
The driver always asked for Rate-B. It never set the adaptation type. The Snapdragon X Elite firmware tunes the PHY for Rate-A. A Rate-B li
ufshci: set HS series per platform and adapt type per gear
The driver always asked for Rate-B. It never set the adaptation type. The Snapdragon X Elite firmware tunes the PHY for Rate-A. A Rate-B link dies at every gear there. HS-G4 and above need initial adaptation. This is a UniPro rule. It applies to every host.
Add an hs_series field to the device tables. Use Rate-A on the Snapdragon X Elite. Keep Rate-B on the PCI hosts. A table entry without an HS series fails to attach. Set PA_TxHsAdaptType to initial adaptation at HS-G4 and above. Leave it alone below that. Hosts before UniPro 1.8 do not have it. The Galaxy Book 4 Edge now links at HS-G5 Rate-A.
fio results (128k sequential, 4k random, posixaio):
QD | SEQ_R(MiB/s) | SEQ_W(MiB/s) | RND_R(kIOPS) | RND_W(kIOPS) ----+--------------+--------------+--------------+------------- 1 | 1357 | 1221 | 12.1 | 27.2 4 | 3103 | 3234 | 46.5 | 92.9 32 | 3508 | 3238 | 176.4 | 125.0
Sequential writes land in the WriteBooster buffer. Sustained writes drop to 556 MiB/s once the buffer runs out.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D59298
show more ...
|
| 3ecee931 | 27-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: reject new requests on a failed controller
A failed controller accepted new requests, but nothing ever completed them, so the caller waited forever. The admin retry path could also resubmit
ufshci: reject new requests on a failed controller
A failed controller accepted new requests, but nothing ever completed them, so the caller waited forever. The admin retry path could also resubmit a request to a dead queue.
Reject new submits and admin retries on a failed controller. The submit check runs under the queue lock, so it cannot race with the queue walk in the fail path.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58948
show more ...
|
| e59d4ec6 | 27-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: handle a recovery reset before the SIM attach
When the first start attempt fails early, the recovery reset runs the start sequence again without a SIM. That pass still looked up the WLUN, so
ufshci: handle a recovery reset before the SIM attach
When the first start attempt fails early, the recovery reset runs the start sequence again without a SIM. That pass still looked up the WLUN, so it dereferenced a NULL SIM and panicked.
Attach the SIM whenever it does not exist yet. Also make the WLUN lookup return NULL when there is no SIM.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58947
show more ...
|
| 746278a6 | 27-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: build valid fake responses for manual completion
The manual completion wrote the fake response to the wrong descriptor for task management slots. It also left the task tag at zero, which tri
ufshci: build valid fake responses for manual completion
The manual completion wrote the fake response to the wrong descriptor for task management slots. It also left the task tag at zero, which tripped the task tag check under INVARIANTS.
Write the fake response where the completion path reads it. Copy the task tag from the request.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58946
show more ...
|
| 7682b8f3 | 27-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: claim trackers before failing them
ufshci_req_queue_fail() drops the queue lock to complete each tracker. In that window the completion path could complete the same tracker again.
Claim the
ufshci: claim trackers before failing them
ufshci_req_queue_fail() drops the queue lock to complete each tracker. In that window the completion path could complete the same tracker again.
Claim the slot before dropping the lock, so the completion scan skips it. Reserved slots are left to their submit thread, which completes them itself. The manual request completion helper lost its only caller, so drop it.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58945
show more ...
|
| 68091ebf | 18-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: report the highest LUN number in the path inquiry
cpi->max_lun is an inclusive upper bound, but the driver reported the LUN count (8 or 32), so CAM probed one nonexistent LUN past the end.
ufshci: report the highest LUN number in the path inquiry
cpi->max_lun is an inclusive upper bound, but the driver reported the LUN count (8 or 32), so CAM probed one nonexistent LUN past the end.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58820
show more ...
|
| 34518292 | 18-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: correct the crypto/config register offsets and HCMID fields
The reserved array after CCAP must be 508, but it was 511. This pushed the config, MCQ config, and ESI registers from 0x300 and 0x
ufshci: correct the crypto/config register offsets and HCMID fields
The reserved array after CCAP must be 508, but it was 511. This pushed the config, MCQ config, and ESI registers from 0x300 and 0x380 up to 0x900. None of these registers are used yet, so nothing broke.
Also fix the HCMID bank index field. The spec places it at bits [23:16], but it was defined on top of the manufacturer code at [15:0].
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58819
show more ...
|
| e1aa173f | 18-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: consolidate the device query submit/poll pattern
The six query helpers duplicated the same submit, error check, poll, and status check sequence. Move it into ufshci_dev_send_query() so futur
ufshci: consolidate the device query submit/poll pattern
The six query helpers duplicated the same submit, error check, poll, and status check sequence. Move it into ufshci_dev_send_query() so future changes to the query flow are made in one place. This also unifies the failure log message format.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58818
show more ...
|
| f3c3db35 | 18-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: validate the CDB before allocating a request
The CDB pointer and length checks depend only on the CCB, so perform them before allocating and initializing the request. This avoids a wasted al
ufshci: validate the CDB before allocating a request
The CDB pointer and length checks depend only on the CCB, so perform them before allocating and initializing the request. This avoids a wasted allocation for invalid CCBs on the I/O path and removes one request-free error path.
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58817
show more ...
|
| dbcebc7c | 18-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: pass the queue being destroyed to the cmd descriptor teardown
ufshci_req_sdb_destroy() hardcoded &ctrlr->transfer_req_queue when destroying command descriptors instead of using its req_queue
ufshci: pass the queue being destroyed to the cmd descriptor teardown
ufshci_req_sdb_destroy() hardcoded &ctrlr->transfer_req_queue when destroying command descriptors instead of using its req_queue argument.
No functional change: the branch only runs for the transfer queue, so the two pointers are always the same today. Using the argument keeps the function queue-agnostic for when more transfer queues exist (MCQ).
Reviewed by: imp (mentor) Sponsored by: Samsung Electronics Differential Revision: https://reviews.freebsd.org/D58816
show more ...
|
| a33860b0 | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: do not reset the device in the XPT_RESET_DEV handler
CAM calls the SIM action callback with the SIM lock and the CAM device lock held. The XPT_RESET_DEV handler called ufshci_dev_reset(), wh
ufshci: do not reset the device in the XPT_RESET_DEV handler
CAM calls the SIM action callback with the SIM lock and the CAM device lock held. The XPT_RESET_DEV handler called ufshci_dev_reset(), which sleeps on device commands. Sleeping there panics when another thread contends for the lock: "panic: sleeping thread holds CAM device lock".
Report success without touching the device, as nvme_sim(4) does. A real device reset needs the controller reset path. That rework is planned together with in-flight request recovery.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58671
show more ...
|
| 2d329613 | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: free the taskqueue on detach
ufshci_ctrlr_destruct() never freed the taskqueue. Every load and unload cycle leaked the taskqueue and its kernel thread. A task that was still queued could als
ufshci: free the taskqueue on detach
ufshci_ctrlr_destruct() never freed the taskqueue. Every load and unload cycle leaked the taskqueue and its kernel thread. A task that was still queued could also run after the module was gone.
Free the taskqueue in destruct. Do it after the interrupt teardown so nothing enqueues new work. A reset task that is still queued at this point races the queue teardown. That race is older than this change. The planned in-flight recovery rework will close it.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58670
show more ...
|
| aaf0e80e | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: release the CCB after sending a start stop unit command
ufshci_sim_send_ssu() got a CCB from cam_periph_getccb() but never returned it. Each call leaked the CCB and one slot of the device's
ufshci: release the CCB after sending a start stop unit command
ufshci_sim_send_ssu() got a CCB from cam_periph_getccb() but never returned it. Each call leaked the CCB and one slot of the device's CCB allocation budget. When the budget runs out, the next cam_periph_getccb() waits forever and the suspend path hangs.
Release the CCB while the periph lock is still held, as the other CAM periph drivers do.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58669
show more ...
|
| c686e7d3 | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: check completions under the queue lock
The completion scan held only the recovery lock. The submit path sets a slot to SCHEDULED and then rings the doorbell, both under the queue lock. A sca
ufshci: check completions under the queue lock
The completion scan held only the recovery lock. The submit path sets a slot to SCHEDULED and then rings the doorbell, both under the queue lock. A scan running between those two steps saw a SCHEDULED slot with a clear doorbell and completed a command the device had not started. The command failed with OCS 0xf, and a reused slot could return wrong read data.
Check the slot state and the doorbell under the queue lock. The submit path holds it across both steps, so a half-submitted slot can no longer be seen. Found with fio randrw verify on QEMU.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58668
show more ...
|
| 266ce89f | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: read UIC command results while holding the lock
The UIC result registers (UICCMDARG2/3) are only valid between a command's completion and the next command's submission. They were read after
ufshci: read UIC command results while holding the lock
The UIC result registers (UICCMDARG2/3) are only valid between a command's completion and the next command's submission. They were read after uic_cmd_lock was dropped, so a concurrent UIC submitter could overwrite them in between. Read them into locals before releasing the lock.
Also mask the generic error code to its [7:0] field when checking it, so unrelated bits in UICCMDARG2 (such as the attribute set type echoed for DME_SET) cannot be mistaken for an error.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58667
show more ...
|
| af00e00f | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: initialize desc_size for non-descriptor query requests
The flag and attribute query builders left param.desc_size uninitialized, so stack garbage was sent as the query UPIU length field. Dev
ufshci: initialize desc_size for non-descriptor query requests
The flag and attribute query builders left param.desc_size uninitialized, so stack garbage was sent as the query UPIU length field. Devices generally ignore the length for these opcodes, which hid the bug. Zero it explicitly.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58665
show more ...
|
| 50a00f10 | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: byte-swap big-endian UPIU fields
The UPIU wire fields are big-endian. The task management and query builders wrote host-order values into them. The completion paths also read the results bac
ufshci: byte-swap big-endian UPIU fields
The UPIU wire fields are big-endian. The task management and query builders wrote host-order values into them. The completion paths also read the results back without conversion. On a little-endian host an ABORT_TASK carried a swapped task tag and LUN, a query carried a swapped length, and attribute reads returned swapped values. Tolerant devices masked most of the damage.
Convert with htobe*/be*toh at the wire boundary, as ufshci_sim.c already does for its fields.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58664
show more ...
|
| 456ab423 | 10-Aug-2026 |
Jaeyoon Choi <jaeyoon@FreeBSD.org> |
ufshci: initialize alloc_units before the dedicated-buffer scan
If every unit descriptor read failed in the LU-dedicated WriteBooster scan, alloc_units was used uninitialized. Start it at zero so th
ufshci: initialize alloc_units before the dedicated-buffer scan
If every unit descriptor read failed in the LU-dedicated WriteBooster scan, alloc_units was used uninitialized. Start it at zero so that case is treated as a zero-sized buffer and WriteBooster is disabled.
Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58663
show more ...
|