From c99a841d40aa8753224386c8ca61aaaccd852ecb Mon Sep 17 00:00:00 2001 From: Pratham Pratap Date: Wed, 12 Jul 2023 00:17:04 +0530 Subject: [PATCH] usb: gadget: cdev: Add spinlock to synchronize ports->cbits_updated Consider a scenario in which open, write and close of AT port is being done repeatedly. At some point in time, cbits_updated in f_cdev structure gets overwritten by the previous close instance causing the AT port to go unresponsive. This prevents port bridge service from sending DTR/RTS settings to at_mdm0 from at_usb0. Fix this by adding spinlock to synchronise the updation of ports->cbits_updated field in f_cdev structure. Change-Id: Ibf39aa90f3918cd5f22e32a3b06685db4c4298ae Signed-off-by: Pratham Pratap --- drivers/usb/gadget/function/f_cdev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 9357949a1525f..481783ea6968a 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -1617,6 +1617,7 @@ static long f_cdev_ioctl(struct file *fp, unsigned int cmd, int i = 0; uint32_t val; struct f_cdev *port; + unsigned long flags; port = fp->private_data; if (!port) { @@ -1638,11 +1639,13 @@ static long f_cdev_ioctl(struct file *fp, unsigned int cmd, break; case TIOCMGET: pr_debug("TIOCMGET on port(%s)%pK\n", port->name, port); + spin_lock_irqsave(&port->port_lock, flags); ret = f_cdev_tiocmget(port); if (ret >= 0) { ret = put_user(ret, (uint32_t *)arg); port->cbits_updated = false; } + spin_unlock_irqrestore(&port->port_lock, flags); break; default: pr_err("Received cmd:%d not supported\n", cmd); @@ -1658,6 +1661,7 @@ static void usb_cser_notify_modem(void *fport, int ctrl_bits) int temp; struct f_cdev *port = fport; struct cserial *cser; + unsigned long flags; cser = &port->port_usb; if (!port) { @@ -1672,6 +1676,7 @@ static void usb_cser_notify_modem(void *fport, int ctrl_bits) if (temp == port->cbits_to_modem) return; + spin_lock_irqsave(&port->port_lock, flags); port->cbits_to_modem = temp; port->cbits_updated = true; @@ -1686,6 +1691,7 @@ static void usb_cser_notify_modem(void *fport, int ctrl_bits) cser->send_modem_ctrl_bits(cser, cbits_to_laptop); } + spin_unlock_irqrestore(&port->port_lock, flags); wake_up(&port->read_wq); }