diff --git a/drivers/virt/haven/hh_dbl.c b/drivers/virt/haven/hh_dbl.c index 265c0dc6110e..1120ccee5ec8 100644 --- a/drivers/virt/haven/hh_dbl.c +++ b/drivers/virt/haven/hh_dbl.c @@ -5,8 +5,8 @@ */ #include -#include #include +#include #include #include @@ -24,7 +24,7 @@ enum hh_dbl_dir { struct hh_dbl_cap_table { struct hh_dbl_desc *client_desc; - struct mutex cap_entry_lock; + spinlock_t cap_entry_lock; hh_capid_t tx_cap_id; int tx_reg_done; @@ -47,6 +47,7 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc, enum hh_dbl_dir dir, const unsigned long flags) { struct hh_dbl_cap_table *cap_table_entry; + int ret; if (IS_ERR_OR_NULL(client_desc)) return -EINVAL; @@ -57,6 +58,8 @@ static int hh_dbl_validate_params(struct hh_dbl_desc *client_desc, cap_table_entry = &hh_dbl_cap_table[client_desc->label]; + spin_lock(&cap_table_entry->cap_entry_lock); + if (cap_table_entry->client_desc != client_desc) { pr_err("%s: Invalid client descriptor\n", __func__); return -EINVAL; @@ -69,38 +72,47 @@ 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_reg_done) - return -EINVAL; + if (!cap_table_entry->rx_reg_done) { + ret = -EINVAL; + goto err; + } - if (cap_table_entry->rx_cap_id != HH_CAPID_INVAL) - return 0; + if ((cap_table_entry->rx_cap_id == HH_CAPID_INVAL) && + (flags & HH_DBL_NONBLOCK)) { + ret = -EAGAIN; + goto err; + } - if (flags & HH_DBL_NONBLOCK) - return -EAGAIN; + spin_unlock(&cap_table_entry->cap_entry_lock); 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_reg_done) - return -EINVAL; + if (!cap_table_entry->tx_reg_done) { + ret = -EINVAL; + goto err; + } - if (cap_table_entry->tx_cap_id != HH_CAPID_INVAL) - return 0; + if ((cap_table_entry->tx_cap_id == HH_CAPID_INVAL) && + (flags & HH_DBL_NONBLOCK)) { + ret = -EAGAIN; + goto err; + } - if (flags & HH_DBL_NONBLOCK) - return -EAGAIN; + spin_unlock(&cap_table_entry->cap_entry_lock); if (wait_event_interruptible(cap_table_entry->cap_wq, cap_table_entry->tx_cap_id != HH_CAPID_INVAL)) return -ERESTARTSYS; - return 0; } return 0; +err: + spin_unlock(&cap_table_entry->cap_entry_lock); + return ret; } /** @@ -184,8 +196,6 @@ int hh_dbl_set_mask(void *dbl_client_desc, hh_dbl_flags_t enable_mask, if (ret != 0) pr_err("%s: Hypercall failed ret = %d\n", __func__, hh_ret); - mutex_unlock(&cap_table_entry->cap_entry_lock); - return ret; } EXPORT_SYMBOL(hh_dbl_set_mask); @@ -307,8 +317,7 @@ void *hh_dbl_tx_register(enum hh_dbl_label label) cap_table_entry = &hh_dbl_cap_table[label]; - if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock)) - return ERR_PTR(-ERESTARTSYS); + spin_lock(&cap_table_entry->cap_entry_lock); /* Avoid multiple client Tx registration for the same doorbell */ if (cap_table_entry->tx_reg_done) { @@ -333,11 +342,11 @@ void *hh_dbl_tx_register(enum hh_dbl_label label) pr_debug("%s: Registered Tx client for label: %d\n", __func__, label); - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return client_desc; err: - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return ERR_PTR(ret); } EXPORT_SYMBOL(hh_dbl_tx_register); @@ -370,8 +379,7 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv) cap_table_entry = &hh_dbl_cap_table[label]; - if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock)) - return ERR_PTR(-ERESTARTSYS); + spin_lock(&cap_table_entry->cap_entry_lock); /* Avoid multiple client Rx registration for the same doorbell */ if (cap_table_entry->rx_reg_done) { @@ -399,13 +407,13 @@ void *hh_dbl_rx_register(enum hh_dbl_label label, dbl_rx_cb_t rx_cb, void *priv) pr_debug("%s: Registered Rx client for label: %d\n", __func__, label); - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return client_desc; err: pr_debug("%s: Registration for Rx client for label failed: %d\n", __func__, label); - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return ERR_PTR(ret); } EXPORT_SYMBOL(hh_dbl_rx_register); @@ -432,14 +440,13 @@ int hh_dbl_tx_unregister(void *dbl_client_desc) cap_table_entry = &hh_dbl_cap_table[client_desc->label]; - if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock)) - return -ERESTARTSYS; + spin_lock(&cap_table_entry->cap_entry_lock); /* Is the client trying to free someone else's doorbell? */ if (cap_table_entry->client_desc != client_desc) { pr_err("%s: Trying to free invalid client descriptor!\n", __func__); - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return -EINVAL; } @@ -455,7 +462,7 @@ int hh_dbl_tx_unregister(void *dbl_client_desc) } cap_table_entry->tx_reg_done = 0; - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return 0; } @@ -483,14 +490,13 @@ int hh_dbl_rx_unregister(void *dbl_client_desc) cap_table_entry = &hh_dbl_cap_table[client_desc->label]; - if (mutex_lock_interruptible(&cap_table_entry->cap_entry_lock)) - return -ERESTARTSYS; + spin_lock(&cap_table_entry->cap_entry_lock); /* Is the client trying to free someone else's doorbell? */ if (cap_table_entry->client_desc != client_desc) { pr_err("%s: Trying to free invalid client descriptor!\n", __func__); - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return -EINVAL; } @@ -509,7 +515,7 @@ int hh_dbl_rx_unregister(void *dbl_client_desc) cap_table_entry->rx_priv_data = NULL; cap_table_entry->rx_reg_done = 0; - mutex_unlock(&cap_table_entry->cap_entry_lock); + spin_unlock(&cap_table_entry->cap_entry_lock); return 0; } @@ -524,6 +530,9 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id, struct hh_dbl_cap_table *cap_table_entry; int ret = 0; + if (!hh_dbl_initialized) + return -EAGAIN; + if (label < 0 || label >= HH_DBL_LABEL_MAX) { pr_err("%s: Invalid label passed\n", __func__); return -EINVAL; @@ -540,7 +549,10 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id, ret = -ENXIO; goto err; } + + spin_lock(&cap_table_entry->cap_entry_lock); cap_table_entry->tx_cap_id = cap_id; + spin_unlock(&cap_table_entry->cap_entry_lock); wake_up_interruptible(&cap_table_entry->cap_wq); @@ -554,9 +566,8 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id, ret = -ENXIO; goto err; } - cap_table_entry->rx_cap_id = cap_id; - cap_table_entry->rx_irq = rx_irq; + cap_table_entry->rx_irq = rx_irq; ret = request_threaded_irq(cap_table_entry->rx_irq, NULL, hh_dbl_rx_callback_thread, @@ -570,6 +581,11 @@ int hh_dbl_populate_cap_info(enum hh_dbl_label label, u64 cap_id, } irq_set_irq_wake(rx_irq, 1); + + spin_lock(&cap_table_entry->cap_entry_lock); + cap_table_entry->rx_cap_id = cap_id; + spin_unlock(&cap_table_entry->cap_entry_lock); + wake_up_interruptible(&cap_table_entry->cap_wq); pr_debug("%s: label: %d; rx_cap_id: %llu; dir: %d; rx_irq: %d\n", @@ -597,7 +613,6 @@ static void hh_dbl_cleanup(int begin_idx) for (i = begin_idx; i >= 0; i--) { cap_table_entry = &hh_dbl_cap_table[i]; kfree(cap_table_entry->rx_irq_name); - mutex_destroy(&cap_table_entry->cap_entry_lock); } } @@ -609,7 +624,7 @@ 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); + spin_lock_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; diff --git a/drivers/virt/haven/hh_msgq.c b/drivers/virt/haven/hh_msgq.c index 3d2b87acd961..899f61b77d74 100644 --- a/drivers/virt/haven/hh_msgq.c +++ b/drivers/virt/haven/hh_msgq.c @@ -420,7 +420,7 @@ int hh_msgq_populate_cap_info(enum hh_msgq_label label, u64 cap_id, int ret; if (!hh_msgq_initialized) - return -EPROBE_DEFER; + return -EAGAIN; if (label < 0 || label >= HH_MSGQ_LABEL_MAX) { pr_err("%s: Invalid label passed\n", __func__); diff --git a/drivers/virt/haven/hh_rm_core.c b/drivers/virt/haven/hh_rm_core.c index 67238a2819e0..39edd525e0f7 100644 --- a/drivers/virt/haven/hh_rm_core.c +++ b/drivers/virt/haven/hh_rm_core.c @@ -776,32 +776,35 @@ int hh_rm_populate_hyp_res(hh_vmid_t vmid) res_entries[i].cap_id_low; label = res_entries[i].resource_label; - /* Populate MessageQ & DBL's cap tables */ - switch (res_entries[i].res_type) { - case HH_RM_RES_TYPE_MQ_TX: - ret = hh_msgq_populate_cap_info(label, cap_id, + /* Populate MessageQ, DBL and vCPUs cap tables */ + do { + switch (res_entries[i].res_type) { + case HH_RM_RES_TYPE_MQ_TX: + ret = hh_msgq_populate_cap_info(label, cap_id, HH_MSGQ_DIRECTION_TX, linux_irq); - break; - case HH_RM_RES_TYPE_MQ_RX: - ret = hh_msgq_populate_cap_info(label, cap_id, + break; + case HH_RM_RES_TYPE_MQ_RX: + ret = hh_msgq_populate_cap_info(label, cap_id, HH_MSGQ_DIRECTION_RX, linux_irq); - break; - case HH_RM_RES_TYPE_VCPU: - ret = hh_vcpu_populate_affinity_info(label, cap_id); - break; - case HH_RM_RES_TYPE_DB_TX: - ret = hh_dbl_populate_cap_info(label, cap_id, + break; + case HH_RM_RES_TYPE_VCPU: + ret = hh_vcpu_populate_affinity_info(label, + cap_id); + break; + case HH_RM_RES_TYPE_DB_TX: + ret = hh_dbl_populate_cap_info(label, cap_id, HH_MSGQ_DIRECTION_TX, linux_irq); - break; - case HH_RM_RES_TYPE_DB_RX: - ret = hh_dbl_populate_cap_info(label, cap_id, + break; + case HH_RM_RES_TYPE_DB_RX: + ret = hh_dbl_populate_cap_info(label, cap_id, HH_MSGQ_DIRECTION_RX, linux_irq); - break; - default: - pr_err("%s: Unknown resource type: %u\n", - __func__, res_entries[i].res_type); - ret = -EINVAL; - } + break; + default: + pr_err("%s: Unknown resource type: %u\n", + __func__, res_entries[i].res_type); + ret = -EINVAL; + } + } while (ret == -EAGAIN); if (ret < 0) goto out;