Loading drivers/platform/msm/mhi_dev/mhi.c +42 −14 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -72,11 +72,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 @@ -466,7 +467,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 @@ -927,6 +928,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 @@ -992,6 +995,10 @@ send_start_completion_event: if (rc) pr_err("Error sending command completion event\n"); 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 @@ -1046,6 +1053,10 @@ send_start_completion_event: 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 @@ -1119,6 +1130,10 @@ send_start_completion_event: 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 @@ -1300,7 +1315,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 @@ -1781,7 +1796,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 @@ -2338,7 +2353,8 @@ 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 @@ -2353,25 +2369,36 @@ static void mhi_ring_init_cb(void *data) queue_work(mhi->ring_init_wq, &mhi->ring_init_cb_work); } 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; 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) int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { if (!info) { pr_err("Invalid info\n"); return -EINVAL; } 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 @@ -2866,7 +2893,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 +25 −3 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -273,7 +273,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 @@ -603,6 +603,8 @@ struct mhi_dev { /*Register for interrupt*/ bool mhi_int; struct kobj_uevent_env kobj_env; }; struct mhi_req { Loading Loading @@ -708,6 +710,14 @@ enum mhi_client_channel { MHI_MAX_CHANNELS = 102, }; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 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 @@ -1221,7 +1231,19 @@ int mhi_dev_net_interface_init(void); void mhi_dev_notify_a7_event(struct mhi_dev *mhi); int mhi_ctrl_state_info(uint32_t *info); /** * 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. * MHI_STATE=DISCONNECTED - MHI device has its pipes suspended. * exposes device nodes for the supported MHI software * channels. */ int mhi_ctrl_state_info(uint32_t idx, uint32_t *info); void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason); Loading drivers/platform/msm/mhi_dev/mhi_uci.c +59 −2 Original line number Diff line number Diff line /* Copyright (c) 2015,2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading 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 @@ -983,6 +1038,8 @@ int mhi_uci_init(void) cdev_del(&uci_ctxt.cdev_ctrl); } uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent; return 0; failed_char_add: Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +42 −14 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -72,11 +72,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 @@ -466,7 +467,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 @@ -927,6 +928,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 @@ -992,6 +995,10 @@ send_start_completion_event: if (rc) pr_err("Error sending command completion event\n"); 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 @@ -1046,6 +1053,10 @@ send_start_completion_event: 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 @@ -1119,6 +1130,10 @@ send_start_completion_event: 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 @@ -1300,7 +1315,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 @@ -1781,7 +1796,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 @@ -2338,7 +2353,8 @@ 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 @@ -2353,25 +2369,36 @@ static void mhi_ring_init_cb(void *data) queue_work(mhi->ring_init_wq, &mhi->ring_init_cb_work); } 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; 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) int mhi_ctrl_state_info(uint32_t idx, uint32_t *info) { if (!info) { pr_err("Invalid info\n"); return -EINVAL; } 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 @@ -2866,7 +2893,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 +25 −3 Original line number Diff line number Diff line /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -273,7 +273,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 @@ -603,6 +603,8 @@ struct mhi_dev { /*Register for interrupt*/ bool mhi_int; struct kobj_uevent_env kobj_env; }; struct mhi_req { Loading Loading @@ -708,6 +710,14 @@ enum mhi_client_channel { MHI_MAX_CHANNELS = 102, }; /* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 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 @@ -1221,7 +1231,19 @@ int mhi_dev_net_interface_init(void); void mhi_dev_notify_a7_event(struct mhi_dev *mhi); int mhi_ctrl_state_info(uint32_t *info); /** * 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. * MHI_STATE=DISCONNECTED - MHI device has its pipes suspended. * exposes device nodes for the supported MHI software * channels. */ int mhi_ctrl_state_info(uint32_t idx, uint32_t *info); void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason); Loading
drivers/platform/msm/mhi_dev/mhi_uci.c +59 −2 Original line number Diff line number Diff line /* Copyright (c) 2015,2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015,2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading 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 @@ -983,6 +1038,8 @@ int mhi_uci_init(void) cdev_del(&uci_ctxt.cdev_ctrl); } uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent; return 0; failed_char_add: Loading