in master/mipi-i3c-hci/core.c [191:260]
static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m,
struct i3c_ccc_cmd *ccc)
{
struct i3c_hci *hci = to_i3c_hci(m);
struct hci_xfer *xfer;
bool raw = !!(hci->quirks & HCI_QUIRK_RAW_CCC);
bool prefixed = raw && !!(ccc->id & I3C_CCC_DIRECT);
unsigned int nxfers = ccc->ndests + prefixed;
DECLARE_COMPLETION_ONSTACK(done);
int i, last, ret = 0;
DBG("cmd=%#x rnw=%d ndests=%d data[0].len=%d",
ccc->id, ccc->rnw, ccc->ndests, ccc->dests[0].payload.len);
xfer = hci_alloc_xfer(nxfers);
if (!xfer)
return -ENOMEM;
if (prefixed) {
xfer->data = NULL;
xfer->data_len = 0;
xfer->rnw = false;
hci->cmd->prep_ccc(hci, xfer, I3C_BROADCAST_ADDR,
ccc->id, true);
xfer++;
}
for (i = 0; i < nxfers - prefixed; i++) {
xfer[i].data = ccc->dests[i].payload.data;
xfer[i].data_len = ccc->dests[i].payload.len;
xfer[i].rnw = ccc->rnw;
ret = hci->cmd->prep_ccc(hci, &xfer[i], ccc->dests[i].addr,
ccc->id, raw);
if (ret)
goto out;
xfer[i].cmd_desc[0] |= CMD_0_ROC;
}
last = i - 1;
xfer[last].cmd_desc[0] |= CMD_0_TOC;
xfer[last].completion = &done;
if (prefixed)
xfer--;
ret = hci->io->queue_xfer(hci, xfer, nxfers);
if (ret)
goto out;
if (!wait_for_completion_timeout(&done, HZ) &&
hci->io->dequeue_xfer(hci, xfer, nxfers)) {
ret = -ETIME;
goto out;
}
for (i = prefixed; i < nxfers; i++) {
if (ccc->rnw)
ccc->dests[i - prefixed].payload.len =
RESP_DATA_LENGTH(xfer[i].response);
if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) {
ret = -EIO;
goto out;
}
}
if (ccc->rnw)
DBG("got: %*ph",
ccc->dests[0].payload.len, ccc->dests[0].payload.data);
out:
hci_free_xfer(xfer, nxfers);
return ret;
}