diff options
| author | Jaeyoon Choi <jaeyoon@FreeBSD.org> | 2026-08-10 01:46:50 +0000 |
|---|---|---|
| committer | Jaeyoon Choi <jaeyoon@FreeBSD.org> | 2026-08-10 02:28:52 +0000 |
| commit | 50a00f10d830119ed54f5bce1b34533f3a09325e (patch) | |
| tree | 6ffccbc5754b20ebbe345f116611546c09702ee2 | |
| parent | 456ab423dddc0ce07787b21fcb79426abc7b436e (diff) | |
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
| -rw-r--r-- | sys/dev/ufshci/ufshci_ctrlr_cmd.c | 10 | ||||
| -rw-r--r-- | sys/dev/ufshci/ufshci_dev.c | 2 | ||||
| -rw-r--r-- | sys/dev/ufshci/ufshci_req_queue.c | 13 |
3 files changed, 13 insertions, 12 deletions
diff --git a/sys/dev/ufshci/ufshci_ctrlr_cmd.c b/sys/dev/ufshci/ufshci_ctrlr_cmd.c index 2e85cfa4b5b0..faeb6f98c942 100644 --- a/sys/dev/ufshci/ufshci_ctrlr_cmd.c +++ b/sys/dev/ufshci/ufshci_ctrlr_cmd.c @@ -29,9 +29,9 @@ ufshci_ctrlr_cmd_send_task_mgmt_request(struct ufshci_controller *ctrlr, UFSHCI_UPIU_TRANSACTION_CODE_TASK_MANAGEMENT_REQUEST; upiu->header.lun = lun; upiu->header.ext_iid_or_function = function; - upiu->input_param1 = lun; - upiu->input_param2 = task_tag; - upiu->input_param3 = iid; + upiu->input_param1 = htobe32(lun); + upiu->input_param2 = htobe32(task_tag); + upiu->input_param3 = htobe32(iid); error = ufshci_ctrlr_submit_task_mgmt_request(ctrlr, req); if (error) @@ -87,8 +87,8 @@ ufshci_ctrlr_cmd_send_query_request(struct ufshci_controller *ctrlr, upiu->idn = param.type; upiu->index = param.index; upiu->selector = param.selector; - upiu->value_64 = param.value; - upiu->length = param.desc_size; + upiu->value_64 = htobe64(param.value); + upiu->length = htobe16(param.desc_size); error = ufshci_ctrlr_submit_transfer_request(ctrlr, req); if (error) diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c index db7a8c564a29..454572f966d5 100644 --- a/sys/dev/ufshci/ufshci_dev.c +++ b/sys/dev/ufshci/ufshci_dev.c @@ -192,7 +192,7 @@ ufshci_dev_read_attribute(struct ufshci_controller *ctrlr, return (ENXIO); } - *value = status.cpl.response_upiu.query_response_upiu.value_64; + *value = be64toh(status.cpl.response_upiu.query_response_upiu.value_64); return (0); } diff --git a/sys/dev/ufshci/ufshci_req_queue.c b/sys/dev/ufshci/ufshci_req_queue.c index d8d86070c18c..db96d13fad24 100644 --- a/sys/dev/ufshci/ufshci_req_queue.c +++ b/sys/dev/ufshci/ufshci_req_queue.c @@ -484,6 +484,7 @@ ufshci_abort_complete(void *arg, const struct ufshci_completion *status, bool error) { struct ufshci_tracker *tr = arg; + uint32_t output_param1; /* * We still need to check the active tracker array, to cover race where @@ -508,12 +509,12 @@ ufshci_abort_complete(void *arg, const struct ufshci_completion *status, ufshci_req_queue_manual_complete_tracker(tr, UFSHCI_DESC_ABORTED, UFSHCI_RESPONSE_CODE_GENERAL_FAILURE); - if ((status->response_upiu.task_mgmt_response_upiu - .output_param1 == - UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE) || - (status->response_upiu.task_mgmt_response_upiu - .output_param1 == - UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED)) { + output_param1 = be32toh( + status->response_upiu.task_mgmt_response_upiu.output_param1); + if (output_param1 == + UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_COMPLETE || + output_param1 == + UFSHCI_TASK_MGMT_SERVICE_RESPONSE_FUNCTION_SUCCEEDED) { ufshci_printf(tr->hwq->ctrlr, "Warning: the abort task request completed \ successfully, but the original task is still incomplete."); |
