diff --git a/drivers/soc/qcom/guestvm_loader.c b/drivers/soc/qcom/guestvm_loader.c index 201d0f33bec5..7eb0e0e10b47 100644 --- a/drivers/soc/qcom/guestvm_loader.c +++ b/drivers/soc/qcom/guestvm_loader.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -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: diff --git a/drivers/virt/haven/hh_dbl.c b/drivers/virt/haven/hh_dbl.c index 945a09e8973e..d08a27340482 100644 --- a/drivers/virt/haven/hh_dbl.c +++ b/drivers/virt/haven/hh_dbl.c @@ -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: diff --git a/drivers/virt/haven/hh_rm_core.c b/drivers/virt/haven/hh_rm_core.c index 83a48d10a92b..330acc9c5a85 100644 --- a/drivers/virt/haven/hh_rm_core.c +++ b/drivers/virt/haven/hh_rm_core.c @@ -23,6 +23,7 @@ #include #include #include +#include #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) { diff --git a/drivers/virt/haven/hh_rm_iface.c b/drivers/virt/haven/hh_rm_iface.c index 6a13fd955f4a..ee8f4a5f5064 100644 --- a/drivers/virt/haven/hh_rm_iface.c +++ b/drivers/virt/haven/hh_rm_iface.c @@ -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; diff --git a/include/linux/haven/hh_dbl.h b/include/linux/haven/hh_dbl.h index 3c092bdea129..ab5c4ca40536 100644 --- a/include/linux/haven/hh_dbl.h +++ b/include/linux/haven/hh_dbl.h @@ -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; } diff --git a/include/linux/haven/hh_rm_drv.h b/include/linux/haven/hh_rm_drv.h index 861b5e15956e..9dad98a13fcb 100644 --- a/include/linux/haven/hh_rm_drv.h +++ b/include/linux/haven/hh_rm_drv.h @@ -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) { diff --git a/net/neuron/channel/ch_haven_recv.c b/net/neuron/channel/ch_haven_recv.c index ad654c489239..47f0a6568436 100644 --- a/net/neuron/channel/ch_haven_recv.c +++ b/net/neuron/channel/ch_haven_recv.c @@ -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: diff --git a/net/neuron/channel/ch_haven_send.c b/net/neuron/channel/ch_haven_send.c index f803d7a04485..43ceb3387c16 100644 --- a/net/neuron/channel/ch_haven_send.c +++ b/net/neuron/channel/ch_haven_send.c @@ -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, diff --git a/net/qrtr/haven.c b/net/qrtr/haven.c index 446d42dd85ec..fc39f96c6b01 100644 --- a/net/qrtr/haven.c +++ b/net/qrtr/haven.c @@ -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); }