blob: 66e49d343075a25ffd25b0943f8614914f722041 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* GXP user command interface.
*
* Copyright (C) 2022 Google LLC
*/
#ifndef __GXP_UCI_H__
#define __GXP_UCI_H__
#include <linux/kthread.h>
#include <gcip/gcip-mailbox.h>
#include "gxp-client.h"
#include "gxp-internal.h"
#include "gxp-mailbox.h"
#include "gxp-vd.h"
#define UCI_RESOURCE_ID 0
struct gxp_mcu;
/* Command/Response Structures */
/* Size of `gxp_uci_type` should be u8 to match FW */
enum gxp_uci_type {
CORE_COMMAND = 0,
WAKELOCK_COMMAND = 1,
} __packed;
struct gxp_uci_wakelock_command_params {
/* DVFS operating point of DSP cores */
uint8_t dsp_operating_point;
/* DVFS operating point of memory */
uint8_t memory_operating_point;
};
struct gxp_uci_core_command_params {
/* iova address of the app command */
uint64_t address;
/* size of the app command */
uint32_t size;
/* number of dsp cores required for this command */
uint8_t num_cores;
/* DVFS operating point of DSP cores */
uint8_t dsp_operating_point;
/* DVFS operating point of memory */
uint8_t memory_operating_point;
};
struct gxp_uci_command {
/* sequence number, should match the corresponding response */
uint64_t seq;
/* unique ID for each client that identifies client VM & security realm */
uint32_t client_id;
/* type of the command */
enum gxp_uci_type type;
/* hint for which core the job should be assigned to */
uint8_t core_id;
/* reserved field */
uint8_t reserved[2];
/* All possible command parameters */
union {
struct gxp_uci_core_command_params core_command_params;
struct gxp_uci_wakelock_command_params wakelock_command_params;
uint8_t opaque[48];
};
};
struct gxp_uci_response {
/* sequence number, should match the corresponding command */
uint64_t seq;
/* unique ID for each client that identifies client VM & security realm*/
uint32_t client_id;
/* status code that tells the success or error. */
uint16_t code;
/* reserved field */
uint8_t reserved[2];
uint8_t opaque[16];
};
/*
* Wrapper struct for responses consumed by a thread other than the one which
* sent the command.
*/
struct gxp_uci_async_response {
/*
* List entry which will be inserted to the waiting queue of the vd.
* It will be pushed into the waiting queue when the response is sent.
* (i.e, the `gxp_uci_send_command` function is called)
* It will be poped when the response is consumed by the vd.
*/
struct list_head wait_list_entry;
/*
* List entry which will be inserted to the dest_queue of the vd.
* It will be pushed into the dest_queue when the response is arrived or timed out.
* It will be poped when the response is consumed by the vd.
*/
struct list_head dest_list_entry;
/* Stores the response. */
struct gxp_uci_response resp;
struct gxp_uci *uci;
/* Queue where to be removed from once it is complete or timed out. */
struct list_head *wait_queue;
/* Queue to add the response to once it is complete or timed out. */
struct list_head *dest_queue;
/*
* The lock that protects queues pointed to by `dest_queue` and `wait_queue`.
* The mailbox code also uses this lock to protect changes to the `wait_queue` pointer
* itself when processing this response.
*/
spinlock_t *queue_lock;
/* Queue of clients to notify when this response is processed. */
wait_queue_head_t *dest_queue_waitq;
/* gxp_eventfd to signal when the response completes. May be NULL. */
struct gxp_eventfd *eventfd;
/* The request was sent from this virtual device. */
struct gxp_virtual_device *vd;
/* Handles arrival, timeout of async response. */
struct gcip_mailbox_resp_awaiter *awaiter;
/* Status of the response. */
enum gxp_response_status status;
};
struct gxp_uci_wait_list {
struct list_head list;
struct gxp_uci_response *resp;
bool is_async;
};
struct gxp_uci {
struct gxp_dev *gxp;
struct gxp_mcu *mcu;
struct gxp_mailbox *mbx;
struct gxp_mapped_resource cmd_queue_mem;
struct gxp_mapped_resource resp_queue_mem;
struct gxp_mapped_resource descriptor_mem;
};
/* UCI APIs */
/**
* gxp_uci_init() - API for initializing GXP UCI in MCU, should only be
* called while initializing MCU
* @mcu: The MCU that UCI communicate with
*
* Return:
* * 0 - Initialization finished successfully
* * -ENOMEM - Cannot get memory to finish init.
*/
int gxp_uci_init(struct gxp_mcu *mcu);
/**
* gxp_uci_exit() - API for releasing the UCI mailbox of MCU.
* @uci: The UCI to be released
*/
void gxp_uci_exit(struct gxp_uci *uci);
/*
* gxp_uci_send_command() - API for sending @cmd to MCU firmware, and
* registering @resp_queue to put the response in after MCU firmware handle the
* command.
*
* Returns 0 on success, a negative errno on failure.
*/
int gxp_uci_send_command(struct gxp_uci *uci, struct gxp_virtual_device *vd,
struct gxp_uci_command *cmd,
struct list_head *wait_queue,
struct list_head *resp_queue, spinlock_t *queue_lock,
wait_queue_head_t *queue_waitq,
struct gxp_eventfd *eventfd);
/*
* gxp_uci_wait_async_response() - API for waiting and fetching a response from
* MCU firmware.
*
* Returns 0 on success, a negative errno on failure.
*/
int gxp_uci_wait_async_response(struct mailbox_resp_queue *uci_resp_queue,
u64 *resp_seq, u16 *error_code, u8 *opaque);
#endif /* __GXP_UCI_H__ */