Loading arch/arm64/include/asm/haven/hcall.h +7 −0 Original line number Diff line number Diff line Loading @@ -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" ); Loading drivers/soc/qcom/mem-buf.c +10 −3 Original line number Diff line number Diff line Loading @@ -786,13 +786,20 @@ 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; } Loading drivers/tty/hvc/hvc_haven.c +61 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading @@ -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); Loading @@ -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) 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; return hh_rm_console_write(vmid, buf, count); } static int hh_hvc_flush(uint32_t vtermno, bool wait) Loading @@ -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); } Loading @@ -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; Loading @@ -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 = { Loading Loading @@ -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); Loading drivers/virt/haven/hh_msgq.c +24 −30 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading @@ -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); Loading Loading @@ -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: Loading drivers/virt/haven/hh_rm_core.c +8 −1 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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__); Loading Loading
arch/arm64/include/asm/haven/hcall.h +7 −0 Original line number Diff line number Diff line Loading @@ -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" ); Loading
drivers/soc/qcom/mem-buf.c +10 −3 Original line number Diff line number Diff line Loading @@ -786,13 +786,20 @@ 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; } Loading
drivers/tty/hvc/hvc_haven.c +61 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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); Loading @@ -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); Loading @@ -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) 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; return hh_rm_console_write(vmid, buf, count); } static int hh_hvc_flush(uint32_t vtermno, bool wait) Loading @@ -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); } Loading @@ -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; Loading @@ -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 = { Loading Loading @@ -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); Loading
drivers/virt/haven/hh_msgq.c +24 −30 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading @@ -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); Loading Loading @@ -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: Loading
drivers/virt/haven/hh_rm_core.c +8 −1 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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__); Loading