usb: hsotg: samsung: Replace endpoint specific locks with a global lock
The endpoint specific locks are replaced with a global lock. This is crucial for running s3c-hsotg driver on a SMP SoC. Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
committed by
Felipe Balbi
parent
99c5150058
commit
22258f4906
@@ -112,7 +112,6 @@ struct s3c_hsotg_ep {
|
|||||||
struct s3c_hsotg_req *req;
|
struct s3c_hsotg_req *req;
|
||||||
struct dentry *debugfs;
|
struct dentry *debugfs;
|
||||||
|
|
||||||
spinlock_t lock;
|
|
||||||
|
|
||||||
unsigned long total_data;
|
unsigned long total_data;
|
||||||
unsigned int size_loaded;
|
unsigned int size_loaded;
|
||||||
@@ -156,6 +155,8 @@ struct s3c_hsotg {
|
|||||||
struct usb_gadget_driver *driver;
|
struct usb_gadget_driver *driver;
|
||||||
struct s3c_hsotg_plat *plat;
|
struct s3c_hsotg_plat *plat;
|
||||||
|
|
||||||
|
spinlock_t lock;
|
||||||
|
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
int irq;
|
int irq;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
@@ -901,6 +902,8 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
|
|||||||
ep->name, req, req->length, req->buf, req->no_interrupt,
|
ep->name, req, req->length, req->buf, req->no_interrupt,
|
||||||
req->zero, req->short_not_ok);
|
req->zero, req->short_not_ok);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&hs->lock, irqflags);
|
||||||
|
|
||||||
/* initialise status of the request */
|
/* initialise status of the request */
|
||||||
INIT_LIST_HEAD(&hs_req->queue);
|
INIT_LIST_HEAD(&hs_req->queue);
|
||||||
req->actual = 0;
|
req->actual = 0;
|
||||||
@@ -913,15 +916,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, irqflags);
|
|
||||||
|
|
||||||
first = list_empty(&hs_ep->queue);
|
first = list_empty(&hs_ep->queue);
|
||||||
list_add_tail(&hs_req->queue, &hs_ep->queue);
|
list_add_tail(&hs_req->queue, &hs_ep->queue);
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
|
s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, irqflags);
|
spin_unlock_irqrestore(&hs->lock, irqflags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1381,9 +1382,9 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (hs_req->req.complete) {
|
if (hs_req->req.complete) {
|
||||||
spin_unlock(&hs_ep->lock);
|
spin_unlock(&hsotg->lock);
|
||||||
hs_req->req.complete(&hs_ep->ep, &hs_req->req);
|
hs_req->req.complete(&hs_ep->ep, &hs_req->req);
|
||||||
spin_lock(&hs_ep->lock);
|
spin_lock(&hsotg->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1418,9 +1419,9 @@ static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg,
|
|||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
|
s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1442,6 +1443,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
|
|||||||
int max_req;
|
int max_req;
|
||||||
int read_ptr;
|
int read_ptr;
|
||||||
|
|
||||||
|
spin_lock(&hsotg->lock);
|
||||||
|
|
||||||
if (!hs_req) {
|
if (!hs_req) {
|
||||||
u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
|
u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
|
||||||
int ptr;
|
int ptr;
|
||||||
@@ -1454,11 +1457,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
|
|||||||
for (ptr = 0; ptr < size; ptr += 4)
|
for (ptr = 0; ptr < size; ptr += 4)
|
||||||
(void)readl(fifo);
|
(void)readl(fifo);
|
||||||
|
|
||||||
|
spin_unlock(&hsotg->lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&hs_ep->lock);
|
|
||||||
|
|
||||||
to_read = size;
|
to_read = size;
|
||||||
read_ptr = hs_req->req.actual;
|
read_ptr = hs_req->req.actual;
|
||||||
max_req = hs_req->req.length - read_ptr;
|
max_req = hs_req->req.length - read_ptr;
|
||||||
@@ -1486,7 +1488,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
|
|||||||
*/
|
*/
|
||||||
readsl(fifo, hs_req->req.buf + read_ptr, to_read);
|
readsl(fifo, hs_req->req.buf + read_ptr, to_read);
|
||||||
|
|
||||||
spin_unlock(&hs_ep->lock);
|
spin_unlock(&hsotg->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2123,7 +2125,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
|
|||||||
struct s3c_hsotg_req *req, *treq;
|
struct s3c_hsotg_req *req, *treq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&ep->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
list_for_each_entry_safe(req, treq, &ep->queue, queue) {
|
list_for_each_entry_safe(req, treq, &ep->queue, queue) {
|
||||||
/*
|
/*
|
||||||
@@ -2138,7 +2140,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
|
|||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ep->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define call_gadget(_hs, _entry) \
|
#define call_gadget(_hs, _entry) \
|
||||||
@@ -2602,7 +2604,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
|
|||||||
dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
|
dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
|
||||||
__func__, epctrl, epctrl_reg);
|
__func__, epctrl, epctrl_reg);
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
|
epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
|
||||||
epctrl |= DxEPCTL_MPS(mps);
|
epctrl |= DxEPCTL_MPS(mps);
|
||||||
@@ -2681,7 +2683,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
|
|||||||
s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
|
s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2711,7 +2713,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
|||||||
/* terminate all requests with shutdown */
|
/* terminate all requests with shutdown */
|
||||||
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
|
kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
ctrl = readl(hsotg->regs + epctrl_reg);
|
ctrl = readl(hsotg->regs + epctrl_reg);
|
||||||
ctrl &= ~DxEPCTL_EPEna;
|
ctrl &= ~DxEPCTL_EPEna;
|
||||||
@@ -2724,7 +2726,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
|
|||||||
/* disable endpoint interrupts */
|
/* disable endpoint interrupts */
|
||||||
s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
|
s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2759,15 +2761,15 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
|
|||||||
|
|
||||||
dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
|
dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, flags);
|
spin_lock_irqsave(&hs->lock, flags);
|
||||||
|
|
||||||
if (!on_list(hs_ep, hs_req)) {
|
if (!on_list(hs_ep, hs_req)) {
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, flags);
|
spin_unlock_irqrestore(&hs->lock, flags);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
|
s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, flags);
|
spin_unlock_irqrestore(&hs->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2789,7 +2791,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
|
|||||||
|
|
||||||
dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
|
dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
|
||||||
|
|
||||||
spin_lock_irqsave(&hs_ep->lock, irqflags);
|
spin_lock_irqsave(&hs->lock, irqflags);
|
||||||
|
|
||||||
/* write both IN and OUT control registers */
|
/* write both IN and OUT control registers */
|
||||||
|
|
||||||
@@ -2825,7 +2827,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
|
|||||||
|
|
||||||
writel(epctl, hs->regs + epreg);
|
writel(epctl, hs->regs + epreg);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hs_ep->lock, irqflags);
|
spin_unlock_irqrestore(&hs->lock, irqflags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3061,8 +3063,6 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
|
|||||||
INIT_LIST_HEAD(&hs_ep->queue);
|
INIT_LIST_HEAD(&hs_ep->queue);
|
||||||
INIT_LIST_HEAD(&hs_ep->ep.ep_list);
|
INIT_LIST_HEAD(&hs_ep->ep.ep_list);
|
||||||
|
|
||||||
spin_lock_init(&hs_ep->lock);
|
|
||||||
|
|
||||||
/* add to the list of endpoints known by the gadget driver */
|
/* add to the list of endpoints known by the gadget driver */
|
||||||
if (epnum)
|
if (epnum)
|
||||||
list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list);
|
list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list);
|
||||||
@@ -3340,7 +3340,7 @@ static int ep_show(struct seq_file *seq, void *v)
|
|||||||
seq_printf(seq, "request list (%p,%p):\n",
|
seq_printf(seq, "request list (%p,%p):\n",
|
||||||
ep->queue.next, ep->queue.prev);
|
ep->queue.next, ep->queue.prev);
|
||||||
|
|
||||||
spin_lock_irqsave(&ep->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
list_for_each_entry(req, &ep->queue, queue) {
|
list_for_each_entry(req, &ep->queue, queue) {
|
||||||
if (--show_limit < 0) {
|
if (--show_limit < 0) {
|
||||||
@@ -3355,7 +3355,7 @@ static int ep_show(struct seq_file *seq, void *v)
|
|||||||
req->req.actual, req->req.status);
|
req->req.actual, req->req.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ep->lock, flags);
|
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3507,6 +3507,8 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
|
|||||||
goto err_clk;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_init(&hsotg->lock);
|
||||||
|
|
||||||
hsotg->irq = ret;
|
hsotg->irq = ret;
|
||||||
|
|
||||||
ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
|
ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
|
||||||
|
Reference in New Issue
Block a user