mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
Merge "haven: dbl: Make hh_dbl_ functions wait for capid availability"
This commit is contained in:
commit
a5d7a7b302
9 changed files with 207 additions and 118 deletions
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/haven/hh_common.h>
|
||||
#include <linux/haven/hh_rm_drv.h>
|
||||
|
||||
#include <soc/qcom/subsystem_notif.h>
|
||||
|
|
@ -31,12 +30,13 @@ static struct kobj_type guestvm_kobj_type = {
|
|||
};
|
||||
|
||||
struct guestvm_loader_private {
|
||||
struct work_struct vm_loader_work;
|
||||
struct notifier_block guestvm_nb;
|
||||
struct kobject vm_loader_kobj;
|
||||
struct device *dev;
|
||||
char vm_name[MAX_LEN];
|
||||
void *vm_loaded;
|
||||
int vmid;
|
||||
u8 vm_status;
|
||||
};
|
||||
|
||||
static inline enum hh_vm_names get_hh_vm_name(const char *str)
|
||||
|
|
@ -50,24 +50,50 @@ static inline enum hh_vm_names get_hh_vm_name(const char *str)
|
|||
return HH_VM_MAX;
|
||||
}
|
||||
|
||||
static void guestvm_loader_rm_notifier(struct work_struct *vm_loader_work)
|
||||
static int guestvm_loader_nb_handler(struct notifier_block *this,
|
||||
unsigned long cmd, void *data)
|
||||
{
|
||||
struct guestvm_loader_private *priv;
|
||||
int ret = 0;
|
||||
struct hh_rm_notif_vm_status_payload *vm_status_payload = data;
|
||||
u8 vm_status = vm_status_payload->vm_status;
|
||||
int ret;
|
||||
|
||||
priv = container_of(vm_loader_work, struct guestvm_loader_private,
|
||||
vm_loader_work);
|
||||
priv->vmid = hh_rm_vm_alloc_vmid(get_hh_vm_name(priv->vm_name));
|
||||
if (priv->vmid == HH_VM_MAX) {
|
||||
dev_err(priv->dev, "Couldn't get vmid.\n");
|
||||
return;
|
||||
priv = container_of(this, struct guestvm_loader_private, guestvm_nb);
|
||||
|
||||
if (cmd != HH_RM_NOTIF_VM_STATUS)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (priv->vmid != vm_status_payload->vmid)
|
||||
dev_warn(priv->dev, "Expected a notification from vmid = %d, but received one from vmid = %d\n",
|
||||
priv->vmid, vm_status_payload->vmid);
|
||||
|
||||
/*
|
||||
* Listen to STATUS_READY or STATUS_RUNNING notifications from RM.
|
||||
* These notifications come from RM after PIL loading the VM images.
|
||||
* Query GET_HYP_RESOURCES to populate other entities such as MessageQ
|
||||
* and DBL.
|
||||
*/
|
||||
switch (vm_status) {
|
||||
case HH_RM_VM_STATUS_READY:
|
||||
priv->vm_status = HH_RM_VM_STATUS_READY;
|
||||
ret = hh_rm_populate_hyp_res(vm_status_payload->vmid);
|
||||
if (ret < 0) {
|
||||
dev_err(priv->dev, "Failed to get hyp resources for vmid = %d ret = %d\n",
|
||||
vm_status_payload->vmid, ret);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
break;
|
||||
case HH_RM_VM_STATUS_RUNNING:
|
||||
break;
|
||||
default:
|
||||
dev_err(priv->dev, "Unknown notification receieved for vmid = %d vm_status = %d\n",
|
||||
vm_status_payload->vmid, vm_status);
|
||||
}
|
||||
ret = hh_rm_vm_start(priv->vmid);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "VM start has failed with %d.\n", ret);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static ssize_t guestvm_load_start(struct kobject *kobj,
|
||||
static ssize_t guestvm_loader_start(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
|
|
@ -88,6 +114,13 @@ static ssize_t guestvm_load_start(struct kobject *kobj,
|
|||
}
|
||||
|
||||
if (boot) {
|
||||
priv->vm_status = HH_RM_VM_STATUS_INIT;
|
||||
priv->vmid = hh_rm_vm_alloc_vmid(get_hh_vm_name(priv->vm_name));
|
||||
if (priv->vmid < 0) {
|
||||
dev_err(priv->dev, "Couldn't allocate VMID.\n");
|
||||
return count;
|
||||
}
|
||||
|
||||
priv->vm_loaded = subsystem_get(priv->vm_name);
|
||||
if (IS_ERR(priv->vm_loaded)) {
|
||||
ret = (int)(PTR_ERR(priv->vm_loaded));
|
||||
|
|
@ -96,13 +129,18 @@ static ssize_t guestvm_load_start(struct kobject *kobj,
|
|||
priv->vm_loaded = NULL;
|
||||
return ret;
|
||||
}
|
||||
schedule_work(&priv->vm_loader_work);
|
||||
|
||||
priv->vm_status = HH_RM_VM_STATUS_RUNNING;
|
||||
ret = hh_rm_vm_start(priv->vmid);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "VM start has failed for vmid = %d ret = %d\n",
|
||||
priv->vmid, ret);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct kobj_attribute guestvm_loader_attribute =
|
||||
__ATTR(boot_guestvm, 0220, NULL, guestvm_load_start);
|
||||
__ATTR(boot_guestvm, 0220, NULL, guestvm_loader_start);
|
||||
|
||||
static struct attribute *attrs[] = {
|
||||
&guestvm_loader_attribute.attr,
|
||||
|
|
@ -132,8 +170,6 @@ static int guestvm_loader_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
strlcpy(priv->vm_name, sub_sys, sizeof(priv->vm_name));
|
||||
|
||||
INIT_WORK(&priv->vm_loader_work, guestvm_loader_rm_notifier);
|
||||
|
||||
ret = kobject_init_and_add(&priv->vm_loader_kobj, &guestvm_kobj_type,
|
||||
kernel_kobj, "load_guestvm");
|
||||
if (ret) {
|
||||
|
|
@ -148,6 +184,12 @@ static int guestvm_loader_probe(struct platform_device *pdev)
|
|||
goto error_return;
|
||||
}
|
||||
|
||||
priv->guestvm_nb.notifier_call = guestvm_loader_nb_handler;
|
||||
ret = hh_rm_register_notifier(&priv->guestvm_nb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->vm_status = HH_RM_VM_STATUS_NO_STATE;
|
||||
return 0;
|
||||
|
||||
error_return:
|
||||
|
|
|
|||
|
|
@ -34,19 +34,21 @@ struct hh_dbl_cap_table {
|
|||
const char *rx_irq_name;
|
||||
dbl_rx_cb_t rx_callback;
|
||||
void *rx_priv_data;
|
||||
wait_queue_head_t cap_wq;
|
||||
};
|
||||
|
||||
static bool hh_dbl_initialized;
|
||||
static struct hh_dbl_cap_table hh_dbl_cap_table[HH_DBL_LABEL_MAX];
|
||||
|
||||
/**
|
||||
* hh_dbl_validate_params - Validate doorbell common parameters
|
||||
*/
|
||||
static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
|
||||
enum hh_dbl_dir dir)
|
||||
enum hh_dbl_dir dir, const unsigned long flags)
|
||||
{
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
|
||||
if (!client_desc)
|
||||
if (IS_ERR_OR_NULL(client_desc))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if the client has manipulated the label */
|
||||
|
|
@ -67,23 +69,35 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
|
|||
* There are no doorbell setup for Tx or Rx
|
||||
*/
|
||||
if (dir == HH_DBL_DIRECTION_RX) {
|
||||
if (!cap_table_entry->rx_cap_id ||
|
||||
!cap_table_entry->rx_reg_done) {
|
||||
pr_err("%s: label: %d; rx_cap_id: %llu; dir: %d rx_done: %d\n",
|
||||
__func__, client_desc->label,
|
||||
cap_table_entry->rx_cap_id,
|
||||
dir, cap_table_entry->rx_reg_done);
|
||||
if (!cap_table_entry->rx_reg_done)
|
||||
return -EINVAL;
|
||||
|
||||
if (cap_table_entry->rx_cap_id != HH_CAPID_INVAL)
|
||||
return 0;
|
||||
|
||||
if (flags & HH_DBL_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (wait_event_interruptible(cap_table_entry->cap_wq,
|
||||
cap_table_entry->rx_cap_id != HH_CAPID_INVAL))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
if (!cap_table_entry->tx_cap_id ||
|
||||
!cap_table_entry->tx_reg_done) {
|
||||
pr_err("%s: label: %d; tx_cap_id: %llu; dir: %d tx_done: %d\n",
|
||||
__func__, client_desc->label,
|
||||
cap_table_entry->tx_cap_id,
|
||||
dir, cap_table_entry->tx_reg_done);
|
||||
if (!cap_table_entry->tx_reg_done)
|
||||
return -EINVAL;
|
||||
|
||||
if (cap_table_entry->tx_cap_id != HH_CAPID_INVAL)
|
||||
return 0;
|
||||
|
||||
if (flags & HH_DBL_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (wait_event_interruptible(cap_table_entry->cap_wq,
|
||||
cap_table_entry->tx_cap_id != HH_CAPID_INVAL))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -93,6 +107,8 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
|
|||
* hh_dbl_read_and_clean - Automatically read and clear the flags in doorbell
|
||||
* @client_desc: client handle to indetify the doorbell object
|
||||
* @clear_flags: clear the bits mentioned in the clear_flags
|
||||
* @flags: Optional flags to pass to send the data. For the list of flags,
|
||||
* see linux/haven/hh_dbl.h
|
||||
*
|
||||
* Reads and clears the flags of the Doorbell object. If there is a pending
|
||||
* bound virtual interrupt, it will be de-asserted
|
||||
|
|
@ -101,7 +117,8 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc,
|
|||
* 0 on success, @clear_flags contains the doorbell’s previous unmasked flags
|
||||
* before the @clear_flags were removed.
|
||||
*/
|
||||
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags)
|
||||
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags,
|
||||
const unsigned long flags)
|
||||
{
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
struct hh_hcall_dbl_recv_resp recv_resp;
|
||||
|
|
@ -111,7 +128,7 @@ int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags)
|
|||
if (!clear_flags)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -137,6 +154,8 @@ EXPORT_SYMBOL(hh_dbl_read_and_clean);
|
|||
* the doorbell's bound virtual interrupt
|
||||
* @ack_mask: Controls which flags should be automatically cleared
|
||||
* when the interrupt is asserted
|
||||
* @flags: Optional flags to pass to send the data. For the list of flags,
|
||||
* see linux/haven/hh_dbl.h
|
||||
*
|
||||
* Sets the Doorbell object’s masks. A doorbell object has two masks
|
||||
* which are configured by the receiver to control which flags it is
|
||||
|
|
@ -146,13 +165,13 @@ EXPORT_SYMBOL(hh_dbl_read_and_clean);
|
|||
* 0 on success
|
||||
*/
|
||||
int hh_dbl_set_mask(void *dbl_client_desc, hh_dbl_flags_t enable_mask,
|
||||
hh_dbl_flags_t ack_mask)
|
||||
hh_dbl_flags_t ack_mask, const unsigned long flags)
|
||||
{
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
struct hh_dbl_desc *client_desc = dbl_client_desc;
|
||||
int ret, hh_ret;
|
||||
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -176,6 +195,8 @@ EXPORT_SYMBOL(hh_dbl_set_mask);
|
|||
* @client_desc: client handle to indetify the doorbell object
|
||||
* @newflags: flags to set in the doorbell. This flag along with enable_mask
|
||||
* in the doorbell decide whehter to raise vIRQ are not.
|
||||
* @flags: Optional flags to pass to send the data. For the list of flags,
|
||||
* see linux/haven/hh_dbl.h
|
||||
*
|
||||
* Set flags in the doorbell. If following the send, the set of enabled flags
|
||||
* as defined by the bitwise-AND of the doorbell flags with the EnableMask,
|
||||
|
|
@ -185,7 +206,8 @@ EXPORT_SYMBOL(hh_dbl_set_mask);
|
|||
* 0 on success, @newflags contains the doorbell’s previous unmasked flags
|
||||
* before the @newflags were added.
|
||||
*/
|
||||
int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags)
|
||||
int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
struct hh_hcall_dbl_send_resp send_resp;
|
||||
|
|
@ -195,7 +217,7 @@ int hh_dbl_send(void *dbl_client_desc, hh_dbl_flags_t *newflags)
|
|||
if (!newflags)
|
||||
return -EINVAL;
|
||||
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_TX);
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_TX, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -218,6 +240,8 @@ EXPORT_SYMBOL(hh_dbl_send);
|
|||
* hh_dbl_reset - clear all the flags of the doorbell and sets all bits in
|
||||
* the Doorbell’s mask.
|
||||
* @client_desc: client handle to indetify the doorbell object
|
||||
* @flags: Optional flags to pass to send the data. For the list of flags,
|
||||
* see linux/haven/hh_dbl.h
|
||||
*
|
||||
* Clears all the flags of the doorbell and sets all bits in the doorbell’s
|
||||
* mask. If there is a pending bound virtual interrupt, it will be de-asserted.
|
||||
|
|
@ -225,13 +249,13 @@ EXPORT_SYMBOL(hh_dbl_send);
|
|||
* Returns:
|
||||
* 0 on success
|
||||
*/
|
||||
int hh_dbl_reset(void *dbl_client_desc)
|
||||
int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags)
|
||||
{
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
struct hh_dbl_desc *client_desc = dbl_client_desc;
|
||||
int ret, hh_ret;
|
||||
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX);
|
||||
ret = hh_dbl_validate_params(client_desc, HH_DBL_DIRECTION_RX, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -278,6 +302,9 @@ void *hh_dbl_tx_register(enum hh_dbl_label label)
|
|||
if (label < 0 || label >= HH_DBL_LABEL_MAX)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!hh_dbl_initialized)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
cap_table_entry = &hh_dbl_cap_table[label];
|
||||
|
||||
if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock))
|
||||
|
|
@ -338,6 +365,9 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv)
|
|||
if (label < 0 || label >= HH_DBL_LABEL_MAX)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!hh_dbl_initialized)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
cap_table_entry = &hh_dbl_cap_table[label];
|
||||
|
||||
if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock))
|
||||
|
|
@ -365,20 +395,6 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv)
|
|||
cap_table_entry->rx_callback = rx_cb;
|
||||
cap_table_entry->rx_priv_data = priv;
|
||||
|
||||
ret = request_threaded_irq(cap_table_entry->rx_irq,
|
||||
NULL,
|
||||
hh_dbl_rx_callback_thread,
|
||||
IRQF_ONESHOT,
|
||||
cap_table_entry->rx_irq_name,
|
||||
cap_table_entry);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("%s: IRQ registration failed\n", __func__);
|
||||
cap_table_entry->rx_callback = NULL;
|
||||
cap_table_entry->rx_priv_data = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
cap_table_entry->rx_reg_done = 1;
|
||||
|
||||
pr_debug("%s: Registered Rx client for label: %d\n", __func__, label);
|
||||
|
|
@ -407,7 +423,7 @@ int hh_dbl_tx_unregister(void *dbl_client_desc)
|
|||
struct hh_dbl_desc *client_desc = dbl_client_desc;
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
|
||||
if (!client_desc)
|
||||
if (IS_ERR_OR_NULL(client_desc))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if the client has manipulated the label */
|
||||
|
|
@ -458,7 +474,7 @@ int hh_dbl_rx_unregister(void *dbl_client_desc)
|
|||
struct hh_dbl_desc *client_desc = dbl_client_desc;
|
||||
struct hh_dbl_cap_table *cap_table_entry;
|
||||
|
||||
if (!client_desc)
|
||||
if (IS_ERR_OR_NULL(client_desc))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if the client has manipulated the label */
|
||||
|
|
@ -525,6 +541,9 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
|
|||
goto err;
|
||||
}
|
||||
cap_table_entry->tx_cap_id = cap_id;
|
||||
|
||||
wake_up_interruptible(&cap_table_entry->cap_wq);
|
||||
|
||||
pr_debug("%s: label: %d; tx_cap_id: %llu; dir: %d; rx_irq: %d\n",
|
||||
__func__, label, cap_id, direction, rx_irq);
|
||||
break;
|
||||
|
|
@ -537,6 +556,21 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
|
|||
}
|
||||
cap_table_entry->rx_cap_id = cap_id;
|
||||
cap_table_entry->rx_irq = rx_irq;
|
||||
|
||||
ret = request_threaded_irq(cap_table_entry->rx_irq,
|
||||
NULL,
|
||||
hh_dbl_rx_callback_thread,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_RISING,
|
||||
cap_table_entry->rx_irq_name,
|
||||
cap_table_entry);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("%s: IRQ registration failed\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
wake_up_interruptible(&cap_table_entry->cap_wq);
|
||||
|
||||
pr_debug("%s: label: %d; rx_cap_id: %llu; dir: %d; rx_irq: %d\n",
|
||||
__func__, label, cap_id, direction, rx_irq);
|
||||
break;
|
||||
|
|
@ -575,6 +609,9 @@ static int __init hh_dbl_init(void)
|
|||
for (i = 0; i < HH_DBL_LABEL_MAX; i++) {
|
||||
entry = &hh_dbl_cap_table[i];
|
||||
mutex_init(&entry->cap_entry_lock);
|
||||
init_waitqueue_head(&entry->cap_wq);
|
||||
entry->tx_cap_id = HH_CAPID_INVAL;
|
||||
entry->rx_cap_id = HH_CAPID_INVAL;
|
||||
entry->rx_irq_name = kasprintf(GFP_KERNEL, "hh_dbl_rx_%d", i);
|
||||
if (!entry->rx_irq_name) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -582,6 +619,8 @@ static int __init hh_dbl_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
hh_dbl_initialized = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/haven/hh_msgq.h>
|
||||
#include <linux/haven/hh_errno.h>
|
||||
#include <linux/haven/hh_common.h>
|
||||
#include <linux/haven/hh_rm_drv.h>
|
||||
|
||||
#include "hh_rm_drv_private.h"
|
||||
|
||||
|
|
@ -66,8 +67,6 @@ SRCU_NOTIFIER_HEAD_STATIC(hh_rm_notifier);
|
|||
static void hh_rm_get_svm_res_work_fn(struct work_struct *work);
|
||||
static DECLARE_WORK(hh_rm_get_svm_res_work, hh_rm_get_svm_res_work_fn);
|
||||
|
||||
static int hh_rm_populate_hyp_res(hh_vmid_t vmid);
|
||||
|
||||
static struct hh_rm_connection *hh_rm_alloc_connection(u32 msg_id)
|
||||
{
|
||||
struct hh_rm_connection *connection;
|
||||
|
|
@ -124,21 +123,6 @@ int hh_rm_unregister_notifier(struct notifier_block *nb)
|
|||
}
|
||||
EXPORT_SYMBOL(hh_rm_unregister_notifier);
|
||||
|
||||
static int hh_rm_process_notif_vm_status(void *recv_buff, size_t recv_buff_size)
|
||||
{
|
||||
struct hh_rm_notif_vm_status_payload *vm_status_payload;
|
||||
|
||||
vm_status_payload = recv_buff + sizeof(struct hh_rm_rpc_hdr);
|
||||
|
||||
/* The VM is now booting. Collect it's info and
|
||||
* populate to other entities such as MessageQ and DBL
|
||||
*/
|
||||
if (vm_status_payload->vm_status == HH_RM_OS_STATUS_BOOT)
|
||||
return hh_rm_populate_hyp_res(vm_status_payload->vmid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hh_rm_connection *
|
||||
hh_rm_wait_for_notif_fragments(void *recv_buff, size_t recv_buff_size)
|
||||
{
|
||||
|
|
@ -214,8 +198,6 @@ static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size)
|
|||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hh_rm_process_notif_vm_status(recv_buff, recv_buff_size);
|
||||
break;
|
||||
case HH_RM_NOTIF_VM_IRQ_LENT:
|
||||
if (recv_buff_size != sizeof(*hdr) +
|
||||
|
|
@ -699,7 +681,14 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int hh_rm_populate_hyp_res(hh_vmid_t vmid)
|
||||
/**
|
||||
* hh_rm_populate_hyp_res: Query Resource Manager VM to get hyp resources.
|
||||
* @vmid: The vmid of resources to be queried.
|
||||
*
|
||||
* The function encodes the error codes via ERR_PTR. Hence, the caller is
|
||||
* responsible to check it with IS_ERR_OR_NULL().
|
||||
*/
|
||||
int hh_rm_populate_hyp_res(hh_vmid_t vmid)
|
||||
{
|
||||
struct hh_vm_get_hyp_res_resp_entry *res_entries = NULL;
|
||||
int linux_irq, ret = 0;
|
||||
|
|
@ -769,6 +758,7 @@ out:
|
|||
kfree(res_entries);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(hh_rm_populate_hyp_res);
|
||||
|
||||
static void hh_rm_get_svm_res_work_fn(struct work_struct *work)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -506,13 +506,13 @@ int hh_rm_vm_start(int vmid)
|
|||
&resp_payload_size, &reply_err_code);
|
||||
if (reply_err_code || IS_ERR_OR_NULL(resp_payload)) {
|
||||
err = PTR_ERR(resp_payload);
|
||||
pr_err("%s: VM_ALLOCATE failed with err: %d\n",
|
||||
pr_err("%s: VM_START failed with err: %d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (resp_payload_size != sizeof(*resp_payload)) {
|
||||
pr_err("%s: Invalid size received for VM_IRQ_ACCEPT: %u\n",
|
||||
pr_err("%s: Invalid size received for VM_START: %u\n",
|
||||
__func__, resp_payload_size);
|
||||
kfree(resp_payload);
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ enum hh_dbl_label {
|
|||
HH_DBL_LABEL_MAX
|
||||
};
|
||||
|
||||
/* Possible flags to pass for send, set_mask, read, reset */
|
||||
#define HH_DBL_NONBLOCK BIT(32)
|
||||
|
||||
#if IS_ENABLED(CONFIG_HH_DBL)
|
||||
void *hh_dbl_tx_register(enum hh_dbl_label label);
|
||||
void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb,
|
||||
|
|
@ -27,11 +30,13 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb,
|
|||
int hh_dbl_tx_unregister(void *dbl_client_desc);
|
||||
int hh_dbl_rx_unregister(void *dbl_client_desc);
|
||||
|
||||
int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags);
|
||||
int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags,
|
||||
const unsigned long flags);
|
||||
int hh_dbl_set_mask(void *dbl_client_desc, hh_dbl_flags_t enable_mask,
|
||||
hh_dbl_flags_t ack_mask);
|
||||
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags);
|
||||
int hh_dbl_reset(void *dbl_client_desc);
|
||||
hh_dbl_flags_t ack_mask, const unsigned long flags);
|
||||
int hh_dbl_read_and_clean(void *dbl_client_desc, hh_dbl_flags_t *clear_flags,
|
||||
const unsigned long flags);
|
||||
int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags);
|
||||
int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id,
|
||||
int direction, int rx_irq);
|
||||
#else
|
||||
|
|
@ -57,25 +62,28 @@ static inline int hh_dbl_rx_unregister(void *dbl_client_desc)
|
|||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags)
|
||||
static inline int hh_dbl_send(void *dbl_client_desc, uint64_t *newflags,
|
||||
const unsigned long flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int hh_dbl_set_mask(void *dbl_client_desc,
|
||||
hh_dbl_flags_t enable_mask,
|
||||
hh_dbl_flags_t ack_mask)
|
||||
hh_dbl_flags_t ack_mask,
|
||||
const unsigned long flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int hh_dbl_read_and_clean(void *dbl_client_desc,
|
||||
hh_dbl_flags_t *clear_flags)
|
||||
hh_dbl_flags_t *clear_flags,
|
||||
const unsigned long flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int hh_dbl_reset(void *dbl_client_desc)
|
||||
static inline int hh_dbl_reset(void *dbl_client_desc, const unsigned long flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,11 +132,14 @@ struct hh_notify_vmid_desc {
|
|||
#define HH_RM_NOTIF_VM_IRQ_RELEASED 0x56100012
|
||||
|
||||
#define HH_RM_VM_STATUS_NO_STATE 0
|
||||
#define HH_RM_VM_STATUS_RUNNING 1
|
||||
#define HH_RM_VM_STATUS_PAUSED 2
|
||||
#define HH_RM_VM_STATUS_SHUTDOWN 3
|
||||
#define HH_RM_VM_STATUS_SHUTOFF 4
|
||||
#define HH_RM_VM_STATUS_CRASHED 5
|
||||
#define HH_RM_VM_STATUS_INIT 1
|
||||
#define HH_RM_VM_STATUS_READY 2
|
||||
#define HH_RM_VM_STATUS_RUNNING 3
|
||||
#define HH_RM_VM_STATUS_PAUSED 4
|
||||
#define HH_RM_VM_STATUS_SHUTDOWN 5
|
||||
#define HH_RM_VM_STATUS_SHUTOFF 6
|
||||
#define HH_RM_VM_STATUS_CRASHED 7
|
||||
#define HH_RM_VM_STATUS_INIT_FAILED 8
|
||||
|
||||
#define HH_RM_OS_STATUS_NONE 0
|
||||
#define HH_RM_OS_STATUS_EARLY_BOOT 1
|
||||
|
|
@ -192,6 +195,9 @@ int hh_rm_get_vmid(enum hh_vm_names vm_name, hh_vmid_t *vmid);
|
|||
int hh_rm_get_vm_name(hh_vmid_t vmid, enum hh_vm_names *vm_name);
|
||||
int hh_rm_vm_start(int vmid);
|
||||
|
||||
/* Client APIs for VM query */
|
||||
int hh_rm_populate_hyp_res(hh_vmid_t vmid);
|
||||
|
||||
/* Client APIs for VM Services */
|
||||
int hh_rm_console_open(hh_vmid_t vmid);
|
||||
int hh_rm_console_close(hh_vmid_t vmid);
|
||||
|
|
@ -276,6 +282,12 @@ static inline int hh_rm_vm_start(int vmid)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Client APIs for VM query */
|
||||
static inline int hh_rm_populate_hyp_res(hh_vmid_t vmid)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Client APIs for VM Services */
|
||||
static inline int hh_rm_console_open(hh_vmid_t vmid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ static inline int channel_hh_kick(struct neuron_mq_data_priv *priv)
|
|||
hh_dbl_flags_t dbl_mask = CH_DBL_MASK;
|
||||
int ret;
|
||||
|
||||
ret = hh_dbl_send(priv->tx_dbl, &dbl_mask);
|
||||
ret = hh_dbl_send(priv->tx_dbl, &dbl_mask, 0);
|
||||
if (ret)
|
||||
pr_err("failed to raise virq to the sender %d\n", ret);
|
||||
|
||||
|
|
@ -251,6 +251,11 @@ static int channel_sync_thread(void *data)
|
|||
struct neuron_shmem_channel_header *hdr;
|
||||
struct neuron_mq_data_priv *priv = (struct neuron_mq_data_priv *)data;
|
||||
|
||||
/* Init the shared memory header and local message queue. */
|
||||
if (msgq_init(priv)) {
|
||||
pr_err("%s: msgq_init failed\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
hdr = (struct neuron_shmem_channel_header *)priv->base;
|
||||
|
||||
/* Waiting for head being updated by the sender. */
|
||||
|
|
@ -380,12 +385,7 @@ static int channel_hh_probe(struct neuron_channel *cdev)
|
|||
goto fail_rx_dbl;
|
||||
}
|
||||
|
||||
/* Init the shared memory header and local message queue. */
|
||||
ret = msgq_init(priv);
|
||||
if (ret)
|
||||
goto fail_mask;
|
||||
init_waitqueue_head(&priv->wait_q);
|
||||
|
||||
/* Start the thread for syncing with the sender. */
|
||||
priv->sync_thread = kthread_run(channel_sync_thread, priv,
|
||||
"recv_sync_thread");
|
||||
|
|
@ -394,8 +394,6 @@ static int channel_hh_probe(struct neuron_channel *cdev)
|
|||
|
||||
return 0;
|
||||
|
||||
fail_mask:
|
||||
hh_dbl_rx_unregister(priv->rx_dbl);
|
||||
fail_rx_dbl:
|
||||
hh_dbl_tx_unregister(priv->tx_dbl);
|
||||
fail_tx_dbl:
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static inline int channel_hh_kick(struct neuron_mq_data_priv *priv)
|
|||
hh_dbl_flags_t dbl_mask = CH_DBL_MASK;
|
||||
int ret;
|
||||
|
||||
ret = hh_dbl_send(priv->tx_dbl, &dbl_mask);
|
||||
ret = hh_dbl_send(priv->tx_dbl, &dbl_mask, 0);
|
||||
if (ret)
|
||||
pr_err("failed to raise virq to the sender %d\n", ret);
|
||||
|
||||
|
|
@ -217,6 +217,19 @@ static int read_config(struct neuron_mq_data_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void msgq_init(struct neuron_mq_data_priv *priv)
|
||||
{
|
||||
struct neuron_shmem_channel_header *hdr = priv->base;
|
||||
struct neuron_msg_queue *msgq = &priv->msgq;
|
||||
|
||||
msgq->headp = &hdr->head;
|
||||
msgq->space_for_next_p = &hdr->space_for_next;
|
||||
msgq->offset = (u32)-1;
|
||||
|
||||
/* Set it to -1 as UNINITIALIZED */
|
||||
smp_store_release(msgq->headp, (u32)-1);
|
||||
}
|
||||
|
||||
/* Thread to sync with the receiver. Note: this thread might never finishes if
|
||||
* it fails to sync with the peer.
|
||||
*/
|
||||
|
|
@ -225,6 +238,7 @@ static int channel_sync_thread(void *data)
|
|||
struct neuron_mq_data_priv *priv = (struct neuron_mq_data_priv *)data;
|
||||
struct neuron_shmem_channel_header *hdr;
|
||||
|
||||
msgq_init(priv);
|
||||
hdr = (struct neuron_shmem_channel_header *)priv->base;
|
||||
hdr->version = CHANNEL_VERSION;
|
||||
hdr->tail_offset = -1;
|
||||
|
|
@ -265,19 +279,6 @@ static int channel_sync_thread(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void msgq_init(struct neuron_mq_data_priv *priv)
|
||||
{
|
||||
struct neuron_shmem_channel_header *hdr = priv->base;
|
||||
struct neuron_msg_queue *msgq = &priv->msgq;
|
||||
|
||||
msgq->headp = &hdr->head;
|
||||
msgq->space_for_next_p = &hdr->space_for_next;
|
||||
msgq->offset = (u32)-1;
|
||||
|
||||
/* Set it to -1 as UNINITIALIZED */
|
||||
smp_store_release(msgq->headp, (u32)-1);
|
||||
}
|
||||
|
||||
static int channel_hh_map_memory(struct neuron_mq_data_priv *priv,
|
||||
struct device *dev)
|
||||
{
|
||||
|
|
@ -367,7 +368,6 @@ static int channel_hh_probe(struct neuron_channel *cdev)
|
|||
goto fail_rx_dbl;
|
||||
}
|
||||
|
||||
msgq_init(priv);
|
||||
init_waitqueue_head(&priv->wait_q);
|
||||
/* Start the thread for syncing with the receiver. */
|
||||
priv->sync_thread = kthread_run(channel_sync_thread, priv,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static void qrtr_haven_kick(struct qrtr_haven_dev *qdev)
|
|||
hh_dbl_flags_t dbl_mask = QRTR_DBL_MASK;
|
||||
int ret;
|
||||
|
||||
ret = hh_dbl_send(qdev->tx_dbl, &dbl_mask);
|
||||
ret = hh_dbl_send(qdev->tx_dbl, &dbl_mask, HH_DBL_NONBLOCK);
|
||||
if (ret)
|
||||
dev_err(qdev->dev, "failed to raise doorbell %d\n", ret);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue