Loading drivers/soc/qcom/glink.c +104 −1 Original line number Diff line number Diff line Loading @@ -142,11 +142,28 @@ struct glink_core_xprt_ctx { bool qos_req_active; bool tx_path_activity; struct delayed_work pm_qos_work; struct glink_core_edge_ctx *edge_ctx; struct mutex xprt_dbgfs_lock_lhb4; void *log_ctx; }; /** * Edge Context * @list_node edge list node used by edge list * @name: name of the edge * @edge_migration_lock:mutex lock for migration over edge * @edge_ref_lock: lock for reference count */ struct glink_core_edge_ctx { struct list_head list_node; char name[GLINK_NAME_SIZE]; struct mutex edge_migration_lock_lhd2; struct rwref_lock edge_ref_lock_lhd1; }; static LIST_HEAD(edge_list); static DEFINE_MUTEX(edge_list_lock_lhd0); /** * Channel Context * @xprt_state_lhb0: controls read/write access to channel state Loading Loading @@ -953,6 +970,83 @@ err: return NULL; } /** * glink_core_migration_edge_lock() - gains a reference count for edge and * take muted lock * @xprt_ctx: transport of the edge */ static void glink_core_migration_edge_lock(struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx; rwref_get(&edge_ctx->edge_ref_lock_lhd1); mutex_lock(&edge_ctx->edge_migration_lock_lhd2); } /** * glink_core_migration_edge_unlock() - release a reference count for edge * and release muted lock. * @xprt_ctx: transport of the edge */ static void glink_core_migration_edge_unlock( struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx; mutex_unlock(&edge_ctx->edge_migration_lock_lhd2); rwref_put(&edge_ctx->edge_ref_lock_lhd1); } /** * glink_edge_ctx_release - Free the edge context * @ch_st_lock: handle to the rwref_lock associated with the edge * * This should only be called when the reference count associated with the * edge goes to zero. */ static void glink_edge_ctx_release(struct rwref_lock *ch_st_lock) { struct glink_core_edge_ctx *ctx = container_of(ch_st_lock, struct glink_core_edge_ctx, edge_ref_lock_lhd1); mutex_lock(&edge_list_lock_lhd0); list_del(&ctx->list_node); mutex_unlock(&edge_list_lock_lhd0); kfree(ctx); } /** * edge_name_to_ctx_create() - lookup a edge by name, create the edge ctx if * it is not found. * @xprt_ctx: Transport to search for a matching edge. * * Return: The edge ctx corresponding to edge of @xprt_ctx. */ static struct glink_core_edge_ctx *edge_name_to_ctx_create( struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx; mutex_lock(&edge_list_lock_lhd0); list_for_each_entry(edge_ctx, &edge_list, list_node) { if (!strcmp(edge_ctx->name, xprt_ctx->edge)) { rwref_get(&edge_ctx->edge_ref_lock_lhd1); mutex_unlock(&edge_list_lock_lhd0); return edge_ctx; } } edge_ctx = kzalloc(sizeof(struct glink_core_edge_ctx), GFP_KERNEL); strlcpy(edge_ctx->name, xprt_ctx->edge, GLINK_NAME_SIZE); rwref_lock_init(&edge_ctx->edge_ref_lock_lhd1, glink_edge_ctx_release); mutex_init(&edge_ctx->edge_migration_lock_lhd2); INIT_LIST_HEAD(&edge_ctx->list_node); list_add_tail(&edge_ctx->list_node, &edge_list); mutex_unlock(&edge_list_lock_lhd0); return edge_ctx; } /** * xprt_lcid_to_ch_ctx_get() - lookup a channel by local id * @xprt_ctx: Transport to search for a matching channel. Loading Loading @@ -3440,6 +3534,7 @@ void glink_xprt_ctx_release(struct rwref_lock *xprt_st_lock) xprt_rm_dbgfs.par_name = "xprt"; glink_debugfs_remove_recur(&xprt_rm_dbgfs); GLINK_INFO("%s: xprt debugfs removec\n", __func__); rwref_put(&xprt_ctx->edge_ctx->edge_ref_lock_lhd1); kthread_stop(xprt_ctx->tx_task); xprt_ctx->tx_task = NULL; glink_core_deinit_xprt_qos_cfg(xprt_ctx); Loading Loading @@ -3709,6 +3804,7 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, xprt_ptr->versions_entries = cfg->versions_entries; xprt_ptr->local_version_idx = cfg->versions_entries - 1; xprt_ptr->remote_version_idx = cfg->versions_entries - 1; xprt_ptr->edge_ctx = edge_name_to_ctx_create(xprt_ptr); xprt_ptr->l_features = cfg->versions[cfg->versions_entries - 1].features; if (!if_ptr->poll) Loading Loading @@ -4557,11 +4653,13 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, uint16_t xprt_resp; bool do_migrate; glink_core_migration_edge_lock(if_ptr->glink_core_priv); ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name); if (ctx == NULL) { GLINK_ERR_XPRT(if_ptr->glink_core_priv, "%s: invalid rcid %u received, name '%s'\n", __func__, rcid, name); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4570,6 +4668,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, GLINK_ERR_CH(ctx, "%s: Duplicate remote open for rcid %u, name '%s'\n", __func__, rcid, name); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4591,6 +4690,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, if (do_migrate) ch_migrate(NULL, ctx); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); } /** Loading @@ -4604,13 +4704,14 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, uint32_t lcid, uint16_t xprt_resp) { struct channel_ctx *ctx; glink_core_migration_edge_lock(if_ptr->glink_core_priv); ctx = xprt_lcid_to_ch_ctx_get(if_ptr->glink_core_priv, lcid); if (!ctx) { /* unknown LCID received - this shouldn't happen */ GLINK_ERR_XPRT(if_ptr->glink_core_priv, "%s: invalid lcid %u received\n", __func__, (unsigned)lcid); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4619,6 +4720,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, "%s: unexpected open ack receive for lcid. Current state: %u. Thread: %u\n", __func__, ctx->local_open_state, current->pid); rwref_put(&ctx->ch_state_lhb2); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4637,6 +4739,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, } } rwref_put(&ctx->ch_state_lhb2); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); } /** Loading Loading
drivers/soc/qcom/glink.c +104 −1 Original line number Diff line number Diff line Loading @@ -142,11 +142,28 @@ struct glink_core_xprt_ctx { bool qos_req_active; bool tx_path_activity; struct delayed_work pm_qos_work; struct glink_core_edge_ctx *edge_ctx; struct mutex xprt_dbgfs_lock_lhb4; void *log_ctx; }; /** * Edge Context * @list_node edge list node used by edge list * @name: name of the edge * @edge_migration_lock:mutex lock for migration over edge * @edge_ref_lock: lock for reference count */ struct glink_core_edge_ctx { struct list_head list_node; char name[GLINK_NAME_SIZE]; struct mutex edge_migration_lock_lhd2; struct rwref_lock edge_ref_lock_lhd1; }; static LIST_HEAD(edge_list); static DEFINE_MUTEX(edge_list_lock_lhd0); /** * Channel Context * @xprt_state_lhb0: controls read/write access to channel state Loading Loading @@ -953,6 +970,83 @@ err: return NULL; } /** * glink_core_migration_edge_lock() - gains a reference count for edge and * take muted lock * @xprt_ctx: transport of the edge */ static void glink_core_migration_edge_lock(struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx; rwref_get(&edge_ctx->edge_ref_lock_lhd1); mutex_lock(&edge_ctx->edge_migration_lock_lhd2); } /** * glink_core_migration_edge_unlock() - release a reference count for edge * and release muted lock. * @xprt_ctx: transport of the edge */ static void glink_core_migration_edge_unlock( struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx = xprt_ctx->edge_ctx; mutex_unlock(&edge_ctx->edge_migration_lock_lhd2); rwref_put(&edge_ctx->edge_ref_lock_lhd1); } /** * glink_edge_ctx_release - Free the edge context * @ch_st_lock: handle to the rwref_lock associated with the edge * * This should only be called when the reference count associated with the * edge goes to zero. */ static void glink_edge_ctx_release(struct rwref_lock *ch_st_lock) { struct glink_core_edge_ctx *ctx = container_of(ch_st_lock, struct glink_core_edge_ctx, edge_ref_lock_lhd1); mutex_lock(&edge_list_lock_lhd0); list_del(&ctx->list_node); mutex_unlock(&edge_list_lock_lhd0); kfree(ctx); } /** * edge_name_to_ctx_create() - lookup a edge by name, create the edge ctx if * it is not found. * @xprt_ctx: Transport to search for a matching edge. * * Return: The edge ctx corresponding to edge of @xprt_ctx. */ static struct glink_core_edge_ctx *edge_name_to_ctx_create( struct glink_core_xprt_ctx *xprt_ctx) { struct glink_core_edge_ctx *edge_ctx; mutex_lock(&edge_list_lock_lhd0); list_for_each_entry(edge_ctx, &edge_list, list_node) { if (!strcmp(edge_ctx->name, xprt_ctx->edge)) { rwref_get(&edge_ctx->edge_ref_lock_lhd1); mutex_unlock(&edge_list_lock_lhd0); return edge_ctx; } } edge_ctx = kzalloc(sizeof(struct glink_core_edge_ctx), GFP_KERNEL); strlcpy(edge_ctx->name, xprt_ctx->edge, GLINK_NAME_SIZE); rwref_lock_init(&edge_ctx->edge_ref_lock_lhd1, glink_edge_ctx_release); mutex_init(&edge_ctx->edge_migration_lock_lhd2); INIT_LIST_HEAD(&edge_ctx->list_node); list_add_tail(&edge_ctx->list_node, &edge_list); mutex_unlock(&edge_list_lock_lhd0); return edge_ctx; } /** * xprt_lcid_to_ch_ctx_get() - lookup a channel by local id * @xprt_ctx: Transport to search for a matching channel. Loading Loading @@ -3440,6 +3534,7 @@ void glink_xprt_ctx_release(struct rwref_lock *xprt_st_lock) xprt_rm_dbgfs.par_name = "xprt"; glink_debugfs_remove_recur(&xprt_rm_dbgfs); GLINK_INFO("%s: xprt debugfs removec\n", __func__); rwref_put(&xprt_ctx->edge_ctx->edge_ref_lock_lhd1); kthread_stop(xprt_ctx->tx_task); xprt_ctx->tx_task = NULL; glink_core_deinit_xprt_qos_cfg(xprt_ctx); Loading Loading @@ -3709,6 +3804,7 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, xprt_ptr->versions_entries = cfg->versions_entries; xprt_ptr->local_version_idx = cfg->versions_entries - 1; xprt_ptr->remote_version_idx = cfg->versions_entries - 1; xprt_ptr->edge_ctx = edge_name_to_ctx_create(xprt_ptr); xprt_ptr->l_features = cfg->versions[cfg->versions_entries - 1].features; if (!if_ptr->poll) Loading Loading @@ -4557,11 +4653,13 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, uint16_t xprt_resp; bool do_migrate; glink_core_migration_edge_lock(if_ptr->glink_core_priv); ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name); if (ctx == NULL) { GLINK_ERR_XPRT(if_ptr->glink_core_priv, "%s: invalid rcid %u received, name '%s'\n", __func__, rcid, name); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4570,6 +4668,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, GLINK_ERR_CH(ctx, "%s: Duplicate remote open for rcid %u, name '%s'\n", __func__, rcid, name); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4591,6 +4690,7 @@ static void glink_core_rx_cmd_ch_remote_open(struct glink_transport_if *if_ptr, if (do_migrate) ch_migrate(NULL, ctx); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); } /** Loading @@ -4604,13 +4704,14 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, uint32_t lcid, uint16_t xprt_resp) { struct channel_ctx *ctx; glink_core_migration_edge_lock(if_ptr->glink_core_priv); ctx = xprt_lcid_to_ch_ctx_get(if_ptr->glink_core_priv, lcid); if (!ctx) { /* unknown LCID received - this shouldn't happen */ GLINK_ERR_XPRT(if_ptr->glink_core_priv, "%s: invalid lcid %u received\n", __func__, (unsigned)lcid); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4619,6 +4720,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, "%s: unexpected open ack receive for lcid. Current state: %u. Thread: %u\n", __func__, ctx->local_open_state, current->pid); rwref_put(&ctx->ch_state_lhb2); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); return; } Loading @@ -4637,6 +4739,7 @@ static void glink_core_rx_cmd_ch_open_ack(struct glink_transport_if *if_ptr, } } rwref_put(&ctx->ch_state_lhb2); glink_core_migration_edge_unlock(if_ptr->glink_core_priv); } /** Loading