aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaeyoon Choi <jaeyoon@FreeBSD.org>2026-08-10 01:35:45 +0000
committerJaeyoon Choi <jaeyoon@FreeBSD.org>2026-08-10 02:28:48 +0000
commit360b7c1635ea772d41275f8d1061cef4e131e328 (patch)
treea6c73ddb1cc679c703479f80713a295114cdf89b
parentc9827f1528a69664f4031e1c511b2e7022601a7c (diff)
ufshci: fix SCSI I/O request failure cleanup
ufshchi_sim_scsiio() did not check the M_NOWAIT request allocation for NULL. The CDB validation and submit failure paths also returned without freeing the request. Fail the CCB when the allocation returns NULL. Free the request on every failure path. Mark the CCB as queued right before the submit, so the failure paths above do not need to touch that flag. Sponsored by: Samsung Electronics Reviewed by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D58656
-rw-r--r--sys/dev/ufshci/ufshci_sim.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c
index 404f3e99d1e2..234ee3bf7dfa 100644
--- a/sys/dev/ufshci/ufshci_sim.c
+++ b/sys/dev/ufshci/ufshci_sim.c
@@ -150,6 +150,11 @@ ufshchi_sim_scsiio(struct cam_sim *sim, union ccb *ccb)
else
req = ufshci_allocate_request_vaddr(payload, payload_len,
M_NOWAIT, ufshci_sim_scsiio_done, ccb);
+ if (req == NULL) {
+ ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
+ xpt_done(ccb);
+ return;
+ }
req->request_size = sizeof(struct ufshci_cmd_command_upiu);
req->response_size = sizeof(struct ufshci_cmd_response_upiu);
@@ -178,8 +183,6 @@ ufshchi_sim_scsiio(struct cam_sim *sim, union ccb *ccb)
upiu->expected_data_transfer_length = htobe32(payload_len);
- ccb->ccb_h.status |= CAM_SIM_QUEUED;
-
if (csio->ccb_h.flags & CAM_CDB_POINTER)
cdb = csio->cdb_io.cdb_ptr;
else
@@ -187,18 +190,22 @@ ufshchi_sim_scsiio(struct cam_sim *sim, union ccb *ccb)
if (cdb == NULL || csio->cdb_len > sizeof(upiu->cdb)) {
ccb->ccb_h.status = CAM_REQ_INVALID;
+ ufshci_free_request(req);
xpt_done(ccb);
return;
}
memcpy(upiu->cdb, cdb, csio->cdb_len);
+ ccb->ccb_h.status |= CAM_SIM_QUEUED;
error = ufshci_ctrlr_submit_transfer_request(ctrlr, req);
if (error == EBUSY) {
ccb->ccb_h.status = CAM_SCSI_BUSY;
+ ufshci_free_request(req);
xpt_done(ccb);
return;
} else if (error) {
ccb->ccb_h.status = CAM_REQ_INVALID;
+ ufshci_free_request(req);
xpt_done(ccb);
return;
}