mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "tty: hvc_haven: Use thread worker to send characters"
This commit is contained in:
commit
fdc33ffd2f
8 changed files with 185 additions and 120 deletions
|
|
@ -31,14 +31,21 @@ static inline int _hh_hcall(const hh_hcall_fnid_t hcall_num,
|
|||
register uint64_t _x7 asm("x7") = args.arg7;
|
||||
|
||||
asm volatile (
|
||||
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
|
||||
"str x18, [%[_x18]]\n"
|
||||
#endif
|
||||
"hvc %[num]\n"
|
||||
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
|
||||
"ldr x18, [%[_x18]]\n"
|
||||
"str xzr, [%[_x18]]\n"
|
||||
#endif
|
||||
: "+r"(_x0), "+r"(_x1), "+r"(_x2), "+r"(_x3), "+r"(_x4),
|
||||
"+r"(_x5), "+r"(_x6), "+r"(_x7)
|
||||
: [num] "i" (hcall_num), [_x18] "r"(&_x18)
|
||||
: "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17",
|
||||
#if !IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
|
||||
"x18",
|
||||
#endif
|
||||
"memory"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -786,12 +786,19 @@ static int mem_buf_msgq_recv_fn(void *unused)
|
|||
int ret;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
ret = hh_msgq_recv(mem_buf_hh_msgq_hdl, &buf, &size, 0);
|
||||
if (ret < 0)
|
||||
buf = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!buf)
|
||||
continue;
|
||||
|
||||
ret = hh_msgq_recv(mem_buf_hh_msgq_hdl, buf,
|
||||
HH_MSGQ_MAX_MSG_SIZE_BYTES, &size, 0);
|
||||
if (ret < 0) {
|
||||
kfree(buf);
|
||||
pr_err_ratelimited("%s failed to receive message rc: %d\n",
|
||||
__func__, ret);
|
||||
else
|
||||
} else {
|
||||
mem_buf_process_msg(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -12,21 +12,27 @@
|
|||
#include <linux/notifier.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <linux/haven/hh_msgq.h>
|
||||
#include <linux/haven/hh_common.h>
|
||||
#include <linux/haven/hh_rm_drv.h>
|
||||
|
||||
#include "hvc_console.h"
|
||||
|
||||
#define HVC_HH_VTERM_COOKIE 0x474E5948
|
||||
/* # of payload bytes that can fit in a 1-fragment CONSOLE_WRITE message */
|
||||
#define HH_HVC_WRITE_MSG_SIZE ((1 * (HH_MSGQ_MAX_MSG_SIZE_BYTES - 8)) - 4)
|
||||
|
||||
struct hh_hvc_prv {
|
||||
struct hvc_struct *hvc;
|
||||
DECLARE_KFIFO(fifo, char, 1024);
|
||||
DECLARE_KFIFO(get_fifo, char, 1024);
|
||||
DECLARE_KFIFO(put_fifo, char, 1024);
|
||||
struct work_struct put_work;
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(fifo_lock);
|
||||
static struct hh_hvc_prv hh_hvc_data[2];
|
||||
static struct hh_hvc_prv hh_hvc_data[HH_VM_MAX];
|
||||
|
||||
static inline int hh_vm_name_to_vtermno(enum hh_vm_names vmname)
|
||||
{
|
||||
|
|
@ -50,11 +56,12 @@ static int hh_hvc_notify_console_chars(struct notifier_block *this,
|
|||
|
||||
ret = hh_rm_get_vm_name(msg->vmid, &vm_name);
|
||||
if (ret) {
|
||||
pr_warn_ratelimited("don't know VMID %d\n", vm_name);
|
||||
pr_warn_ratelimited("don't know VMID %d ret: %d\n", msg->vmid,
|
||||
ret);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
ret = kfifo_in_spinlocked(&hh_hvc_data[vm_name].fifo,
|
||||
ret = kfifo_in_spinlocked(&hh_hvc_data[vm_name].get_fifo,
|
||||
msg->bytes, msg->num_bytes,
|
||||
&fifo_lock);
|
||||
|
||||
|
|
@ -69,6 +76,36 @@ static int hh_hvc_notify_console_chars(struct notifier_block *this,
|
|||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void hh_hvc_put_work_fn(struct work_struct *ws)
|
||||
{
|
||||
hh_vmid_t vmid;
|
||||
char buf[HH_HVC_WRITE_MSG_SIZE];
|
||||
int count, ret;
|
||||
struct hh_hvc_prv *prv = container_of(ws, struct hh_hvc_prv, put_work);
|
||||
enum hh_vm_names vm_name = vtermno_to_hh_vm_name(prv->hvc->vtermno);
|
||||
|
||||
ret = hh_rm_get_vmid(vm_name, &vmid);
|
||||
if (ret) {
|
||||
pr_warn_once("hh_rm_get_vmid failed for %d: %d\n",
|
||||
vm_name, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!kfifo_is_empty(&prv->put_fifo)) {
|
||||
count = kfifo_out_spinlocked(&prv->put_fifo, buf, sizeof(buf),
|
||||
&fifo_lock);
|
||||
if (count <= 0)
|
||||
continue;
|
||||
|
||||
ret = hh_rm_console_write(vmid, buf, count);
|
||||
if (ret) {
|
||||
pr_warn_once("hh_rm_console_write failed for %d: %d\n",
|
||||
vm_name, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hh_hvc_get_chars(uint32_t vtermno, char *buf, int count)
|
||||
{
|
||||
int vm_name = vtermno_to_hh_vm_name(vtermno);
|
||||
|
|
@ -76,24 +113,22 @@ static int hh_hvc_get_chars(uint32_t vtermno, char *buf, int count)
|
|||
if (vm_name < 0 || vm_name >= HH_VM_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return kfifo_out_spinlocked(&hh_hvc_data[vm_name].fifo,
|
||||
return kfifo_out_spinlocked(&hh_hvc_data[vm_name].get_fifo,
|
||||
buf, count, &fifo_lock);
|
||||
}
|
||||
|
||||
static int hh_hvc_put_chars(uint32_t vtermno, const char *buf, int count)
|
||||
{
|
||||
int ret, vm_name = vtermno_to_hh_vm_name(vtermno);
|
||||
hh_vmid_t vmid;
|
||||
|
||||
if (vm_name < 0 || vm_name >= HH_VM_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hh_rm_get_vmid(vm_name, &vmid);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
return hh_rm_console_write(vmid, buf, count);
|
||||
ret = kfifo_in_spinlocked(&hh_hvc_data[vm_name].put_fifo,
|
||||
buf, count, &fifo_lock);
|
||||
if (ret > 0)
|
||||
schedule_work(&hh_hvc_data[vm_name].put_work);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hh_hvc_flush(uint32_t vtermno, bool wait)
|
||||
|
|
@ -108,6 +143,11 @@ static int hh_hvc_flush(uint32_t vtermno, bool wait)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cancel_work_sync(&hh_hvc_data[vm_name].put_work)) {
|
||||
/* flush the fifo */
|
||||
hh_hvc_put_work_fn(&hh_hvc_data[vm_name].put_work);
|
||||
}
|
||||
|
||||
return hh_rm_console_flush(vmid);
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +171,11 @@ static void hh_hvc_notify_del(struct hvc_struct *hp, int vm_name)
|
|||
if (vm_name < 0 || vm_name >= HH_VM_MAX)
|
||||
return;
|
||||
|
||||
if (cancel_work_sync(&hh_hvc_data[vm_name].put_work)) {
|
||||
/* flush the fifo */
|
||||
hh_hvc_put_work_fn(&hh_hvc_data[vm_name].put_work);
|
||||
}
|
||||
|
||||
ret = hh_rm_get_vmid(vm_name, &vmid);
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -140,7 +185,7 @@ static void hh_hvc_notify_del(struct hvc_struct *hp, int vm_name)
|
|||
if (ret)
|
||||
pr_err("Failed close VM%d console - %d\n", vm_name, ret);
|
||||
|
||||
kfifo_reset(&hh_hvc_data[vm_name].fifo);
|
||||
kfifo_reset(&hh_hvc_data[vm_name].get_fifo);
|
||||
}
|
||||
|
||||
static struct notifier_block hh_hvc_nb = {
|
||||
|
|
@ -175,7 +220,9 @@ static int __init hvc_hh_init(void)
|
|||
|
||||
for (i = 0; i < HH_VM_MAX; i++) {
|
||||
prv = &hh_hvc_data[i];
|
||||
INIT_KFIFO(prv->fifo);
|
||||
INIT_KFIFO(prv->get_fifo);
|
||||
INIT_KFIFO(prv->put_fifo);
|
||||
INIT_WORK(&prv->put_work, hh_hvc_put_work_fn);
|
||||
prv->hvc = hvc_alloc(hh_vm_name_to_vtermno(i), i, &hh_hv_ops,
|
||||
256);
|
||||
ret = PTR_ERR_OR_ZERO(prv->hvc);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ static irqreturn_t hh_msgq_tx_isr(int irq, void *dev)
|
|||
}
|
||||
|
||||
static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
|
||||
void *buff, size_t *size, u64 rx_flags)
|
||||
void *buff, size_t buff_size,
|
||||
size_t *recv_size, u64 rx_flags)
|
||||
{
|
||||
struct hh_hcall_msgq_recv_resp resp = {};
|
||||
unsigned long flags;
|
||||
|
|
@ -83,11 +84,11 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
|
|||
|
||||
spin_lock_irqsave(&cap_table_entry->rx_lock, flags);
|
||||
hh_ret = hh_hcall_msgq_recv(cap_table_entry->rx_cap_id, buff,
|
||||
HH_MSGQ_MAX_MSG_SIZE_BYTES, &resp);
|
||||
buff_size, &resp);
|
||||
|
||||
switch (hh_ret) {
|
||||
case HH_ERROR_OK:
|
||||
*size = resp.recv_size;
|
||||
*recv_size = resp.recv_size;
|
||||
ret = 0;
|
||||
break;
|
||||
case HH_ERROR_MSGQUEUE_EMPTY:
|
||||
|
|
@ -110,30 +111,36 @@ static int __hh_msgq_recv(struct hh_msgq_cap_table *cap_table_entry,
|
|||
/**
|
||||
* hh_msgq_recv: Receive a message from the client running on a different VM
|
||||
* @client_desc: The client descriptor that was obtained via hh_msgq_register()
|
||||
* @buff: Pointer to the buffer where the received data must be placed. Note
|
||||
* that the caller is responsible to free the data contained in buff
|
||||
* @size: The size of the buffer received
|
||||
* @buff: Pointer to the buffer where the received data must be placed
|
||||
* @buff_size: The size of the buffer space available
|
||||
* @recv_size: The actual amount of data that is copied into buff
|
||||
* @flags: Optional flags to pass to receive the data. For the list of flags,
|
||||
* see linux/haven/hh_msgq.h
|
||||
*
|
||||
* The function returns -EINVAL if the caller passes invalid arguments, -EAGAIN
|
||||
* The function returns 0 if the data is successfully received and recv_size
|
||||
* would contain the actual amount of data copied into buff.
|
||||
* It returns -EINVAL if the caller passes invalid arguments, -EAGAIN
|
||||
* if the message queue is not yet ready to communicate, and -EPERM if the
|
||||
* caller doesn't have permissions to receive the data. 0 is the data is
|
||||
* successfully received.
|
||||
* caller doesn't have permissions to receive the data. In all these failure
|
||||
* cases, recv_size is unmodified.
|
||||
*
|
||||
* Note: this function may sleep and should not be called from interrupt
|
||||
* context
|
||||
*/
|
||||
int hh_msgq_recv(void *msgq_client_desc,
|
||||
void **buff, size_t *size, unsigned long flags)
|
||||
void *buff, size_t buff_size,
|
||||
size_t *recv_size, unsigned long flags)
|
||||
{
|
||||
struct hh_msgq_desc *client_desc = msgq_client_desc;
|
||||
struct hh_msgq_cap_table *cap_table_entry;
|
||||
int ret;
|
||||
|
||||
if (!client_desc || !(*buff) || !size)
|
||||
if (!client_desc || !buff || !buff_size || !recv_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (buff_size > HH_MSGQ_MAX_MSG_SIZE_BYTES)
|
||||
return -E2BIG;
|
||||
|
||||
cap_table_entry = &hh_msgq_cap_table[client_desc->label];
|
||||
|
||||
spin_lock(&cap_table_entry->cap_entry_lock);
|
||||
|
|
@ -170,31 +177,18 @@ int hh_msgq_recv(void *msgq_client_desc,
|
|||
|
||||
spin_unlock(&cap_table_entry->cap_entry_lock);
|
||||
|
||||
*buff = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!(*buff))
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
if (cap_table_entry->rx_empty && (flags & HH_MSGQ_NONBLOCK)) {
|
||||
ret = -EAGAIN;
|
||||
goto buff_free;
|
||||
}
|
||||
if (cap_table_entry->rx_empty && (flags & HH_MSGQ_NONBLOCK))
|
||||
return -EAGAIN;
|
||||
|
||||
if (wait_event_interruptible(cap_table_entry->rx_wq,
|
||||
!cap_table_entry->rx_empty)) {
|
||||
ret = -ERESTARTSYS;
|
||||
goto buff_free;
|
||||
}
|
||||
!cap_table_entry->rx_empty))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
ret = __hh_msgq_recv(cap_table_entry, *buff, size, flags);
|
||||
ret = __hh_msgq_recv(cap_table_entry, buff, buff_size,
|
||||
recv_size, flags);
|
||||
} while (ret == -EAGAIN);
|
||||
|
||||
buff_free:
|
||||
if (ret < 0) {
|
||||
kfree(*buff);
|
||||
*buff = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ static void hh_rm_process_recv_work(struct work_struct *work)
|
|||
* to release the original packet that arrived.
|
||||
*/
|
||||
kfree(recv_buff);
|
||||
kfree(msgq_data);
|
||||
}
|
||||
|
||||
static int hh_rm_recv_task_fn(void *data)
|
||||
|
|
@ -427,12 +428,18 @@ static int hh_rm_recv_task_fn(void *data)
|
|||
int ret;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
recv_buff = kzalloc(HH_MSGQ_MAX_MSG_SIZE_BYTES, GFP_KERNEL);
|
||||
if (!recv_buff)
|
||||
continue;
|
||||
|
||||
/* Block until a new message is received */
|
||||
ret = hh_msgq_recv(hh_rm_msgq_desc, &recv_buff,
|
||||
ret = hh_msgq_recv(hh_rm_msgq_desc, recv_buff,
|
||||
HH_MSGQ_MAX_MSG_SIZE_BYTES,
|
||||
&recv_buff_size, 0);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to receive the message: %d\n",
|
||||
__func__, ret);
|
||||
kfree(recv_buff);
|
||||
continue;
|
||||
} else if (recv_buff_size <= sizeof(struct hh_rm_rpc_hdr)) {
|
||||
pr_err("%s: Invalid message size received\n", __func__);
|
||||
|
|
|
|||
|
|
@ -118,10 +118,6 @@ struct hh_vm_console_common_req_payload {
|
|||
u32 reserved0;
|
||||
} __packed;
|
||||
|
||||
struct hh_vm_console_common_resp_payload {
|
||||
u32 response;
|
||||
} __packed;
|
||||
|
||||
/* Call: CONSOLE_WRITE */
|
||||
struct hh_vm_console_write_req_payload {
|
||||
u32 vmid;
|
||||
|
|
@ -129,10 +125,6 @@ struct hh_vm_console_write_req_payload {
|
|||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct hh_vm_console_write_resp_payload {
|
||||
u32 response;
|
||||
} __packed;
|
||||
|
||||
/* Message ID headers */
|
||||
/* Call: VM_GET_HYP_RESOURCES */
|
||||
#define HH_RM_RES_TYPE_DB_TX 0
|
||||
|
|
|
|||
|
|
@ -426,33 +426,35 @@ EXPORT_SYMBOL(hh_rm_vm_start);
|
|||
*/
|
||||
int hh_rm_console_open(hh_vmid_t vmid)
|
||||
{
|
||||
struct hh_vm_console_common_resp_payload *resp_payload;
|
||||
void *resp;
|
||||
struct hh_vm_console_common_req_payload req_payload = {0};
|
||||
size_t resp_payload_size;
|
||||
int err = 0, reply_err_code = 0;
|
||||
int reply_err_code = 0;
|
||||
|
||||
req_payload.vmid = vmid;
|
||||
|
||||
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_OPEN,
|
||||
&req_payload, sizeof(req_payload),
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
|
||||
err = PTR_ERR(resp_payload);
|
||||
pr_err("%s: CONSOLE_OPEN failed with err: %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
resp = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_OPEN,
|
||||
&req_payload, sizeof(req_payload),
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (IS_ERR(resp)) {
|
||||
pr_err("%s: Unable to send CONSOLE_OPEN to RM: %d\n", __func__,
|
||||
PTR_ERR(resp));
|
||||
return PTR_ERR(resp);
|
||||
}
|
||||
|
||||
if (resp_payload_size != sizeof(*resp_payload)) {
|
||||
if (reply_err_code) {
|
||||
pr_err("%s: CONSOLE_OPEN returned error: %d\n", __func__,
|
||||
reply_err_code);
|
||||
return reply_err_code;
|
||||
}
|
||||
|
||||
if (resp_payload_size) {
|
||||
pr_err("%s: Invalid size received for CONSOLE_OPEN: %u\n",
|
||||
__func__, resp_payload_size);
|
||||
err = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = err ? : resp_payload->response;
|
||||
kfree(resp_payload);
|
||||
out:
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hh_rm_console_open);
|
||||
|
||||
|
|
@ -462,33 +464,35 @@ EXPORT_SYMBOL(hh_rm_console_open);
|
|||
*/
|
||||
int hh_rm_console_close(hh_vmid_t vmid)
|
||||
{
|
||||
struct hh_vm_console_common_resp_payload *resp_payload;
|
||||
void *resp;
|
||||
struct hh_vm_console_common_req_payload req_payload = {0};
|
||||
size_t resp_payload_size;
|
||||
int err = 0, reply_err_code = 0;
|
||||
int reply_err_code = 0;
|
||||
|
||||
req_payload.vmid = vmid;
|
||||
|
||||
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_CLOSE,
|
||||
&req_payload, sizeof(req_payload),
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
|
||||
err = PTR_ERR(resp_payload);
|
||||
pr_err("%s: CONSOLE_CLOSE failed with err: %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
resp = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_CLOSE,
|
||||
&req_payload, sizeof(req_payload),
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (IS_ERR(resp)) {
|
||||
pr_err("%s: Unable to send CONSOLE_CLOSE to RM: %d\n", __func__,
|
||||
PTR_ERR(resp));
|
||||
return PTR_ERR(resp);
|
||||
}
|
||||
|
||||
if (resp_payload_size != sizeof(*resp_payload)) {
|
||||
if (reply_err_code) {
|
||||
pr_err("%s: CONSOLE_CLOSE returned error: %d\n", __func__,
|
||||
reply_err_code);
|
||||
return reply_err_code;
|
||||
}
|
||||
|
||||
if (resp_payload_size) {
|
||||
pr_err("%s: Invalid size received for CONSOLE_CLOSE: %u\n",
|
||||
__func__, resp_payload_size);
|
||||
err = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = err ? : resp_payload->response;
|
||||
kfree(resp_payload);
|
||||
out:
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hh_rm_console_close);
|
||||
|
||||
|
|
@ -500,10 +504,10 @@ EXPORT_SYMBOL(hh_rm_console_close);
|
|||
*/
|
||||
int hh_rm_console_write(hh_vmid_t vmid, const char *buf, size_t size)
|
||||
{
|
||||
struct hh_vm_console_write_resp_payload *resp_payload;
|
||||
void *resp;
|
||||
struct hh_vm_console_write_req_payload *req_payload;
|
||||
size_t resp_payload_size;
|
||||
int err = 0, reply_err_code = 0;
|
||||
int reply_err_code = 0;
|
||||
size_t req_payload_size = sizeof(*req_payload) + size;
|
||||
|
||||
if (size < 1 || size > U32_MAX)
|
||||
|
|
@ -518,27 +522,30 @@ int hh_rm_console_write(hh_vmid_t vmid, const char *buf, size_t size)
|
|||
req_payload->num_bytes = size;
|
||||
memcpy(req_payload->data, buf, size);
|
||||
|
||||
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_WRITE,
|
||||
req_payload, req_payload_size,
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
|
||||
err = PTR_ERR(resp_payload);
|
||||
pr_err("%s: CONSOLE_WRITE failed with err: %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
resp = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_WRITE,
|
||||
req_payload, req_payload_size,
|
||||
&resp_payload_size, &reply_err_code);
|
||||
kfree(req_payload);
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
pr_err("%s: Unable to send CONSOLE_WRITE to RM: %d\n", __func__,
|
||||
PTR_ERR(resp));
|
||||
return PTR_ERR(resp);
|
||||
}
|
||||
|
||||
if (resp_payload_size != sizeof(*resp_payload)) {
|
||||
if (reply_err_code) {
|
||||
pr_err("%s: CONSOLE_WRITE returned error: %d\n", __func__,
|
||||
reply_err_code);
|
||||
return reply_err_code;
|
||||
}
|
||||
|
||||
if (resp_payload_size) {
|
||||
pr_err("%s: Invalid size received for CONSOLE_WRITE: %u\n",
|
||||
__func__, resp_payload_size);
|
||||
err = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = err ? : resp_payload->response;
|
||||
kfree(resp_payload);
|
||||
out:
|
||||
kfree(req_payload);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hh_rm_console_write);
|
||||
|
||||
|
|
@ -548,33 +555,36 @@ EXPORT_SYMBOL(hh_rm_console_write);
|
|||
*/
|
||||
int hh_rm_console_flush(hh_vmid_t vmid)
|
||||
{
|
||||
struct hh_vm_console_common_resp_payload *resp_payload;
|
||||
void *resp;
|
||||
struct hh_vm_console_common_req_payload req_payload = {0};
|
||||
size_t resp_payload_size;
|
||||
int err = 0, reply_err_code = 0;
|
||||
int reply_err_code = 0;
|
||||
|
||||
req_payload.vmid = vmid;
|
||||
|
||||
resp_payload = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_FLUSH,
|
||||
resp = hh_rm_call(HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_FLUSH,
|
||||
&req_payload, sizeof(req_payload),
|
||||
&resp_payload_size, &reply_err_code);
|
||||
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
|
||||
err = PTR_ERR(resp_payload);
|
||||
pr_err("%s: CONSOLE_FLUSH failed with err: %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
pr_err("%s: Unable to send CONSOLE_FLUSH to RM: %d\n", __func__,
|
||||
PTR_ERR(resp));
|
||||
return PTR_ERR(resp);
|
||||
}
|
||||
|
||||
if (resp_payload_size != sizeof(*resp_payload)) {
|
||||
if (reply_err_code) {
|
||||
pr_err("%s: CONSOLE_FLUSH returned error: %d\n", __func__,
|
||||
reply_err_code);
|
||||
return reply_err_code;
|
||||
}
|
||||
|
||||
if (resp_payload_size) {
|
||||
pr_err("%s: Invalid size received for CONSOLE_FLUSH: %u\n",
|
||||
__func__, resp_payload_size);
|
||||
err = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = err ? : resp_payload->response;
|
||||
kfree(resp_payload);
|
||||
out:
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hh_rm_console_flush);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ int hh_msgq_unregister(void *msgq_client_desc);
|
|||
int hh_msgq_send(void *msgq_client_desc,
|
||||
void *buff, size_t size, unsigned long flags);
|
||||
int hh_msgq_recv(void *msgq_client_desc,
|
||||
void **buff, size_t *size, unsigned long flags);
|
||||
void *buff, size_t buff_size,
|
||||
size_t *recv_size, unsigned long flags);
|
||||
|
||||
int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id,
|
||||
int direction, int irq);
|
||||
|
|
|
|||
Loading…
Reference in a new issue