ec_host_cmd: improve handling IN_PROGRESS commands
Add the ec_host_cmd_send_in_progress_continue function which allows continuing execution of a handler, while the ec_host_cmd thread is not blocked and new commands can be handled. That means some long command handlers can executed in the background while the Host Command subsys is not frozen. Signed-off-by: Dawid Niedzwiecki <dawidn@google.com>
This commit is contained in:
parent
a1b9f0a7d6
commit
d1ad180567
2 changed files with 57 additions and 32 deletions
|
|
@ -79,6 +79,7 @@ enum ec_host_cmd_log_level {
|
|||
};
|
||||
|
||||
typedef void (*ec_host_cmd_user_cb_t)(const struct ec_host_cmd_rx_ctx *rx_ctx, void *user_data);
|
||||
typedef enum ec_host_cmd_status (*ec_host_cmd_in_progress_cb_t)(void *user_data);
|
||||
|
||||
struct ec_host_cmd {
|
||||
struct ec_host_cmd_rx_ctx rx_ctx;
|
||||
|
|
@ -281,7 +282,7 @@ int ec_host_cmd_init(struct ec_host_cmd_backend *backend);
|
|||
* @retval 0 if successful.
|
||||
*/
|
||||
int ec_host_cmd_send_response(enum ec_host_cmd_status status,
|
||||
const struct ec_host_cmd_handler_args *args);
|
||||
const struct ec_host_cmd_handler_args *args);
|
||||
|
||||
/**
|
||||
* @brief Signal a new host command
|
||||
|
|
@ -346,6 +347,23 @@ bool ec_host_cmd_send_in_progress_ended(void);
|
|||
* @retval The final status or EC_HOST_CMD_UNAVAILABLE if not available.
|
||||
*/
|
||||
enum ec_host_cmd_status ec_host_cmd_send_in_progress_status(void);
|
||||
|
||||
/**
|
||||
* @brief Continue processing a handler in callback after returning EC_HOST_CMD_IN_PROGRESS.
|
||||
*
|
||||
* A Host Command handler may return the EC_HOST_CMD_IN_PROGRESS, but needs to continue work.
|
||||
* This function should be called before returning EC_HOST_CMD_IN_PROGRESS with a callback that
|
||||
* will be executed. The return status of the callback will be stored and can be get with the
|
||||
* ec_host_cmd_send_in_progress_status function. The ec_host_cmd_send_in_progress_ended function
|
||||
* can be used to check if the callback has ended.
|
||||
*
|
||||
* @param[in] cb A callback to be called after returning from a command handler.
|
||||
* @param[in] user_data User data to be passed to the callback.
|
||||
*
|
||||
* @retval EC_HOST_CMD_BUSY if any command is already in progress, EC_HOST_CMD_SUCCESS otherwise
|
||||
*/
|
||||
enum ec_host_cmd_status ec_host_cmd_send_in_progress_continue(ec_host_cmd_in_progress_cb_t cb,
|
||||
void *user_data);
|
||||
#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -64,7 +64,10 @@ static bool cmd_in_progress;
|
|||
|
||||
/* The final result of the last command that has sent EC_HOST_CMD_IN_PROGRESS */
|
||||
static enum ec_host_cmd_status saved_status = EC_HOST_CMD_UNAVAILABLE;
|
||||
#endif
|
||||
static struct k_work work_in_progress;
|
||||
ec_host_cmd_in_progress_cb_t cb_in_progress;
|
||||
static void *user_data_in_progress;
|
||||
#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
|
||||
|
||||
#ifdef CONFIG_EC_HOST_CMD_LOG_SUPPRESSED
|
||||
static uint16_t suppressed_cmds[CONFIG_EC_HOST_CMD_LOG_SUPPRESSED_NUMBER];
|
||||
|
|
@ -97,6 +100,36 @@ enum ec_host_cmd_status ec_host_cmd_send_in_progress_status(void)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum ec_host_cmd_status ec_host_cmd_send_in_progress_continue(ec_host_cmd_in_progress_cb_t cb,
|
||||
void *user_data)
|
||||
{
|
||||
if (cmd_in_progress) {
|
||||
return EC_HOST_CMD_BUSY;
|
||||
}
|
||||
|
||||
cmd_in_progress = true;
|
||||
cb_in_progress = cb;
|
||||
user_data_in_progress = user_data;
|
||||
saved_status = EC_HOST_CMD_UNAVAILABLE;
|
||||
LOG_INF("HC pending");
|
||||
k_work_submit(&work_in_progress);
|
||||
|
||||
return EC_HOST_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void handler_in_progress(struct k_work *work)
|
||||
{
|
||||
if (cb_in_progress != NULL) {
|
||||
saved_status = cb_in_progress(user_data_in_progress);
|
||||
LOG_INF("HC pending done, result=%d", saved_status);
|
||||
} else {
|
||||
saved_status = EC_HOST_CMD_UNAVAILABLE;
|
||||
LOG_ERR("HC incorrect IN_PROGRESS callback");
|
||||
}
|
||||
cb_in_progress = NULL;
|
||||
cmd_in_progress = false;
|
||||
}
|
||||
#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
|
||||
|
||||
#ifdef CONFIG_EC_HOST_CMD_LOG_SUPPRESSED
|
||||
|
|
@ -259,36 +292,6 @@ int ec_host_cmd_send_response(enum ec_host_cmd_status status,
|
|||
struct ec_host_cmd *hc = &ec_host_cmd;
|
||||
struct ec_host_cmd_tx_buf *tx = &hc->tx;
|
||||
|
||||
#ifdef CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS
|
||||
if (cmd_in_progress) {
|
||||
/* We previously got EC_HOST_CMD_IN_PROGRESS. This must be the completion
|
||||
* of that command, so save the result code.
|
||||
*/
|
||||
LOG_INF("HC pending done, size=%d, result=%d",
|
||||
args->output_buf_size, status);
|
||||
|
||||
/* Don't support saving response data, so mark the response as unavailable
|
||||
* in that case.
|
||||
*/
|
||||
if (args->output_buf_size != 0) {
|
||||
saved_status = EC_HOST_CMD_UNAVAILABLE;
|
||||
} else {
|
||||
saved_status = status;
|
||||
}
|
||||
|
||||
/* We can't send the response back to the host now since we already sent
|
||||
* the in-progress response and the host is on to other things now.
|
||||
*/
|
||||
cmd_in_progress = false;
|
||||
|
||||
return EC_HOST_CMD_SUCCESS;
|
||||
|
||||
} else if (status == EC_HOST_CMD_IN_PROGRESS) {
|
||||
cmd_in_progress = true;
|
||||
LOG_INF("HC pending");
|
||||
}
|
||||
#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
|
||||
|
||||
if (status != EC_HOST_CMD_SUCCESS) {
|
||||
const struct ec_host_cmd_request_header *const rx_header =
|
||||
(const struct ec_host_cmd_request_header *const)hc->rx_ctx.buf;
|
||||
|
|
@ -459,6 +462,10 @@ int ec_host_cmd_init(struct ec_host_cmd_backend *backend)
|
|||
/* Allow writing to rx buff at startup */
|
||||
k_sem_init(&hc->rx_ready, 0, 1);
|
||||
|
||||
#ifdef CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS
|
||||
k_work_init(&work_in_progress, handler_in_progress);
|
||||
#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */
|
||||
|
||||
handler_tx_buf = hc->tx.buf;
|
||||
handler_rx_buf = hc->rx_ctx.buf;
|
||||
handler_tx_buf_end = handler_tx_buf + CONFIG_EC_HOST_CMD_HANDLER_TX_BUFFER_SIZE;
|
||||
|
|
|
|||
Loading…
Reference in a new issue