Loading drivers/char/diag/diag_debugfs.c +2 −4 Original line number Diff line number Diff line Loading @@ -440,8 +440,7 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf, "write count: %lu\n" "read work pending: %d\n" "read done work pending: %d\n" "connect work pending: %d\n" "disconnect work pending: %d\n" "event work pending: %d\n" "max size supported: %d\n\n", usb_info->id, usb_info->name, Loading @@ -455,8 +454,7 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf, usb_info->write_cnt, work_pending(&usb_info->read_work), work_pending(&usb_info->read_done_work), work_pending(&usb_info->connect_work), work_pending(&usb_info->disconnect_work), work_pending(&usb_info->event_work), usb_info->max_size); bytes_in_buffer += bytes_written; Loading drivers/char/diag/diag_usb.c +62 −43 Original line number Diff line number Diff line Loading @@ -86,7 +86,29 @@ struct diag_usb_info diag_usb[NUM_DIAG_USB_DEV] = { } #endif }; static int diag_usb_event_add(struct diag_usb_info *usb_info, int data) { struct diag_usb_event_q *entry = NULL; entry = kzalloc(sizeof(struct diag_usb_event_q), GFP_ATOMIC); if (!entry) return -ENOMEM; entry->data = data; INIT_LIST_HEAD(&entry->link); list_add_tail(&entry->link, &usb_info->event_q); return 0; } static void diag_usb_event_remove(struct diag_usb_event_q *entry) { if (!entry) return; list_del(&entry->link); kfree(entry); entry = NULL; } static int diag_usb_buf_tbl_add(struct diag_usb_info *usb_info, unsigned char *buf, uint32_t len, int ctxt) { Loading Loading @@ -194,25 +216,6 @@ static void usb_connect(struct diag_usb_info *ch) queue_work(ch->usb_wq, &(ch->read_work)); } static void usb_connect_work_fn(struct work_struct *work) { struct diag_usb_info *ch = container_of(work, struct diag_usb_info, connect_work); wait_event_interruptible(ch->wait_q, ch->enabled > 0); ch->max_size = usb_diag_request_size(ch->hdl); atomic_set(&ch->connected, 1); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: disconnected_status: %d, connected_status: %d\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); usb_connect(ch); if (atomic_read(&ch->disconnected)) wake_up_interruptible(&ch->wait_q); } /* * This function is called asynchronously when USB is disconnected * and synchronously when Diag wants to disconnect from USB Loading @@ -224,32 +227,48 @@ static void usb_disconnect(struct diag_usb_info *ch) ch->ops->close(ch->ctxt, DIAG_USB_MODE); } static void usb_disconnect_work_fn(struct work_struct *work) static void usb_event_work_fn(struct work_struct *work) { struct diag_usb_info *ch = container_of(work, struct diag_usb_info, disconnect_work); event_work); struct diag_usb_event_q *entry = NULL; if (!ch) return; entry = list_first_entry(&(ch->event_q), struct diag_usb_event_q, link); if (!entry) return; switch (entry->data) { case USB_DIAG_CONNECT: wait_event_interruptible(ch->wait_q, ch->enabled > 0); ch->max_size = usb_diag_request_size(ch->hdl); atomic_set(&ch->connected, 1); atomic_set(&ch->disconnected, 1); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: disconnected_status: %d, connected_status: %d\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); "diag: USB channel %s: connected_status: %d\n", ch->name, atomic_read(&ch->connected)); wait_event_interruptible(ch->wait_q, atomic_read(&ch->connected) > 0); usb_connect(ch); break; case USB_DIAG_DISCONNECT: atomic_set(&ch->connected, 0); atomic_set(&ch->disconnected, 0); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: Cleared disconnected(%d) and connected(%d) status\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); "diag: USB channel %s: Cleared connected(%d) status\n", ch->name, atomic_read(&ch->connected)); if (!atomic_read(&ch->connected) && driver->usb_connected && diag_mask_param() && ch->id == DIAG_USB_LOCAL) driver->usb_connected && (ch->id == DIAG_USB_LOCAL) && diag_mask_param()) diag_clear_masks(0); usb_disconnect(ch); break; } diag_usb_event_remove(entry); if (!list_empty(&ch->event_q)) queue_work(ch->usb_wq, &(ch->event_work)); } static void usb_read_work_fn(struct work_struct *work) Loading Loading @@ -378,15 +397,16 @@ static void diag_usb_notifier(void *priv, unsigned int event, case USB_DIAG_CONNECT: pr_info("diag: USB channel %s: Received Connect event\n", usb_info->name); if (!atomic_read(&usb_info->connected)) diag_usb_event_add(usb_info, USB_DIAG_CONNECT); queue_work(usb_info->usb_wq, &usb_info->connect_work); &usb_info->event_work); break; case USB_DIAG_DISCONNECT: pr_info("diag: USB channel %s: Received Disconnect event\n", usb_info->name); diag_usb_event_add(usb_info, USB_DIAG_DISCONNECT); queue_work(usb_info->usb_wq, &usb_info->disconnect_work); &usb_info->event_work); break; case USB_DIAG_READ_DONE: spin_lock_irqsave(&usb_info->lock, flags); Loading Loading @@ -665,7 +685,6 @@ int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops) if (!ch->read_ptr) goto err; atomic_set(&ch->connected, 0); atomic_set(&ch->disconnected, 0); atomic_set(&ch->read_pending, 0); /* * This function is called when the mux registers with Diag-USB. Loading @@ -674,11 +693,11 @@ int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops) */ atomic_set(&ch->diag_state, 1); INIT_LIST_HEAD(&ch->buf_tbl); INIT_LIST_HEAD(&ch->event_q); diagmem_init(driver, ch->mempool); INIT_WORK(&(ch->read_work), usb_read_work_fn); INIT_WORK(&(ch->read_done_work), usb_read_done_work_fn); INIT_WORK(&(ch->connect_work), usb_connect_work_fn); INIT_WORK(&(ch->disconnect_work), usb_disconnect_work_fn); INIT_WORK(&(ch->event_work), usb_event_work_fn); init_waitqueue_head(&ch->wait_q); strlcpy(wq_name, "DIAG_USB_", sizeof(wq_name)); strlcat(wq_name, ch->name, sizeof(wq_name)); Loading drivers/char/diag/diag_usb.h +7 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,11 @@ struct diag_usb_buf_tbl_t { int ctxt; }; struct diag_usb_event_q { struct list_head link; int data; }; struct diag_usb_info { int id; int ctxt; Loading @@ -45,7 +50,6 @@ struct diag_usb_info { atomic_t connected; atomic_t diag_state; atomic_t read_pending; atomic_t disconnected; int enabled; int mempool; int max_size; Loading @@ -60,10 +64,10 @@ struct diag_usb_info { struct diag_request *read_ptr; struct work_struct read_work; struct work_struct read_done_work; struct work_struct connect_work; struct work_struct disconnect_work; struct work_struct event_work; struct workqueue_struct *usb_wq; wait_queue_head_t wait_q; struct list_head event_q; }; #ifdef CONFIG_DIAG_OVER_USB Loading Loading
drivers/char/diag/diag_debugfs.c +2 −4 Original line number Diff line number Diff line Loading @@ -440,8 +440,7 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf, "write count: %lu\n" "read work pending: %d\n" "read done work pending: %d\n" "connect work pending: %d\n" "disconnect work pending: %d\n" "event work pending: %d\n" "max size supported: %d\n\n", usb_info->id, usb_info->name, Loading @@ -455,8 +454,7 @@ static ssize_t diag_dbgfs_read_usbinfo(struct file *file, char __user *ubuf, usb_info->write_cnt, work_pending(&usb_info->read_work), work_pending(&usb_info->read_done_work), work_pending(&usb_info->connect_work), work_pending(&usb_info->disconnect_work), work_pending(&usb_info->event_work), usb_info->max_size); bytes_in_buffer += bytes_written; Loading
drivers/char/diag/diag_usb.c +62 −43 Original line number Diff line number Diff line Loading @@ -86,7 +86,29 @@ struct diag_usb_info diag_usb[NUM_DIAG_USB_DEV] = { } #endif }; static int diag_usb_event_add(struct diag_usb_info *usb_info, int data) { struct diag_usb_event_q *entry = NULL; entry = kzalloc(sizeof(struct diag_usb_event_q), GFP_ATOMIC); if (!entry) return -ENOMEM; entry->data = data; INIT_LIST_HEAD(&entry->link); list_add_tail(&entry->link, &usb_info->event_q); return 0; } static void diag_usb_event_remove(struct diag_usb_event_q *entry) { if (!entry) return; list_del(&entry->link); kfree(entry); entry = NULL; } static int diag_usb_buf_tbl_add(struct diag_usb_info *usb_info, unsigned char *buf, uint32_t len, int ctxt) { Loading Loading @@ -194,25 +216,6 @@ static void usb_connect(struct diag_usb_info *ch) queue_work(ch->usb_wq, &(ch->read_work)); } static void usb_connect_work_fn(struct work_struct *work) { struct diag_usb_info *ch = container_of(work, struct diag_usb_info, connect_work); wait_event_interruptible(ch->wait_q, ch->enabled > 0); ch->max_size = usb_diag_request_size(ch->hdl); atomic_set(&ch->connected, 1); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: disconnected_status: %d, connected_status: %d\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); usb_connect(ch); if (atomic_read(&ch->disconnected)) wake_up_interruptible(&ch->wait_q); } /* * This function is called asynchronously when USB is disconnected * and synchronously when Diag wants to disconnect from USB Loading @@ -224,32 +227,48 @@ static void usb_disconnect(struct diag_usb_info *ch) ch->ops->close(ch->ctxt, DIAG_USB_MODE); } static void usb_disconnect_work_fn(struct work_struct *work) static void usb_event_work_fn(struct work_struct *work) { struct diag_usb_info *ch = container_of(work, struct diag_usb_info, disconnect_work); event_work); struct diag_usb_event_q *entry = NULL; if (!ch) return; entry = list_first_entry(&(ch->event_q), struct diag_usb_event_q, link); if (!entry) return; switch (entry->data) { case USB_DIAG_CONNECT: wait_event_interruptible(ch->wait_q, ch->enabled > 0); ch->max_size = usb_diag_request_size(ch->hdl); atomic_set(&ch->connected, 1); atomic_set(&ch->disconnected, 1); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: disconnected_status: %d, connected_status: %d\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); "diag: USB channel %s: connected_status: %d\n", ch->name, atomic_read(&ch->connected)); wait_event_interruptible(ch->wait_q, atomic_read(&ch->connected) > 0); usb_connect(ch); break; case USB_DIAG_DISCONNECT: atomic_set(&ch->connected, 0); atomic_set(&ch->disconnected, 0); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: USB channel %s: Cleared disconnected(%d) and connected(%d) status\n", ch->name, atomic_read(&ch->disconnected), atomic_read(&ch->connected)); "diag: USB channel %s: Cleared connected(%d) status\n", ch->name, atomic_read(&ch->connected)); if (!atomic_read(&ch->connected) && driver->usb_connected && diag_mask_param() && ch->id == DIAG_USB_LOCAL) driver->usb_connected && (ch->id == DIAG_USB_LOCAL) && diag_mask_param()) diag_clear_masks(0); usb_disconnect(ch); break; } diag_usb_event_remove(entry); if (!list_empty(&ch->event_q)) queue_work(ch->usb_wq, &(ch->event_work)); } static void usb_read_work_fn(struct work_struct *work) Loading Loading @@ -378,15 +397,16 @@ static void diag_usb_notifier(void *priv, unsigned int event, case USB_DIAG_CONNECT: pr_info("diag: USB channel %s: Received Connect event\n", usb_info->name); if (!atomic_read(&usb_info->connected)) diag_usb_event_add(usb_info, USB_DIAG_CONNECT); queue_work(usb_info->usb_wq, &usb_info->connect_work); &usb_info->event_work); break; case USB_DIAG_DISCONNECT: pr_info("diag: USB channel %s: Received Disconnect event\n", usb_info->name); diag_usb_event_add(usb_info, USB_DIAG_DISCONNECT); queue_work(usb_info->usb_wq, &usb_info->disconnect_work); &usb_info->event_work); break; case USB_DIAG_READ_DONE: spin_lock_irqsave(&usb_info->lock, flags); Loading Loading @@ -665,7 +685,6 @@ int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops) if (!ch->read_ptr) goto err; atomic_set(&ch->connected, 0); atomic_set(&ch->disconnected, 0); atomic_set(&ch->read_pending, 0); /* * This function is called when the mux registers with Diag-USB. Loading @@ -674,11 +693,11 @@ int diag_usb_register(int id, int ctxt, struct diag_mux_ops *ops) */ atomic_set(&ch->diag_state, 1); INIT_LIST_HEAD(&ch->buf_tbl); INIT_LIST_HEAD(&ch->event_q); diagmem_init(driver, ch->mempool); INIT_WORK(&(ch->read_work), usb_read_work_fn); INIT_WORK(&(ch->read_done_work), usb_read_done_work_fn); INIT_WORK(&(ch->connect_work), usb_connect_work_fn); INIT_WORK(&(ch->disconnect_work), usb_disconnect_work_fn); INIT_WORK(&(ch->event_work), usb_event_work_fn); init_waitqueue_head(&ch->wait_q); strlcpy(wq_name, "DIAG_USB_", sizeof(wq_name)); strlcat(wq_name, ch->name, sizeof(wq_name)); Loading
drivers/char/diag/diag_usb.h +7 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,11 @@ struct diag_usb_buf_tbl_t { int ctxt; }; struct diag_usb_event_q { struct list_head link; int data; }; struct diag_usb_info { int id; int ctxt; Loading @@ -45,7 +50,6 @@ struct diag_usb_info { atomic_t connected; atomic_t diag_state; atomic_t read_pending; atomic_t disconnected; int enabled; int mempool; int max_size; Loading @@ -60,10 +64,10 @@ struct diag_usb_info { struct diag_request *read_ptr; struct work_struct read_work; struct work_struct read_done_work; struct work_struct connect_work; struct work_struct disconnect_work; struct work_struct event_work; struct workqueue_struct *usb_wq; wait_queue_head_t wait_q; struct list_head event_q; }; #ifdef CONFIG_DIAG_OVER_USB Loading