blob: 09eaed49382d1f114b49d3de7331543f814031a5 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Implementation of DCI (Direct Command Interface) using mailbox.
*
* Copyright (C) 2022 Google LLC
*/
#ifndef __GXP_DCI_H__
#define __GXP_DCI_H__
#include <gcip/gcip-mailbox.h>
#include "gxp-mailbox.h"
#include "gxp-vd.h"
/* Basic Buffer descriptor struct for message payloads. */
struct gxp_dci_buffer_descriptor {
/* Address in the device's virtual address space. */
u64 address;
/* Size in bytes. */
u32 size;
/* Flags can be used to indicate message type, etc. */
u32 flags;
};
/* Format used for mailbox command queues. */
struct gxp_dci_command {
/* Sequence number. Should match the corresponding response. */
u64 seq;
/*
* Identifies the type of command.
* Should be a value from `gxp_mailbox_command_code`
*/
u16 code;
/*
* Priority level from 0 to 99, with 0 being the highest. Pending
* commands with higher priorities will be executed before lower
* priority ones.
*/
u8 priority;
/*
* Insert spaces to make padding explicit. This does not affect
* alignment.
*/
u8 reserved[5];
/* Struct describing the buffer containing the message payload */
struct gxp_dci_buffer_descriptor buffer_descriptor;
};
/* Format used for mailbox response queues from kernel. */
struct gxp_dci_response {
/* Sequence number. Should match the corresponding command. */
u64 seq;
/* The status code. Either SUCCESS or an error. */
u16 status;
/* Padding. */
u16 reserved;
/* Return value, dependent on the command this responds to. */
u32 retval;
};
/*
* Wrapper struct for responses consumed by a thread other than the one which
* sent the command.
*/
struct gxp_dci_async_response {
struct list_head list_entry;
struct gxp_dci_response resp;
/* Queue to add the response to once it is complete or timed out */
struct list_head *dest_queue;
/*
* The lock that protects queue pointed to by `dest_queue`.
* The mailbox code also uses this lock to protect changes to the
* `dest_queue` pointer itself when processing this response.
*/
spinlock_t *dest_queue_lock;
/* Queue of clients to notify when this response is processed */
wait_queue_head_t *dest_queue_waitq;
/* Specified power states vote during the command execution */
struct gxp_power_states requested_states;
/* gxp_eventfd to signal when the response completes. May be NULL */
struct gxp_eventfd *eventfd;
/* Handles arrival, timeout of async response. */
struct gcip_mailbox_resp_awaiter *awaiter;
};
enum gxp_dci_response_status {
GXP_DCI_RESP_OK = GCIP_MAILBOX_STATUS_OK,
GXP_DCI_RESP_WAITING = GCIP_MAILBOX_STATUS_WAITING_RESPONSE,
GXP_DCI_RESP_CANCELLED = GCIP_MAILBOX_STATUS_NO_RESPONSE,
};
/*
* Initializes the DCI to be able to work with user commands.
* Calling this function means that the device will communicate with the firmware side via DCI.
*/
void gxp_dci_init(struct gxp_mailbox_manager *mgr);
/*
* The following functions all require their caller have locked
* gxp->vd_semaphore for reading.
*/
/*
* Allocates a mailbox which is initialized for DCI.
* The mailbox must be released by calling `gxp_dci_release`.
*/
struct gxp_mailbox *gxp_dci_alloc(struct gxp_mailbox_manager *mgr,
struct gxp_virtual_device *vd, uint virt_core,
u8 core_id);
/* Releases a mailbox which is allocated by `gxp_dci_alloc`. */
void gxp_dci_release(struct gxp_mailbox_manager *mgr,
struct gxp_virtual_device *vd, uint virt_core,
struct gxp_mailbox *mailbox);
/* Executes command and get response through @resp. */
int gxp_dci_execute_cmd(struct gxp_mailbox *mailbox,
struct gxp_dci_command *cmd,
struct gxp_dci_response *resp);
/*
* Executes command asynchronously.
* The response can be obtained by waiting the `mailbox_resp_queues` of corresponding
* virtual device of the mailbox which is a queue of `gxp_dci_async_response`.
*/
int gxp_dci_execute_cmd_async(struct gxp_mailbox *mailbox,
struct gxp_dci_command *cmd,
struct list_head *resp_queue,
spinlock_t *queue_lock,
wait_queue_head_t *queue_waitq,
struct gxp_power_states requested_states,
struct gxp_eventfd *eventfd);
#endif /* __GXP_DCI_H__ */