usb: gadget: mv_udc: add missing spinlock in ep enable/disable

The ep enable / disable functions can be called from interrupt
context, and they are not race safe on SMP systems. The critical
data can be modified in more than one routing.
Make them race safe by using IRQ-safe spinlock functions.

Signed-off-by: Neil Zhang <zhangwm@marvell.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index fcb980d..501b05a 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -497,6 +497,7 @@
 	u16 max = 0;
 	u32 bit_pos, epctrlx, direction;
 	unsigned char zlt = 0, ios = 0, mult = 0;
+	unsigned long flags;
 
 	ep = container_of(_ep, struct mv_ep, ep);
 	udc = ep->udc;
@@ -517,9 +518,6 @@
 	 */
 	zlt = 1;
 
-	/* Get the endpoint queue head address */
-	dqh = (struct mv_dqh *)ep->dqh;
-
 	bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
 
 	/* Check if the Endpoint is Primed */
@@ -556,6 +554,10 @@
 	default:
 		goto en_done;
 	}
+
+	spin_lock_irqsave(&udc->lock, flags);
+	/* Get the endpoint queue head address */
+	dqh = ep->dqh;
 	dqh->max_packet_length = (max << EP_QUEUE_HEAD_MAX_PKT_LEN_POS)
 		| (mult << EP_QUEUE_HEAD_MULT_POS)
 		| (zlt ? EP_QUEUE_HEAD_ZLT_SEL : 0)
@@ -600,6 +602,8 @@
 		writel(epctrlx, &udc->op_regs->epctrlx[ep->ep_num]);
 	}
 
+	spin_unlock_irqrestore(&udc->lock, flags);
+
 	return 0;
 en_done:
 	return -EINVAL;
@@ -611,6 +615,7 @@
 	struct mv_ep *ep;
 	struct mv_dqh *dqh;
 	u32 bit_pos, epctrlx, direction;
+	unsigned long flags;
 
 	ep = container_of(_ep, struct mv_ep, ep);
 	if ((_ep == NULL) || !ep->desc)
@@ -621,6 +626,8 @@
 	/* Get the endpoint queue head address */
 	dqh = ep->dqh;
 
+	spin_lock_irqsave(&udc->lock, flags);
+
 	direction = ep_dir(ep);
 	bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num);
 
@@ -639,6 +646,9 @@
 
 	ep->desc = NULL;
 	ep->stopped = 1;
+
+	spin_unlock_irqrestore(&udc->lock, flags);
+
 	return 0;
 }