static int send_scpi_cmd(struct scpi_data_buf *scpi_buf, bool high_priority) { struct mbox_chan *chan; struct mbox_client cl = {0}; struct mhu_data_buf *data = scpi_buf->data; u32 status; cl.dev = the_scpi_device; cl.rx_callback = scpi_rx_callback; chan = mbox_request_channel(&cl, high_priority); if (IS_ERR(chan)) return PTR_ERR(chan); init_completion(&scpi_buf->complete); if (mbox_send_message(chan, (void *)data) < 0) { status = SCPI_ERR_TIMEOUT; goto free_channel; } wait_for_completion(&scpi_buf->complete); status = *(u32 *)(data->rx_buf); /* read first word */ free_channel: mbox_free_channel(chan); return scpi_to_linux_errno(status); }
static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int len, void *rx_buf) { int ret; u8 token, chan; struct scpi_xfer *msg; struct scpi_chan *scpi_chan; chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans; scpi_chan = scpi_info->channels + chan; msg = get_scpi_xfer(scpi_chan); if (!msg) return -ENOMEM; token = atomic_inc_return(&scpi_chan->token) & CMD_TOKEN_ID_MASK; msg->slot = BIT(SCPI_SLOT); msg->cmd = PACK_SCPI_CMD(cmd, token, len); msg->tx_buf = tx_buf; msg->tx_len = len; msg->rx_buf = rx_buf; init_completion(&msg->done); ret = mbox_send_message(scpi_chan->chan, msg); if (ret < 0 || !rx_buf) goto out; if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT)) ret = -ETIMEDOUT; else /* first status word */ ret = le32_to_cpu(msg->status); out: if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */ scpi_process_cmd(scpi_chan, msg->cmd); put_scpi_xfer(msg, scpi_chan); /* SCPI error codes > 0, translate them to Linux scale*/ return ret > 0 ? scpi_to_linux_errno(ret) : ret; }