Merge "soc: qcom: hab: Replace imp whse with rbtree based"

This commit is contained in:
QCTECMDR Service 2024-09-04 19:04:22 -07:00 committed by Gerrit - the friendly Code Review server
commit 9a254c3f9e
7 changed files with 177 additions and 93 deletions

View File

@ -80,7 +80,7 @@ struct uhab_context *hab_ctx_alloc(int kernel)
ctx->closing = 0;
INIT_LIST_HEAD(&ctx->vchannels);
INIT_LIST_HEAD(&ctx->exp_whse);
INIT_LIST_HEAD(&ctx->imp_whse);
hab_rb_init(&ctx->imp_whse);
INIT_LIST_HEAD(&ctx->exp_rxq);
init_waitqueue_head(&ctx->exp_wq);
@ -167,8 +167,11 @@ void hab_ctx_free_fn(struct uhab_context *ctx)
write_unlock(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
list_del(&exp->node);
for (exp_super = hab_rb_min(&ctx->imp_whse, struct export_desc_super, node);
exp_super != NULL;
exp_super = hab_rb_min(&ctx->imp_whse, struct export_desc_super, node)) {
exp = &exp_super->exp;
hab_rb_remove(&ctx->imp_whse, exp_super);
ctx->import_total--;
pr_debug("leaked imp %d vcid %X for ctx is collected total %d\n",
exp->export_id, exp->vcid_local,

View File

@ -318,7 +318,7 @@ struct uhab_context {
struct list_head exp_rxq;
spinlock_t expq_lock;
struct list_head imp_whse;
HAB_RB_ROOT imp_whse;
spinlock_t imp_lock;
uint32_t import_total;
@ -511,6 +511,8 @@ struct export_desc_super {
enum export_state exp_state;
uint32_t remote_imported;
HAB_RB_ENTRY node;
/*
* exp must be the last member
* because it is a variable length struct with pfns as payload
@ -767,4 +769,8 @@ int hab_stat_log(struct physical_channel **pchans, int pchan_cnt, char *dest,
int hab_stat_buffer_print(char *dest,
int dest_size, const char *fmt, ...);
int hab_create_cdev_node(int mmid_grp_index);
struct export_desc_super *hab_rb_exp_insert(struct rb_root *root, struct export_desc_super *exp_s);
struct export_desc_super *hab_rb_exp_find(struct rb_root *root, struct export_desc_super *key);
#endif /* __HAB_H */

View File

@ -423,6 +423,64 @@ static void reclaim_cleanup(struct work_struct *reclaim_work)
}
}
void hab_rb_init(struct rb_root *root)
{
*root = RB_ROOT;
}
struct export_desc_super *hab_rb_exp_find(struct rb_root *root, struct export_desc_super *key)
{
struct rb_node *node = root->rb_node;
struct export_desc_super *exp_super;
while (node) {
exp_super = rb_entry(node, struct export_desc_super, node);
if (key->exp.export_id < exp_super->exp.export_id)
node = node->rb_left;
else if (key->exp.export_id > exp_super->exp.export_id)
node = node->rb_right;
else {
if (key->exp.pchan < exp_super->exp.pchan)
node = node->rb_left;
else if (key->exp.pchan > exp_super->exp.pchan)
node = node->rb_right;
else
return exp_super;
}
}
return NULL;
}
struct export_desc_super *hab_rb_exp_insert(struct rb_root *root, struct export_desc_super *exp_s)
{
struct rb_node **new = &(root->rb_node), *parent = NULL;
while (*new) {
struct export_desc_super *this = rb_entry(*new, struct export_desc_super, node);
parent = *new;
if (exp_s->exp.export_id < this->exp.export_id)
new = &((*new)->rb_left);
else if (exp_s->exp.export_id > this->exp.export_id)
new = &((*new)->rb_right);
else {
if (exp_s->exp.pchan < this->exp.pchan)
new = &((*new)->rb_left);
else if (exp_s->exp.pchan > this->exp.pchan)
new = &((*new)->rb_right);
else
/* should not found the target key before insert */
return this;
}
}
rb_link_node(&exp_s->node, parent, new);
rb_insert_color(&exp_s->node, root);
return NULL;
}
/* create one more char device for /dev/hab */
#define CDEV_NUM_MAX (MM_ID_MAX / 100 + 1)

View File

@ -470,8 +470,8 @@ int hab_mem_import(struct uhab_context *ctx,
int kernel)
{
int ret = 0, found = 0;
struct export_desc *exp = NULL;
struct export_desc_super *exp_super = NULL;
struct export_desc *export = NULL;
struct export_desc_super *exp_super = NULL, key = {0};
struct virtual_channel *vchan = NULL;
struct hab_header header = HAB_HEADER_INITIALIZER;
struct hab_import_ack expected_ack = {0};
@ -528,59 +528,56 @@ int hab_mem_import(struct uhab_context *ctx,
}
}
key.exp.export_id = param->exportid;
key.exp.pchan = vchan->pchan;
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry(exp, &ctx->imp_whse, node) {
if ((exp->export_id == param->exportid) &&
(exp->pchan == vchan->pchan)) {
exp_super = container_of(exp, struct export_desc_super, exp);
/* not allowed to import one exp desc more than once */
if (exp_super->import_state == EXP_DESC_IMPORTED
|| exp_super->import_state == EXP_DESC_IMPORTING) {
pr_err("vc %x not allowed to import expid %u more than once\n",
vchan->id, exp->export_id);
spin_unlock_bh(&ctx->imp_lock);
ret = -EINVAL;
goto err_imp;
}
/*
* set the flag to avoid another thread getting the exp desc again
* and must be before unlock, otherwise it is no use.
*/
exp_super->import_state = EXP_DESC_IMPORTING;
found = 1;
break;
exp_super = hab_rb_exp_find(&ctx->imp_whse, &key);
if (exp_super) {
/* not allowed to import one exp desc more than once */
if (exp_super->import_state == EXP_DESC_IMPORTED
|| exp_super->import_state == EXP_DESC_IMPORTING) {
export = &exp_super->exp;
pr_err("vc %x not allowed to import one expid %u more than once\n",
vchan->id, export->export_id);
spin_unlock_bh(&ctx->imp_lock);
ret = -EINVAL;
goto err_imp;
}
}
spin_unlock_bh(&ctx->imp_lock);
if (!found) {
pr_err("vc %x fail to get export descriptor from export id %d\n",
vchan->id, param->exportid);
/*
* set the flag to avoid another thread getting the exp desc again
* and must be before unlock, otherwise it is no use.
*/
exp_super->import_state = EXP_DESC_IMPORTING;
found = 1;
} else {
spin_unlock_bh(&ctx->imp_lock);
pr_err("Fail to get export descriptor from export id %d vcid %x\n",
param->exportid, vchan->id);
ret = -ENODEV;
goto err_imp;
}
spin_unlock_bh(&ctx->imp_lock);
if ((exp->payload_count << PAGE_SHIFT) != param->sizebytes) {
export = &exp_super->exp;
if ((export->payload_count << PAGE_SHIFT) != param->sizebytes) {
pr_err("vc %x input size %d don't match buffer size %d\n",
vchan->id, param->sizebytes, exp->payload_count << PAGE_SHIFT);
vchan->id, param->sizebytes, export->payload_count << PAGE_SHIFT);
ret = -EINVAL;
exp_super->import_state = EXP_DESC_INIT;
goto err_imp;
}
ret = habmem_imp_hyp_map(ctx->import_ctx, param, exp, kernel);
ret = habmem_imp_hyp_map(ctx->import_ctx, param, export, kernel);
if (ret) {
pr_err("Import fail on vc %x ret:%d pcnt:%d rem:%d 1st_ref:0x%X\n",
vchan->id, ret, exp->payload_count,
exp->domid_local, *((uint32_t *)exp->payload));
vchan->id, ret, export->payload_count,
export->domid_local, *((uint32_t *)export->payload));
exp_super->import_state = EXP_DESC_INIT;
goto err_imp;
}
exp->import_index = param->index;
exp->kva = kernel ? (void *)param->kva : NULL;
export->import_index = param->index;
export->kva = kernel ? (void *)param->kva : NULL;
exp_super->import_state = EXP_DESC_IMPORTED;
err_imp:
@ -590,10 +587,10 @@ int hab_mem_import(struct uhab_context *ctx,
(found == 1) &&
(ret != 0)) {
/* dma_buf create failure, rollback required */
hab_send_unimport_msg(vchan, exp->export_id);
hab_send_unimport_msg(vchan, export->export_id);
spin_lock_bh(&ctx->imp_lock);
list_del(&exp->node);
hab_rb_remove(&ctx->imp_whse, exp_super);
ctx->import_total--;
spin_unlock_bh(&ctx->imp_lock);
@ -610,8 +607,8 @@ int hab_mem_unimport(struct uhab_context *ctx,
int kernel)
{
int ret = 0, found = 0;
struct export_desc *exp = NULL, *exp_tmp;
struct export_desc_super *exp_super = NULL;
struct export_desc *exp = NULL;
struct export_desc_super *exp_super = NULL, key = {0};
struct virtual_channel *vchan;
if (!ctx || !param)
@ -624,30 +621,27 @@ int hab_mem_unimport(struct uhab_context *ctx,
return -ENODEV;
}
key.exp.export_id = param->exportid;
key.exp.pchan = vchan->pchan;
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
/* same pchan is expected here */
if (exp->export_id == param->exportid &&
exp->pchan == vchan->pchan) {
exp_super = container_of(exp, struct export_desc_super, exp);
/* only successfully imported export desc could be found and released */
if (exp_super->import_state == EXP_DESC_IMPORTED) {
list_del(&exp->node);
ctx->import_total--;
found = 1;
} else
pr_err("vc %x exp id:%u status:%d is found, invalid to unimport\n",
vchan->id, exp->export_id, exp_super->import_state);
break;
}
exp_super = hab_rb_exp_find(&ctx->imp_whse, &key);
if (exp_super) {
/* only successfully imported export desc could be found and released */
if (exp_super->import_state == EXP_DESC_IMPORTED) {
hab_rb_remove(&ctx->imp_whse, exp_super);
ctx->import_total--;
found = 1;
} else
pr_err("vc %x exp id:%u status:%d is found, invalid to unimport\n",
vchan->id, exp_super->exp.export_id, exp_super->import_state);
}
spin_unlock_bh(&ctx->imp_lock);
if (!found)
if (!found) {
ret = -EINVAL;
else {
pr_err("exp id %u unavailable on vc %x\n", param->exportid, vchan->id);
} else {
exp = &exp_super->exp;
ret = habmm_imp_hyp_unmap(ctx->import_ctx, exp, kernel);
if (ret) {
pr_err("unmap fail id:%d pcnt:%d vcid:%d\n",

View File

@ -242,17 +242,23 @@ static void hab_msg_queue(struct virtual_channel *vchan,
}
static int hab_export_enqueue(struct virtual_channel *vchan,
struct export_desc *exp)
struct export_desc *export)
{
struct uhab_context *ctx = vchan->ctx;
struct export_desc_super *exp_super = container_of(export, struct export_desc_super, exp);
int irqs_disabled = irqs_disabled();
struct export_desc_super *ret;
hab_spin_lock(&ctx->imp_lock, irqs_disabled);
list_add_tail(&exp->node, &ctx->imp_whse);
ctx->import_total++;
ret = hab_rb_exp_insert(&ctx->imp_whse, exp_super);
if (ret != NULL)
pr_err("expid %u already exists on vc %x, size %d\n",
export->export_id, vchan->id, PAGE_SIZE * export->payload_count);
else
ctx->import_total++;
hab_spin_unlock(&ctx->imp_lock, irqs_disabled);
return 0;
return (ret == NULL) ? 0 : -EINVAL;
}
/*
@ -544,19 +550,22 @@ static int hab_receive_export_desc(struct physical_channel *pchan,
ack_recvd->ack.export_id = exp_desc->export_id;
ack_recvd->ack.vcid_local = exp_desc->vcid_local;
ack_recvd->ack.vcid_remote = exp_desc->vcid_remote;
ack_recvd->ack.imp_whse_added = 1;
}
hab_export_enqueue(vchan, exp_desc);
ret = hab_export_enqueue(vchan, exp_desc);
if (pchan->mem_proto == 1) {
ack_recvd->ack.imp_whse_added = ret ? 0 : 1;
hab_spin_lock(&vchan->ctx->impq_lock, irqs_disabled);
list_add_tail(&ack_recvd->node, &vchan->ctx->imp_rxq);
hab_spin_unlock(&vchan->ctx->impq_lock, irqs_disabled);
} else
hab_send_export_ack(vchan, pchan, exp_desc);
(void)hab_send_export_ack(vchan, pchan, exp_desc);
return 0;
if (ret)
kfree(exp_desc_super);
return ret;
err_imp:
if (pchan->mem_proto == 1) {

View File

@ -40,6 +40,17 @@
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/devcoredump.h>
void hab_rb_init(struct rb_root *root);
#define hab_rb_remove(root, pos) rb_erase(&(pos)->node, root)
#define hab_rb_min(root, type, node) rb_entry_safe(rb_first(root), type, node)
#define hab_rb_max(root, type, node) rb_entry_safe(rb_last(root), type, node)
#define hab_rb_for_each_entry(pos, n, head, member) \
rbtree_postorder_for_each_entry_safe(pos, n, head, member)
#define HAB_RB_ENTRY struct rb_node
#define HAB_RB_ROOT struct rb_root
#if defined(CONFIG_MSM_VHOST_HAB) || defined(CONFIG_MSM_VIRTIO_HAB)
#include <asm/arch_timer.h>
static inline unsigned long long msm_timer_get_sclk_ticks(void)

View File

@ -121,13 +121,14 @@ static int print_ctx_total_expimp(struct uhab_context *ctx,
struct compressed_pfns *pfn_table = NULL;
int exp_total = 0, imp_total = 0;
int exp_cnt = 0, imp_cnt = 0;
struct export_desc *exp = NULL;
struct export_desc *export = NULL;
struct export_desc_super *exp_super, *exp_super_tmp;
int exim_size = 0;
int ret = 0;
read_lock(&ctx->exp_lock);
list_for_each_entry(exp, &ctx->exp_whse, node) {
pfn_table = (struct compressed_pfns *)exp->payload;
list_for_each_entry(export, &ctx->exp_whse, node) {
pfn_table = (struct compressed_pfns *)export->payload;
exim_size = get_pft_tbl_total_size(pfn_table);
exp_total += exim_size;
exp_cnt++;
@ -135,9 +136,10 @@ static int print_ctx_total_expimp(struct uhab_context *ctx,
read_unlock(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry(exp, &ctx->imp_whse, node) {
if (habmm_imp_hyp_map_check(ctx->import_ctx, exp)) {
pfn_table = (struct compressed_pfns *)exp->payload;
hab_rb_for_each_entry(exp_super, exp_super_tmp, &ctx->imp_whse, node) {
export = &exp_super->exp;
if (habmm_imp_hyp_map_check(ctx->import_ctx, export)) {
pfn_table = (struct compressed_pfns *)export->payload;
exim_size = get_pft_tbl_total_size(pfn_table);
imp_total += exim_size;
imp_cnt++;
@ -146,7 +148,7 @@ static int print_ctx_total_expimp(struct uhab_context *ctx,
spin_unlock_bh(&ctx->imp_lock);
if (exp_cnt || exp_total || imp_cnt || imp_total)
hab_stat_buffer_print(buf, size,
ret = hab_stat_buffer_print(buf, size,
"ctx %d exp %d size %d imp %d size %d\n",
ctx->owner, exp_cnt, exp_total,
imp_cnt, imp_total);
@ -154,26 +156,27 @@ static int print_ctx_total_expimp(struct uhab_context *ctx,
return 0;
read_lock(&ctx->exp_lock);
hab_stat_buffer_print(buf, size, "export[expid:vcid:size]: ");
list_for_each_entry(exp, &ctx->exp_whse, node) {
pfn_table = (struct compressed_pfns *)exp->payload;
ret = hab_stat_buffer_print(buf, size, "export[expid:vcid:size]: ");
list_for_each_entry(export, &ctx->exp_whse, node) {
pfn_table = (struct compressed_pfns *)export->payload;
exim_size = get_pft_tbl_total_size(pfn_table);
hab_stat_buffer_print(buf, size,
"[%d:%x:%d] ", exp->export_id,
exp->vcid_local, exim_size);
ret = hab_stat_buffer_print(buf, size,
"[%d:%x:%d] ", export->export_id,
export->vcid_local, exim_size);
}
hab_stat_buffer_print(buf, size, "\n");
ret = hab_stat_buffer_print(buf, size, "\n");
read_unlock(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
hab_stat_buffer_print(buf, size, "import[expid:vcid:size]: ");
list_for_each_entry(exp, &ctx->imp_whse, node) {
if (habmm_imp_hyp_map_check(ctx->import_ctx, exp)) {
pfn_table = (struct compressed_pfns *)exp->payload;
ret = hab_stat_buffer_print(buf, size, "import[expid:vcid:size]: ");
hab_rb_for_each_entry(exp_super, exp_super_tmp, &ctx->imp_whse, node) {
export = &exp_super->exp;
if (habmm_imp_hyp_map_check(ctx->import_ctx, export)) {
pfn_table = (struct compressed_pfns *)export->payload;
exim_size = get_pft_tbl_total_size(pfn_table);
hab_stat_buffer_print(buf, size,
"[%d:%x:%d] ", exp->export_id,
exp->vcid_local, exim_size);
ret = hab_stat_buffer_print(buf, size,
"[%d:%x:%d] ", export->export_id,
export->vcid_local, exim_size);
}
}
ret = hab_stat_buffer_print(buf, size, "\n");