Loading drivers/platform/msm/mhi_dev/mhi.c +41 −23 Original line number Diff line number Diff line Loading @@ -71,11 +71,12 @@ static struct mhi_dev *mhi_ctx; static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, unsigned long data); static void mhi_ring_init_cb(void *user_data); static void mhi_update_state_info(uint32_t info); static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info); static int mhi_deinit(struct mhi_dev *mhi); static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify); static int mhi_dev_pcie_notify_event; static void mhi_dev_transfer_completion_cb(void *mreq); static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; /* * mhi_dev_ring_cache_completion_cb () - Call back function called Loading Loading @@ -454,7 +455,7 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, return; } mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); ep_pcie_mask_irq_event(mhi_ctx->phandle, EP_PCIE_INT_EVT_MHI_A7, true); Loading Loading @@ -825,16 +826,14 @@ EXPORT_SYMBOL(mhi_dev_send_ee_event); static void mhi_dev_trigger_cb(void) { struct mhi_dev_ready_cb_info *info; uint32_t state_data; enum mhi_ctrl_info state_data; mutex_lock(&mhi_ctx->mhi_lock); list_for_each_entry(info, &mhi_ctx->client_cb_list, list) if (info->cb) { mhi_ctrl_state_info(&state_data); mhi_ctrl_state_info(info->cb_data.channel, &state_data); info->cb_data.ctrl_info = state_data; info->cb(&info->cb_data); } mutex_unlock(&mhi_ctx->mhi_lock); } int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi) Loading Loading @@ -937,6 +936,8 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, struct mhi_addr host_addr; struct mhi_dev_channel *ch; struct mhi_dev_ring *ring; char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL}; char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL}; ch_id = el->generic.chid; mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n", Loading Loading @@ -1022,6 +1023,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, /* Trigger callback to clients */ mhi_dev_trigger_cb(); mhi_update_state_info(ch_id, MHI_STATE_CONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, connected); break; case MHI_DEV_RING_EL_STOP: if (ch_id >= HW_CHANNEL_BASE) { Loading Loading @@ -1074,6 +1079,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("stop event send failed\n"); mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); } break; case MHI_DEV_RING_EL_RESET: Loading Loading @@ -1146,6 +1155,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) pr_err("Error sending command completion event\n"); mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); } break; default: Loading Loading @@ -1327,7 +1340,7 @@ static int mhi_dev_abort(struct mhi_dev *mhi) } /* Update ctrl node */ mhi_update_state_info(MHI_STATE_DISCONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED); flush_workqueue(mhi->ring_init_wq); flush_workqueue(mhi->pending_ring_wq); Loading Loading @@ -1808,7 +1821,7 @@ int mhi_dev_resume(struct mhi_dev *mhi) mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC); } mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); atomic_set(&mhi->is_suspended, 0); Loading Loading @@ -2369,7 +2382,7 @@ static void mhi_dev_enable(struct work_struct *work) if (mhi_ctx->config_iatu || mhi_ctx->mhi_int) enable_irq(mhi_ctx->mhi_irq); mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED); } static void mhi_ring_init_cb(void *data) Loading Loading @@ -2429,28 +2442,32 @@ int mhi_register_state_cb(void (*mhi_state_cb) } EXPORT_SYMBOL(mhi_register_state_cb); static void mhi_update_state_info(uint32_t info) static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info) { struct mhi_dev_client_cb_reason reason; if (uevent_idx == MHI_DEV_UEVENT_CTRL) mhi_ctx->ctrl_info = info; if (info == MHI_STATE_CONNECTED) return; channel_state_info[uevent_idx].ctrl_info = info; if (uevent_idx == MHI_CLIENT_QMI_OUT || uevent_idx == MHI_CLIENT_QMI_IN) { /* For legacy reasons for QTI client */ reason.reason = MHI_DEV_CTRL_UPDATE; uci_ctrl_update(&reason); } int mhi_ctrl_state_info(uint32_t *info) { if (!info) { pr_err("Invalid info\n"); return -EINVAL; } int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { if (idx == MHI_DEV_UEVENT_CTRL) *info = mhi_ctx->ctrl_info; mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info); else *info = channel_state_info[idx].ctrl_info; mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info); return 0; } Loading Loading @@ -2945,7 +2962,8 @@ static int mhi_dev_probe(struct platform_device *pdev) "Failed to create IPC logging context\n"); } mhi_uci_init(); mhi_update_state_info(MHI_STATE_CONFIGURED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED); } INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event); Loading drivers/platform/msm/mhi_dev/mhi.h +15 −2 Original line number Diff line number Diff line Loading @@ -275,7 +275,7 @@ struct mhi_config { #define MHI_ENV_VALUE 2 #define MHI_MASK_ROWS_CH_EV_DB 4 #define TRB_MAX_DATA_SIZE 8192 #define MHI_CTRL_STATE 25 #define MHI_CTRL_STATE 100 #define IPA_DMA_SYNC 1 #define IPA_DMA_ASYNC 0 Loading Loading @@ -607,6 +607,8 @@ struct mhi_dev { bool mhi_int; /* Registered client callback list */ struct list_head client_cb_list; struct kobj_uevent_env kobj_env; }; struct mhi_req { Loading Loading @@ -712,6 +714,14 @@ enum mhi_client_channel { MHI_MAX_CHANNELS = 102, }; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */ #define MHI_DEV_UEVENT_CTRL 0 struct mhi_dev_uevent_info { enum mhi_client_channel channel; enum mhi_ctrl_info ctrl_info; }; struct mhi_dev_iov { void *addr; uint32_t buf_size; Loading Loading @@ -1251,6 +1261,9 @@ void mhi_dev_notify_a7_event(struct mhi_dev *mhi); /** * mhi_ctrl_state_info() - Provide MHI state info * @idx: Channel number idx. Look at channel_state_info and * pass the index for the corresponding channel. * @info: Return the control info. * MHI_STATE=CONFIGURED - MHI device is present but not ready * for data traffic. * MHI_STATE=CONNECTED - MHI device is ready for data transfer. Loading @@ -1258,7 +1271,7 @@ void mhi_dev_notify_a7_event(struct mhi_dev *mhi); * exposes device nodes for the supported MHI software * channels. */ int mhi_ctrl_state_info(uint32_t *info); int mhi_ctrl_state_info(uint32_t idx, uint32_t *info); /** * uci_ctrl_update() - Update UCI once TRE's are available for clients to Loading drivers/platform/msm/mhi_dev/mhi_uci.c +58 −1 Original line number Diff line number Diff line Loading @@ -441,6 +441,61 @@ static int mhi_uci_client_release(struct inode *mhi_inode, return rc; } static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) { switch (info) { case MHI_STATE_CONNECTED: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "CONNECTED"); break; case MHI_STATE_DISCONNECTED: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "DISCONNECTED"); break; case MHI_STATE_CONFIGURED: default: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "CONFIGURED"); break; } } static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env) { int rc, nbytes = 0; uint32_t info = 0; char buf[MHI_CTRL_STATE]; rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info); if (rc) { pr_err("Failed to obtain MHI_STATE\n"); return -EINVAL; } mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_STATE=%s", buf); rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); if (rc) { pr_err("Failed to obtain channel 14 state\n"); return -EINVAL; } nbytes = 0; mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf); rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info); if (rc) { pr_err("Failed to obtain channel 12 state\n"); return -EINVAL; } nbytes = 0; mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf); return 0; } static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *user_buf, size_t count, loff_t *offp) Loading @@ -455,7 +510,7 @@ static ssize_t mhi_uci_ctrl_client_read(struct file *file, return -EINVAL; uci_ctrl_handle = file->private_data; rc = mhi_ctrl_state_info(&info); rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); if (rc) return -EINVAL; Loading Loading @@ -993,6 +1048,8 @@ int mhi_uci_init(void) uci_ctxt.cdev_ctrl = NULL; } uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent; return 0; failed_char_add: Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +41 −23 Original line number Diff line number Diff line Loading @@ -71,11 +71,12 @@ static struct mhi_dev *mhi_ctx; static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, unsigned long data); static void mhi_ring_init_cb(void *user_data); static void mhi_update_state_info(uint32_t info); static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info); static int mhi_deinit(struct mhi_dev *mhi); static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify); static int mhi_dev_pcie_notify_event; static void mhi_dev_transfer_completion_cb(void *mreq); static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS]; /* * mhi_dev_ring_cache_completion_cb () - Call back function called Loading Loading @@ -454,7 +455,7 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, return; } mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); ep_pcie_mask_irq_event(mhi_ctx->phandle, EP_PCIE_INT_EVT_MHI_A7, true); Loading Loading @@ -825,16 +826,14 @@ EXPORT_SYMBOL(mhi_dev_send_ee_event); static void mhi_dev_trigger_cb(void) { struct mhi_dev_ready_cb_info *info; uint32_t state_data; enum mhi_ctrl_info state_data; mutex_lock(&mhi_ctx->mhi_lock); list_for_each_entry(info, &mhi_ctx->client_cb_list, list) if (info->cb) { mhi_ctrl_state_info(&state_data); mhi_ctrl_state_info(info->cb_data.channel, &state_data); info->cb_data.ctrl_info = state_data; info->cb(&info->cb_data); } mutex_unlock(&mhi_ctx->mhi_lock); } int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi) Loading Loading @@ -937,6 +936,8 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, struct mhi_addr host_addr; struct mhi_dev_channel *ch; struct mhi_dev_ring *ring; char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL}; char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL}; ch_id = el->generic.chid; mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n", Loading Loading @@ -1022,6 +1023,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, /* Trigger callback to clients */ mhi_dev_trigger_cb(); mhi_update_state_info(ch_id, MHI_STATE_CONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, connected); break; case MHI_DEV_RING_EL_STOP: if (ch_id >= HW_CHANNEL_BASE) { Loading Loading @@ -1074,6 +1079,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, pr_err("stop event send failed\n"); mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); } break; case MHI_DEV_RING_EL_RESET: Loading Loading @@ -1146,6 +1155,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, if (rc) pr_err("Error sending command completion event\n"); mutex_unlock(&ch->ch_lock); mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED); if (ch_id == MHI_CLIENT_MBIM_OUT) kobject_uevent_env(&mhi_ctx->dev->kobj, KOBJ_CHANGE, disconnected); } break; default: Loading Loading @@ -1327,7 +1340,7 @@ static int mhi_dev_abort(struct mhi_dev *mhi) } /* Update ctrl node */ mhi_update_state_info(MHI_STATE_DISCONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED); flush_workqueue(mhi->ring_init_wq); flush_workqueue(mhi->pending_ring_wq); Loading Loading @@ -1808,7 +1821,7 @@ int mhi_dev_resume(struct mhi_dev *mhi) mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC); } mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED); atomic_set(&mhi->is_suspended, 0); Loading Loading @@ -2369,7 +2382,7 @@ static void mhi_dev_enable(struct work_struct *work) if (mhi_ctx->config_iatu || mhi_ctx->mhi_int) enable_irq(mhi_ctx->mhi_irq); mhi_update_state_info(MHI_STATE_CONNECTED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED); } static void mhi_ring_init_cb(void *data) Loading Loading @@ -2429,28 +2442,32 @@ int mhi_register_state_cb(void (*mhi_state_cb) } EXPORT_SYMBOL(mhi_register_state_cb); static void mhi_update_state_info(uint32_t info) static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info) { struct mhi_dev_client_cb_reason reason; if (uevent_idx == MHI_DEV_UEVENT_CTRL) mhi_ctx->ctrl_info = info; if (info == MHI_STATE_CONNECTED) return; channel_state_info[uevent_idx].ctrl_info = info; if (uevent_idx == MHI_CLIENT_QMI_OUT || uevent_idx == MHI_CLIENT_QMI_IN) { /* For legacy reasons for QTI client */ reason.reason = MHI_DEV_CTRL_UPDATE; uci_ctrl_update(&reason); } int mhi_ctrl_state_info(uint32_t *info) { if (!info) { pr_err("Invalid info\n"); return -EINVAL; } int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { if (idx == MHI_DEV_UEVENT_CTRL) *info = mhi_ctx->ctrl_info; mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info); else *info = channel_state_info[idx].ctrl_info; mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info); return 0; } Loading Loading @@ -2945,7 +2962,8 @@ static int mhi_dev_probe(struct platform_device *pdev) "Failed to create IPC logging context\n"); } mhi_uci_init(); mhi_update_state_info(MHI_STATE_CONFIGURED); mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED); } INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event); Loading
drivers/platform/msm/mhi_dev/mhi.h +15 −2 Original line number Diff line number Diff line Loading @@ -275,7 +275,7 @@ struct mhi_config { #define MHI_ENV_VALUE 2 #define MHI_MASK_ROWS_CH_EV_DB 4 #define TRB_MAX_DATA_SIZE 8192 #define MHI_CTRL_STATE 25 #define MHI_CTRL_STATE 100 #define IPA_DMA_SYNC 1 #define IPA_DMA_ASYNC 0 Loading Loading @@ -607,6 +607,8 @@ struct mhi_dev { bool mhi_int; /* Registered client callback list */ struct list_head client_cb_list; struct kobj_uevent_env kobj_env; }; struct mhi_req { Loading Loading @@ -712,6 +714,14 @@ enum mhi_client_channel { MHI_MAX_CHANNELS = 102, }; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */ #define MHI_DEV_UEVENT_CTRL 0 struct mhi_dev_uevent_info { enum mhi_client_channel channel; enum mhi_ctrl_info ctrl_info; }; struct mhi_dev_iov { void *addr; uint32_t buf_size; Loading Loading @@ -1251,6 +1261,9 @@ void mhi_dev_notify_a7_event(struct mhi_dev *mhi); /** * mhi_ctrl_state_info() - Provide MHI state info * @idx: Channel number idx. Look at channel_state_info and * pass the index for the corresponding channel. * @info: Return the control info. * MHI_STATE=CONFIGURED - MHI device is present but not ready * for data traffic. * MHI_STATE=CONNECTED - MHI device is ready for data transfer. Loading @@ -1258,7 +1271,7 @@ void mhi_dev_notify_a7_event(struct mhi_dev *mhi); * exposes device nodes for the supported MHI software * channels. */ int mhi_ctrl_state_info(uint32_t *info); int mhi_ctrl_state_info(uint32_t idx, uint32_t *info); /** * uci_ctrl_update() - Update UCI once TRE's are available for clients to Loading
drivers/platform/msm/mhi_dev/mhi_uci.c +58 −1 Original line number Diff line number Diff line Loading @@ -441,6 +441,61 @@ static int mhi_uci_client_release(struct inode *mhi_inode, return rc; } static void mhi_parse_state(char *buf, int *nbytes, uint32_t info) { switch (info) { case MHI_STATE_CONNECTED: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "CONNECTED"); break; case MHI_STATE_DISCONNECTED: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "DISCONNECTED"); break; case MHI_STATE_CONFIGURED: default: *nbytes = scnprintf(buf, MHI_CTRL_STATE, "CONFIGURED"); break; } } static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env) { int rc, nbytes = 0; uint32_t info = 0; char buf[MHI_CTRL_STATE]; rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info); if (rc) { pr_err("Failed to obtain MHI_STATE\n"); return -EINVAL; } mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_STATE=%s", buf); rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); if (rc) { pr_err("Failed to obtain channel 14 state\n"); return -EINVAL; } nbytes = 0; mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf); rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info); if (rc) { pr_err("Failed to obtain channel 12 state\n"); return -EINVAL; } nbytes = 0; mhi_parse_state(buf, &nbytes, info); add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf); return 0; } static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *user_buf, size_t count, loff_t *offp) Loading @@ -455,7 +510,7 @@ static ssize_t mhi_uci_ctrl_client_read(struct file *file, return -EINVAL; uci_ctrl_handle = file->private_data; rc = mhi_ctrl_state_info(&info); rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info); if (rc) return -EINVAL; Loading Loading @@ -993,6 +1048,8 @@ int mhi_uci_init(void) uci_ctxt.cdev_ctrl = NULL; } uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent; return 0; failed_char_add: Loading