diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index 048619d40c74..695492f752f1 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -352,7 +352,8 @@ static void usb_read_done_work_fn(struct work_struct *work) } static void diag_usb_write_done(struct diag_usb_info *ch, - struct diag_request *req) + struct diag_request *req, + int sync) { int ctxt = 0; int len = 0; @@ -362,14 +363,15 @@ static void diag_usb_write_done(struct diag_usb_info *ch, if (!ch || !req) return; - - spin_lock_irqsave(&ch->write_lock, flags); + if (!sync) + spin_lock_irqsave(&ch->write_lock, flags); ch->write_cnt++; entry = diag_usb_buf_tbl_get(ch, req->context); if (!entry) { pr_err_ratelimited("diag: In %s, unable to find entry %pK in the table\n", __func__, req->context); - spin_unlock_irqrestore(&ch->write_lock, flags); + if (!sync) + spin_unlock_irqrestore(&ch->write_lock, flags); return; } if (atomic_read(&entry->ref_count) != 0) { @@ -377,7 +379,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch, atomic_read(&entry->ref_count)); diag_ws_on_copy_complete(DIAG_WS_MUX); diagmem_free(driver, req, ch->mempool); - spin_unlock_irqrestore(&ch->write_lock, flags); + if (!sync) + spin_unlock_irqrestore(&ch->write_lock, flags); return; } DIAG_LOG(DIAG_DEBUG_MUX, "full write_done\n"); @@ -394,7 +397,8 @@ static void diag_usb_write_done(struct diag_usb_info *ch, len = 0; ctxt = 0; diagmem_free(driver, req, ch->mempool); - spin_unlock_irqrestore(&ch->write_lock, flags); + if(!sync) + spin_unlock_irqrestore(&ch->write_lock, flags); } static void diag_usb_notifier(void *priv, unsigned int event, @@ -439,7 +443,10 @@ static void diag_usb_notifier(void *priv, unsigned int event, &usb_info->read_done_work); break; case USB_DIAG_WRITE_DONE: - diag_usb_write_done(usb_info, d_req); + diag_usb_write_done(usb_info, d_req, 0); + break; + case USB_DIAG_WRITE_DONE_SYNC: + diag_usb_write_done(usb_info, d_req, 1); break; default: pr_err_ratelimited("diag: Unknown event from USB diag\n"); diff --git a/include/linux/usb/usbdiag.h b/include/linux/usb/usbdiag.h index 9ccf2dc763a8..b3f6cc5946d4 100644 --- a/include/linux/usb/usbdiag.h +++ b/include/linux/usb/usbdiag.h @@ -18,6 +18,7 @@ #define USB_DIAG_DISCONNECT 1 #define USB_DIAG_WRITE_DONE 2 #define USB_DIAG_READ_DONE 3 +#define USB_DIAG_WRITE_DONE_SYNC 4 struct diag_request { char *buf;