Merge "soc: qcom: hab: Replace imp whse with rbtree based"
This commit is contained in:
commit
9a254c3f9e
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user