soc: qcom: glink: Reduce code under spinlock
Glink core channel cleanup has a lot of code under spinlock with preemption disabled this leads to deadlock scenerio. Spinklock is used only for critical section, rest of the code is be without spinlock. CRs-Fixed: 1060407 Change-Id: I577dbff1cf2ee3711e1879aaa6dc48c72f98b98c Signed-off-by: Dhoat Harpal <hdhoat@codeaurora.org>
This commit is contained in:
parent
c605e110ab
commit
4f6f2d2a7b
1 changed files with 39 additions and 20 deletions
|
@ -4020,6 +4020,37 @@ static struct glink_core_xprt_ctx *glink_create_dummy_xprt_ctx(
|
||||||
return xprt_ptr;
|
return xprt_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct channel_ctx *get_first_ch_ctx(
|
||||||
|
struct glink_core_xprt_ctx *xprt_ctx)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct channel_ctx *ctx;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
|
||||||
|
if (!list_empty(&xprt_ctx->channels)) {
|
||||||
|
ctx = list_first_entry(&xprt_ctx->channels,
|
||||||
|
struct channel_ctx, port_list_node);
|
||||||
|
rwref_get(&ctx->ch_state_lhb2);
|
||||||
|
} else {
|
||||||
|
ctx = NULL;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void glink_core_move_ch_node(struct glink_core_xprt_ctx *xprt_ptr,
|
||||||
|
struct glink_core_xprt_ctx *dummy_xprt_ctx, struct channel_ctx *ctx)
|
||||||
|
{
|
||||||
|
unsigned long flags, d_flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
||||||
|
spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
||||||
|
rwref_get(&dummy_xprt_ctx->xprt_state_lhb0);
|
||||||
|
list_move_tail(&ctx->port_list_node, &dummy_xprt_ctx->channels);
|
||||||
|
spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
||||||
|
spin_unlock_irqrestore(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* glink_core_channel_cleanup() - cleanup all channels for the transport
|
* glink_core_channel_cleanup() - cleanup all channels for the transport
|
||||||
*
|
*
|
||||||
|
@ -4030,7 +4061,7 @@ static struct glink_core_xprt_ctx *glink_create_dummy_xprt_ctx(
|
||||||
static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
|
static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
|
||||||
{
|
{
|
||||||
unsigned long flags, d_flags;
|
unsigned long flags, d_flags;
|
||||||
struct channel_ctx *ctx, *tmp_ctx;
|
struct channel_ctx *ctx;
|
||||||
struct channel_lcid *temp_lcid, *temp_lcid1;
|
struct channel_lcid *temp_lcid, *temp_lcid1;
|
||||||
struct glink_core_xprt_ctx *dummy_xprt_ctx;
|
struct glink_core_xprt_ctx *dummy_xprt_ctx;
|
||||||
|
|
||||||
|
@ -4039,29 +4070,18 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
|
||||||
GLINK_ERR("%s: Dummy Transport creation failed\n", __func__);
|
GLINK_ERR("%s: Dummy Transport creation failed\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rwref_read_get(&dummy_xprt_ctx->xprt_state_lhb0);
|
rwref_read_get(&dummy_xprt_ctx->xprt_state_lhb0);
|
||||||
rwref_read_get(&xprt_ptr->xprt_state_lhb0);
|
rwref_read_get(&xprt_ptr->xprt_state_lhb0);
|
||||||
spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
ctx = get_first_ch_ctx(xprt_ptr);
|
||||||
spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
while (ctx) {
|
||||||
|
|
||||||
list_for_each_entry_safe(ctx, tmp_ctx, &xprt_ptr->channels,
|
|
||||||
port_list_node) {
|
|
||||||
rwref_write_get_atomic(&ctx->ch_state_lhb2, true);
|
rwref_write_get_atomic(&ctx->ch_state_lhb2, true);
|
||||||
if (ctx->local_open_state == GLINK_CHANNEL_OPENED ||
|
if (ctx->local_open_state == GLINK_CHANNEL_OPENED ||
|
||||||
ctx->local_open_state == GLINK_CHANNEL_OPENING) {
|
ctx->local_open_state == GLINK_CHANNEL_OPENING) {
|
||||||
rwref_get(&dummy_xprt_ctx->xprt_state_lhb0);
|
|
||||||
list_move_tail(&ctx->port_list_node,
|
|
||||||
&dummy_xprt_ctx->channels);
|
|
||||||
ctx->transport_ptr = dummy_xprt_ctx;
|
ctx->transport_ptr = dummy_xprt_ctx;
|
||||||
rwref_write_put(&ctx->ch_state_lhb2);
|
rwref_write_put(&ctx->ch_state_lhb2);
|
||||||
|
glink_core_move_ch_node(xprt_ptr, dummy_xprt_ctx, ctx);
|
||||||
} else {
|
} else {
|
||||||
/* local state is in either CLOSED or CLOSING */
|
/* local state is in either CLOSED or CLOSING */
|
||||||
spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1,
|
|
||||||
flags);
|
|
||||||
spin_unlock_irqrestore(
|
|
||||||
&dummy_xprt_ctx->xprt_ctx_lock_lhb1,
|
|
||||||
d_flags);
|
|
||||||
glink_core_remote_close_common(ctx, true);
|
glink_core_remote_close_common(ctx, true);
|
||||||
if (ctx->local_open_state == GLINK_CHANNEL_CLOSING)
|
if (ctx->local_open_state == GLINK_CHANNEL_CLOSING)
|
||||||
glink_core_ch_close_ack_common(ctx, true);
|
glink_core_ch_close_ack_common(ctx, true);
|
||||||
|
@ -4069,22 +4089,21 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
|
||||||
if (ch_is_fully_closed(ctx))
|
if (ch_is_fully_closed(ctx))
|
||||||
glink_delete_ch_from_list(ctx, false);
|
glink_delete_ch_from_list(ctx, false);
|
||||||
rwref_write_put(&ctx->ch_state_lhb2);
|
rwref_write_put(&ctx->ch_state_lhb2);
|
||||||
spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1,
|
|
||||||
d_flags);
|
|
||||||
spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
|
||||||
}
|
}
|
||||||
|
rwref_put(&ctx->ch_state_lhb2);
|
||||||
|
ctx = get_first_ch_ctx(xprt_ptr);
|
||||||
}
|
}
|
||||||
|
spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
||||||
list_for_each_entry_safe(temp_lcid, temp_lcid1,
|
list_for_each_entry_safe(temp_lcid, temp_lcid1,
|
||||||
&xprt_ptr->free_lcid_list, list_node) {
|
&xprt_ptr->free_lcid_list, list_node) {
|
||||||
list_del(&temp_lcid->list_node);
|
list_del(&temp_lcid->list_node);
|
||||||
kfree(&temp_lcid->list_node);
|
kfree(&temp_lcid->list_node);
|
||||||
}
|
}
|
||||||
dummy_xprt_ctx->dummy_in_use = false;
|
|
||||||
spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
|
||||||
spin_unlock_irqrestore(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
|
||||||
rwref_read_put(&xprt_ptr->xprt_state_lhb0);
|
rwref_read_put(&xprt_ptr->xprt_state_lhb0);
|
||||||
|
|
||||||
spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
spin_lock_irqsave(&dummy_xprt_ctx->xprt_ctx_lock_lhb1, d_flags);
|
||||||
|
dummy_xprt_ctx->dummy_in_use = false;
|
||||||
while (!list_empty(&dummy_xprt_ctx->channels)) {
|
while (!list_empty(&dummy_xprt_ctx->channels)) {
|
||||||
ctx = list_first_entry(&dummy_xprt_ctx->channels,
|
ctx = list_first_entry(&dummy_xprt_ctx->channels,
|
||||||
struct channel_ctx, port_list_node);
|
struct channel_ctx, port_list_node);
|
||||||
|
|
Loading…
Add table
Reference in a new issue