Loading drivers/platform/msm/mhi_dev/mhi.c +33 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ 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); void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer) { Loading Loading @@ -383,6 +384,8 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, pr_err("Failed to enable command db\n"); return; } mhi_update_state_info(MHI_STATE_CONNECTED); break; case IPA_MHI_EVENT_DATA_AVAILABLE: rc = mhi_dev_notify_sm_event(MHI_DEV_EVENT_HW_ACC_WAKEUP); Loading Loading @@ -1360,6 +1363,7 @@ int mhi_dev_suspend(struct mhi_dev *mhi) mhi_dev_write_to_host(mhi, &data_transfer); } mhi_update_state_info(MHI_STATE_DISCONNECTED); atomic_set(&mhi->mhi_dev_wake, 0); pm_relax(mhi->dev); Loading Loading @@ -1398,6 +1402,7 @@ int mhi_dev_resume(struct mhi_dev *mhi) /* update the channel state in the host */ mhi_dev_write_to_host(mhi, &data_transfer); } mhi_update_state_info(MHI_STATE_CONNECTED); atomic_set(&mhi->is_suspended, 0); Loading Loading @@ -1843,7 +1848,6 @@ static void mhi_dev_enable(struct work_struct *work) return; } mhi_uci_init(); /*Enable MHI dev network stack Interface*/ rc = mhi_dev_net_interface_init(); if (rc) Loading Loading @@ -1911,6 +1915,8 @@ static void mhi_dev_enable(struct work_struct *work) if (mhi_ctx->config_iatu) enable_irq(mhi_ctx->mhi_irq); mhi_update_state_info(MHI_STATE_CONNECTED); } static void mhi_ring_init_cb(void *data) Loading @@ -1925,6 +1931,30 @@ 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) { struct mhi_dev_client_cb_reason reason; mhi_ctx->ctrl_info = info; 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; } *info = mhi_ctx->ctrl_info; mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info); return 0; } EXPORT_SYMBOL(mhi_ctrl_state_info); static int get_device_tree_data(struct platform_device *pdev) { struct mhi_dev *mhi; Loading Loading @@ -2238,6 +2268,8 @@ static int mhi_dev_probe(struct platform_device *pdev) pr_err("Error reading MHI Dev DT\n"); return rc; } mhi_uci_init(); mhi_update_state_info(MHI_STATE_CONFIGURED); } mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); Loading drivers/platform/msm/mhi_dev/mhi.h +16 −0 Original line number Diff line number Diff line Loading @@ -273,6 +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 /* Possible ring element types */ union mhi_dev_ring_element_type { Loading Loading @@ -350,6 +351,13 @@ enum mhi_dev_ch_operation { MHI_DEV_POLL, }; enum mhi_ctrl_info { MHI_STATE_CONFIGURED = 0, MHI_STATE_CONNECTED = 1, MHI_STATE_DISCONNECTED = 2, MHI_STATE_INVAL, }; struct mhi_dev_channel; struct mhi_dev_ring { Loading Loading @@ -395,6 +403,7 @@ static inline void mhi_dev_ring_inc_index(struct mhi_dev_ring *ring, enum cb_reason { MHI_DEV_TRE_AVAILABLE = 0, MHI_DEV_CTRL_UPDATE, }; struct mhi_dev_client_cb_reason { Loading Loading @@ -545,6 +554,9 @@ struct mhi_dev { /* iATU is required to map control and data region */ bool config_iatu; /* MHI state info */ enum mhi_ctrl_info ctrl_info; }; enum mhi_msg_level { Loading Loading @@ -1143,4 +1155,8 @@ 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); void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason); #endif /* _MHI_H_ */ drivers/platform/msm/mhi_dev/mhi_uci.c +156 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,12 @@ struct chan_attr { u32 uci_ownership; }; struct uci_ctrl { wait_queue_head_t ctrl_wq; struct mhi_uci_ctxt_t *uci_ctxt; atomic_t ctrl_data_update; }; struct uci_client { u32 client_index; /* write channel - always odd*/ Loading Loading @@ -100,9 +106,13 @@ struct uci_client { struct mhi_uci_ctxt_t { struct chan_attr chan_attrib[MHI_MAX_SOFTWARE_CHANNELS]; struct uci_client client_handles[MHI_SOFTWARE_CLIENT_LIMIT]; struct uci_ctrl ctrl_handle; void (*event_notifier)(struct mhi_dev_client_cb_reason *cb); dev_t start_ctrl_nr; struct cdev cdev[MHI_MAX_SOFTWARE_CHANNELS]; dev_t ctrl_nr; struct cdev cdev_ctrl; struct device *dev; struct class *mhi_uci_class; atomic_t mhi_disabled; atomic_t mhi_enable_notif_wq_active; Loading @@ -129,12 +139,16 @@ MODULE_PARM_DESC(mhi_uci_ipc_log_lvl, "ipc dbg lvl"); static ssize_t mhi_uci_client_read(struct file *file, char __user *buf, size_t count, loff_t *offp); static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *buf, size_t count, loff_t *offp); static ssize_t mhi_uci_client_write(struct file *file, const char __user *buf, size_t count, loff_t *offp); static int mhi_uci_client_open(struct inode *mhi_inode, struct file*); static int mhi_uci_ctrl_open(struct inode *mhi_inode, struct file*); static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle); static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait); static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait); static struct mhi_uci_ctxt_t uci_ctxt; static int mhi_init_read_chan(struct uci_client *client_handle, Loading Loading @@ -215,6 +229,30 @@ error_memcpy: return data_inserted_so_far; } static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; struct uci_ctrl *uci_ctrl_handle; uci_ctrl_handle = file->private_data; if (!uci_ctrl_handle) return -ENODEV; poll_wait(file, &uci_ctrl_handle->ctrl_wq, wait); if (!atomic_read(&uci_ctxt.mhi_disabled) && atomic_read(&uci_ctrl_handle->ctrl_data_update)) { uci_log(UCI_DBG_VERBOSE, "Client can read ctrl_state"); mask |= POLLIN | POLLRDNORM; } uci_log(UCI_DBG_VERBOSE, "Client attempted to poll ctrl returning mask 0x%x\n", mask); return mask; } static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; Loading Loading @@ -297,6 +335,22 @@ handle_not_rdy_err: return rc; } static int mhi_uci_ctrl_open(struct inode *inode, struct file *file_handle) { struct uci_ctrl *uci_ctrl_handle; uci_log(UCI_DBG_DBG, "Client opened ctrl file device node\n"); uci_ctrl_handle = &uci_ctxt.ctrl_handle; if (!uci_ctrl_handle) return -EINVAL; file_handle->private_data = uci_ctrl_handle; return 0; } static int mhi_uci_client_open(struct inode *mhi_inode, struct file *file_handle) { Loading Loading @@ -381,6 +435,53 @@ static int mhi_uci_client_release(struct inode *mhi_inode, return rc; } static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *user_buf, size_t count, loff_t *offp) { uint32_t rc = 0, info; int nbytes, size; char buf[MHI_CTRL_STATE]; struct uci_ctrl *uci_ctrl_handle = NULL; if (!file || !user_buf || !count || (count < MHI_CTRL_STATE) || !file->private_data) return -EINVAL; uci_ctrl_handle = file->private_data; rc = mhi_ctrl_state_info(&info); if (rc) return -EINVAL; switch (info) { case MHI_STATE_CONFIGURED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=CONFIGURED"); break; case MHI_STATE_CONNECTED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=CONNECTED"); break; case MHI_STATE_DISCONNECTED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=DISCONNECTED"); break; default: pr_err("invalid info:%d\n", info); return -EINVAL; } size = simple_read_from_buffer(user_buf, count, offp, buf, nbytes); atomic_set(&uci_ctrl_handle->ctrl_data_update, 0); if (size == 0) *offp = 0; return size; } static ssize_t mhi_uci_client_read(struct file *file, char __user *buf, size_t uspace_buf_size, loff_t *bytes_pending) { Loading Loading @@ -636,6 +737,23 @@ static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt) return 0; } void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason) { struct uci_ctrl *uci_ctrl_handle = NULL; if (reason->reason == MHI_DEV_CTRL_UPDATE) { uci_ctrl_handle = &uci_ctxt.ctrl_handle; if (!uci_ctrl_handle) { pr_err("Invalid uci ctrl handle\n"); return; } uci_log(UCI_DBG_DBG, "received state change update\n"); wake_up(&uci_ctrl_handle->ctrl_wq); atomic_set(&uci_ctrl_handle->ctrl_data_update, 1); } } EXPORT_SYMBOL(uci_ctrl_update); static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason) { Loading Loading @@ -720,6 +838,12 @@ static long mhi_uci_client_ioctl(struct file *file, unsigned cmd, return rc; } static const struct file_operations mhi_uci_ctrl_client_fops = { .open = mhi_uci_ctrl_open, .read = mhi_uci_ctrl_client_read, .poll = mhi_uci_ctrl_poll, }; static const struct file_operations mhi_uci_client_fops = { .read = mhi_uci_client_read, .write = mhi_uci_client_write, Loading Loading @@ -772,16 +896,25 @@ int mhi_uci_init(void) } } } init_waitqueue_head(&uci_ctxt.ctrl_handle.ctrl_wq); uci_log(UCI_DBG_INFO, "Allocating char devices.\n"); r = alloc_chrdev_region(&uci_ctxt.start_ctrl_nr, 0, MHI_MAX_SOFTWARE_CHANNELS, DEVICE_NAME); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to alloc char devs, ret 0x%x\n", r); goto failed_char_alloc; } r = alloc_chrdev_region(&uci_ctxt.ctrl_nr, 0, 1, DEVICE_NAME); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to alloc char ctrl devs, 0x%x\n", r); goto failed_char_alloc; } uci_log(UCI_DBG_INFO, "Creating class\n"); uci_ctxt.mhi_uci_class = class_create(THIS_MODULE, DEVICE_NAME); Loading @@ -805,12 +938,12 @@ int mhi_uci_init(void) i, r); goto failed_char_add; } uci_ctxt.client_handles[i].dev = device_create(uci_ctxt.mhi_uci_class, NULL, uci_ctxt.start_ctrl_nr + i, NULL, DEVICE_NAME "_pipe_%d", i * 2); if (IS_ERR(uci_ctxt.client_handles[i].dev)) { uci_log(UCI_DBG_ERROR, "Failed to add cdev %d\n", i); Loading @@ -819,6 +952,27 @@ int mhi_uci_init(void) } } } /* Control node */ cdev_init(&uci_ctxt.cdev_ctrl, &mhi_uci_ctrl_client_fops); uci_ctxt.cdev_ctrl.owner = THIS_MODULE; r = cdev_add(&uci_ctxt.cdev_ctrl, uci_ctxt.ctrl_nr , 1); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to add ctrl cdev %d, ret 0x%x\n", i, r); goto failed_char_add; } uci_ctxt.dev = device_create(uci_ctxt.mhi_uci_class, NULL, uci_ctxt.ctrl_nr, NULL, DEVICE_NAME "_ctrl"); if (IS_ERR(uci_ctxt.dev)) { uci_log(UCI_DBG_ERROR, "Failed to add ctrl cdev %d\n", i); cdev_del(&uci_ctxt.cdev_ctrl); } return 0; failed_char_add: Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +33 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ 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); void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer) { Loading Loading @@ -383,6 +384,8 @@ static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event, pr_err("Failed to enable command db\n"); return; } mhi_update_state_info(MHI_STATE_CONNECTED); break; case IPA_MHI_EVENT_DATA_AVAILABLE: rc = mhi_dev_notify_sm_event(MHI_DEV_EVENT_HW_ACC_WAKEUP); Loading Loading @@ -1360,6 +1363,7 @@ int mhi_dev_suspend(struct mhi_dev *mhi) mhi_dev_write_to_host(mhi, &data_transfer); } mhi_update_state_info(MHI_STATE_DISCONNECTED); atomic_set(&mhi->mhi_dev_wake, 0); pm_relax(mhi->dev); Loading Loading @@ -1398,6 +1402,7 @@ int mhi_dev_resume(struct mhi_dev *mhi) /* update the channel state in the host */ mhi_dev_write_to_host(mhi, &data_transfer); } mhi_update_state_info(MHI_STATE_CONNECTED); atomic_set(&mhi->is_suspended, 0); Loading Loading @@ -1843,7 +1848,6 @@ static void mhi_dev_enable(struct work_struct *work) return; } mhi_uci_init(); /*Enable MHI dev network stack Interface*/ rc = mhi_dev_net_interface_init(); if (rc) Loading Loading @@ -1911,6 +1915,8 @@ static void mhi_dev_enable(struct work_struct *work) if (mhi_ctx->config_iatu) enable_irq(mhi_ctx->mhi_irq); mhi_update_state_info(MHI_STATE_CONNECTED); } static void mhi_ring_init_cb(void *data) Loading @@ -1925,6 +1931,30 @@ 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) { struct mhi_dev_client_cb_reason reason; mhi_ctx->ctrl_info = info; 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; } *info = mhi_ctx->ctrl_info; mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info); return 0; } EXPORT_SYMBOL(mhi_ctrl_state_info); static int get_device_tree_data(struct platform_device *pdev) { struct mhi_dev *mhi; Loading Loading @@ -2238,6 +2268,8 @@ static int mhi_dev_probe(struct platform_device *pdev) pr_err("Error reading MHI Dev DT\n"); return rc; } mhi_uci_init(); mhi_update_state_info(MHI_STATE_CONFIGURED); } mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); Loading
drivers/platform/msm/mhi_dev/mhi.h +16 −0 Original line number Diff line number Diff line Loading @@ -273,6 +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 /* Possible ring element types */ union mhi_dev_ring_element_type { Loading Loading @@ -350,6 +351,13 @@ enum mhi_dev_ch_operation { MHI_DEV_POLL, }; enum mhi_ctrl_info { MHI_STATE_CONFIGURED = 0, MHI_STATE_CONNECTED = 1, MHI_STATE_DISCONNECTED = 2, MHI_STATE_INVAL, }; struct mhi_dev_channel; struct mhi_dev_ring { Loading Loading @@ -395,6 +403,7 @@ static inline void mhi_dev_ring_inc_index(struct mhi_dev_ring *ring, enum cb_reason { MHI_DEV_TRE_AVAILABLE = 0, MHI_DEV_CTRL_UPDATE, }; struct mhi_dev_client_cb_reason { Loading Loading @@ -545,6 +554,9 @@ struct mhi_dev { /* iATU is required to map control and data region */ bool config_iatu; /* MHI state info */ enum mhi_ctrl_info ctrl_info; }; enum mhi_msg_level { Loading Loading @@ -1143,4 +1155,8 @@ 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); void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason); #endif /* _MHI_H_ */
drivers/platform/msm/mhi_dev/mhi_uci.c +156 −2 Original line number Diff line number Diff line Loading @@ -73,6 +73,12 @@ struct chan_attr { u32 uci_ownership; }; struct uci_ctrl { wait_queue_head_t ctrl_wq; struct mhi_uci_ctxt_t *uci_ctxt; atomic_t ctrl_data_update; }; struct uci_client { u32 client_index; /* write channel - always odd*/ Loading Loading @@ -100,9 +106,13 @@ struct uci_client { struct mhi_uci_ctxt_t { struct chan_attr chan_attrib[MHI_MAX_SOFTWARE_CHANNELS]; struct uci_client client_handles[MHI_SOFTWARE_CLIENT_LIMIT]; struct uci_ctrl ctrl_handle; void (*event_notifier)(struct mhi_dev_client_cb_reason *cb); dev_t start_ctrl_nr; struct cdev cdev[MHI_MAX_SOFTWARE_CHANNELS]; dev_t ctrl_nr; struct cdev cdev_ctrl; struct device *dev; struct class *mhi_uci_class; atomic_t mhi_disabled; atomic_t mhi_enable_notif_wq_active; Loading @@ -129,12 +139,16 @@ MODULE_PARM_DESC(mhi_uci_ipc_log_lvl, "ipc dbg lvl"); static ssize_t mhi_uci_client_read(struct file *file, char __user *buf, size_t count, loff_t *offp); static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *buf, size_t count, loff_t *offp); static ssize_t mhi_uci_client_write(struct file *file, const char __user *buf, size_t count, loff_t *offp); static int mhi_uci_client_open(struct inode *mhi_inode, struct file*); static int mhi_uci_ctrl_open(struct inode *mhi_inode, struct file*); static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle); static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait); static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait); static struct mhi_uci_ctxt_t uci_ctxt; static int mhi_init_read_chan(struct uci_client *client_handle, Loading Loading @@ -215,6 +229,30 @@ error_memcpy: return data_inserted_so_far; } static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; struct uci_ctrl *uci_ctrl_handle; uci_ctrl_handle = file->private_data; if (!uci_ctrl_handle) return -ENODEV; poll_wait(file, &uci_ctrl_handle->ctrl_wq, wait); if (!atomic_read(&uci_ctxt.mhi_disabled) && atomic_read(&uci_ctrl_handle->ctrl_data_update)) { uci_log(UCI_DBG_VERBOSE, "Client can read ctrl_state"); mask |= POLLIN | POLLRDNORM; } uci_log(UCI_DBG_VERBOSE, "Client attempted to poll ctrl returning mask 0x%x\n", mask); return mask; } static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait) { unsigned int mask = 0; Loading Loading @@ -297,6 +335,22 @@ handle_not_rdy_err: return rc; } static int mhi_uci_ctrl_open(struct inode *inode, struct file *file_handle) { struct uci_ctrl *uci_ctrl_handle; uci_log(UCI_DBG_DBG, "Client opened ctrl file device node\n"); uci_ctrl_handle = &uci_ctxt.ctrl_handle; if (!uci_ctrl_handle) return -EINVAL; file_handle->private_data = uci_ctrl_handle; return 0; } static int mhi_uci_client_open(struct inode *mhi_inode, struct file *file_handle) { Loading Loading @@ -381,6 +435,53 @@ static int mhi_uci_client_release(struct inode *mhi_inode, return rc; } static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *user_buf, size_t count, loff_t *offp) { uint32_t rc = 0, info; int nbytes, size; char buf[MHI_CTRL_STATE]; struct uci_ctrl *uci_ctrl_handle = NULL; if (!file || !user_buf || !count || (count < MHI_CTRL_STATE) || !file->private_data) return -EINVAL; uci_ctrl_handle = file->private_data; rc = mhi_ctrl_state_info(&info); if (rc) return -EINVAL; switch (info) { case MHI_STATE_CONFIGURED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=CONFIGURED"); break; case MHI_STATE_CONNECTED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=CONNECTED"); break; case MHI_STATE_DISCONNECTED: nbytes = scnprintf(buf, sizeof(buf), "MHI_STATE=DISCONNECTED"); break; default: pr_err("invalid info:%d\n", info); return -EINVAL; } size = simple_read_from_buffer(user_buf, count, offp, buf, nbytes); atomic_set(&uci_ctrl_handle->ctrl_data_update, 0); if (size == 0) *offp = 0; return size; } static ssize_t mhi_uci_client_read(struct file *file, char __user *buf, size_t uspace_buf_size, loff_t *bytes_pending) { Loading Loading @@ -636,6 +737,23 @@ static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt) return 0; } void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason) { struct uci_ctrl *uci_ctrl_handle = NULL; if (reason->reason == MHI_DEV_CTRL_UPDATE) { uci_ctrl_handle = &uci_ctxt.ctrl_handle; if (!uci_ctrl_handle) { pr_err("Invalid uci ctrl handle\n"); return; } uci_log(UCI_DBG_DBG, "received state change update\n"); wake_up(&uci_ctrl_handle->ctrl_wq); atomic_set(&uci_ctrl_handle->ctrl_data_update, 1); } } EXPORT_SYMBOL(uci_ctrl_update); static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason) { Loading Loading @@ -720,6 +838,12 @@ static long mhi_uci_client_ioctl(struct file *file, unsigned cmd, return rc; } static const struct file_operations mhi_uci_ctrl_client_fops = { .open = mhi_uci_ctrl_open, .read = mhi_uci_ctrl_client_read, .poll = mhi_uci_ctrl_poll, }; static const struct file_operations mhi_uci_client_fops = { .read = mhi_uci_client_read, .write = mhi_uci_client_write, Loading Loading @@ -772,16 +896,25 @@ int mhi_uci_init(void) } } } init_waitqueue_head(&uci_ctxt.ctrl_handle.ctrl_wq); uci_log(UCI_DBG_INFO, "Allocating char devices.\n"); r = alloc_chrdev_region(&uci_ctxt.start_ctrl_nr, 0, MHI_MAX_SOFTWARE_CHANNELS, DEVICE_NAME); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to alloc char devs, ret 0x%x\n", r); goto failed_char_alloc; } r = alloc_chrdev_region(&uci_ctxt.ctrl_nr, 0, 1, DEVICE_NAME); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to alloc char ctrl devs, 0x%x\n", r); goto failed_char_alloc; } uci_log(UCI_DBG_INFO, "Creating class\n"); uci_ctxt.mhi_uci_class = class_create(THIS_MODULE, DEVICE_NAME); Loading @@ -805,12 +938,12 @@ int mhi_uci_init(void) i, r); goto failed_char_add; } uci_ctxt.client_handles[i].dev = device_create(uci_ctxt.mhi_uci_class, NULL, uci_ctxt.start_ctrl_nr + i, NULL, DEVICE_NAME "_pipe_%d", i * 2); if (IS_ERR(uci_ctxt.client_handles[i].dev)) { uci_log(UCI_DBG_ERROR, "Failed to add cdev %d\n", i); Loading @@ -819,6 +952,27 @@ int mhi_uci_init(void) } } } /* Control node */ cdev_init(&uci_ctxt.cdev_ctrl, &mhi_uci_ctrl_client_fops); uci_ctxt.cdev_ctrl.owner = THIS_MODULE; r = cdev_add(&uci_ctxt.cdev_ctrl, uci_ctxt.ctrl_nr , 1); if (IS_ERR_VALUE(r)) { uci_log(UCI_DBG_ERROR, "Failed to add ctrl cdev %d, ret 0x%x\n", i, r); goto failed_char_add; } uci_ctxt.dev = device_create(uci_ctxt.mhi_uci_class, NULL, uci_ctxt.ctrl_nr, NULL, DEVICE_NAME "_ctrl"); if (IS_ERR(uci_ctxt.dev)) { uci_log(UCI_DBG_ERROR, "Failed to add ctrl cdev %d\n", i); cdev_del(&uci_ctxt.cdev_ctrl); } return 0; failed_char_add: Loading