Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

i3c: mipi-i3c-hci: Consolidate common xfer processing logic

Several parts of the MIPI I3C HCI driver duplicate the same sequence for
queuing a transfer, waiting for completion, and handling timeouts. This
logic appears in five separate locations and will be affected by an
upcoming fix.

Refactor the repeated code into a new helper, i3c_hci_process_xfer(), and
store the timeout value in the hci_xfer structure so that callers do not
need to pass it as a separate parameter.

Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260306072451.11131-12-adrian.hunter@intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Adrian Hunter and committed by
Alexandre Belloni
7ac45bc6 b6d58643

+33 -28
+3 -5
drivers/i3c/master/mipi-i3c-hci/cmd_v1.c
··· 331 331 CMD_A0_ROC | CMD_A0_TOC; 332 332 xfer->cmd_desc[1] = 0; 333 333 xfer->completion = &done; 334 - hci->io->queue_xfer(hci, xfer, 1); 335 - if (!wait_for_completion_timeout(&done, HZ) && 336 - hci->io->dequeue_xfer(hci, xfer, 1)) { 337 - ret = -ETIMEDOUT; 334 + xfer->timeout = HZ; 335 + ret = i3c_hci_process_xfer(hci, xfer, 1); 336 + if (ret) 338 337 break; 339 - } 340 338 if ((RESP_STATUS(xfer->response) == RESP_ERR_ADDR_HEADER || 341 339 RESP_STATUS(xfer->response) == RESP_ERR_NACK) && 342 340 RESP_DATA_LENGTH(xfer->response) == 1) {
+3 -5
drivers/i3c/master/mipi-i3c-hci/cmd_v2.c
··· 253 253 xfer[0].rnw = true; 254 254 xfer[0].cmd_desc[1] = CMD_A1_DATA_LENGTH(8); 255 255 xfer[1].completion = &done; 256 + xfer[1].timeout = HZ; 256 257 257 258 for (;;) { 258 259 ret = i3c_master_get_free_addr(&hci->master, next_addr); ··· 273 272 CMD_A0_ASSIGN_ADDRESS(next_addr) | 274 273 CMD_A0_ROC | 275 274 CMD_A0_TOC; 276 - hci->io->queue_xfer(hci, xfer, 2); 277 - if (!wait_for_completion_timeout(&done, HZ) && 278 - hci->io->dequeue_xfer(hci, xfer, 2)) { 279 - ret = -ETIMEDOUT; 275 + ret = i3c_hci_process_xfer(hci, xfer, 2); 276 + if (ret) 280 277 break; 281 - } 282 278 if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) { 283 279 ret = 0; /* no more devices to be assigned */ 284 280 break;
+25 -18
drivers/i3c/master/mipi-i3c-hci/core.c
··· 213 213 reg_write(DCT_SECTION, FIELD_PREP(DCT_TABLE_INDEX, 0)); 214 214 } 215 215 216 + int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n) 217 + { 218 + struct completion *done = xfer[n - 1].completion; 219 + unsigned long timeout = xfer[n - 1].timeout; 220 + int ret; 221 + 222 + ret = hci->io->queue_xfer(hci, xfer, n); 223 + if (ret) 224 + return ret; 225 + 226 + if (!wait_for_completion_timeout(done, timeout) && 227 + hci->io->dequeue_xfer(hci, xfer, n)) { 228 + dev_err(&hci->master.dev, "%s: timeout error\n", __func__); 229 + return -ETIMEDOUT; 230 + } 231 + 232 + return 0; 233 + } 234 + 216 235 static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, 217 236 struct i3c_ccc_cmd *ccc) 218 237 { ··· 272 253 last = i - 1; 273 254 xfer[last].cmd_desc[0] |= CMD_0_TOC; 274 255 xfer[last].completion = &done; 256 + xfer[last].timeout = HZ; 275 257 276 258 if (prefixed) 277 259 xfer--; 278 260 279 - ret = hci->io->queue_xfer(hci, xfer, nxfers); 261 + ret = i3c_hci_process_xfer(hci, xfer, nxfers); 280 262 if (ret) 281 263 goto out; 282 - if (!wait_for_completion_timeout(&done, HZ) && 283 - hci->io->dequeue_xfer(hci, xfer, nxfers)) { 284 - ret = -ETIMEDOUT; 285 - goto out; 286 - } 287 264 for (i = prefixed; i < nxfers; i++) { 288 265 if (ccc->rnw) 289 266 ccc->dests[i - prefixed].payload.len = ··· 350 335 last = i - 1; 351 336 xfer[last].cmd_desc[0] |= CMD_0_TOC; 352 337 xfer[last].completion = &done; 338 + xfer[last].timeout = HZ; 353 339 354 - ret = hci->io->queue_xfer(hci, xfer, nxfers); 340 + ret = i3c_hci_process_xfer(hci, xfer, nxfers); 355 341 if (ret) 356 342 goto out; 357 - if (!wait_for_completion_timeout(&done, HZ) && 358 - hci->io->dequeue_xfer(hci, xfer, nxfers)) { 359 - ret = -ETIMEDOUT; 360 - goto out; 361 - } 362 343 for (i = 0; i < nxfers; i++) { 363 344 if (i3c_xfers[i].rnw) 364 345 i3c_xfers[i].len = RESP_DATA_LENGTH(xfer[i].response); ··· 394 383 last = i - 1; 395 384 xfer[last].cmd_desc[0] |= CMD_0_TOC; 396 385 xfer[last].completion = &done; 386 + xfer[last].timeout = m->i2c.timeout; 397 387 398 - ret = hci->io->queue_xfer(hci, xfer, nxfers); 388 + ret = i3c_hci_process_xfer(hci, xfer, nxfers); 399 389 if (ret) 400 390 goto out; 401 - if (!wait_for_completion_timeout(&done, m->i2c.timeout) && 402 - hci->io->dequeue_xfer(hci, xfer, nxfers)) { 403 - ret = -ETIMEDOUT; 404 - goto out; 405 - } 406 391 for (i = 0; i < nxfers; i++) { 407 392 if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) { 408 393 ret = -EIO;
+2
drivers/i3c/master/mipi-i3c-hci/hci.h
··· 89 89 unsigned int data_len; 90 90 unsigned int cmd_tid; 91 91 struct completion *completion; 92 + unsigned long timeout; 92 93 union { 93 94 struct { 94 95 /* PIO specific */ ··· 157 156 void amd_set_od_pp_timing(struct i3c_hci *hci); 158 157 void amd_set_resp_buf_thld(struct i3c_hci *hci); 159 158 void i3c_hci_sync_irq_inactive(struct i3c_hci *hci); 159 + int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n); 160 160 161 161 #endif