diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-01 12:20:28 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-01 12:20:28 -0500 |
commit | f9b0f5170918695891f42645737682ccb452ee13 (patch) | |
tree | 75eaab0ff54f8aadaa6375df140cc9d685f78d95 /drivers/usb/renesas_usbhs | |
parent | 8062d94a545457a83d5291bd62c3bfd14200bba0 (diff) | |
parent | 6440093f5eae9842feb06e40d41c3bd569b6b461 (diff) |
Merge tag 'gadget-for-v3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
USB: Gadget: changes for 3.4
This merge is rather big. Here's what it contains:
For am5536udc we have just simple coding style fixes. Nothing that has any
potential to cause any issues going forward.
With mv_udc, there's only one single change removing an unneeded NULL check.
at91_udc also only saw a single change this merge window, and that's only
removing a duplicated header.
The Renesas controller has a few more involved changes. Support for SUDMAC was
added, there's now a special handling of IRQ resources for when the IRQ line is
shared between Renesas controller and SUDMAC, we also had a bug fix where
Renesas controller would sleep in atomic context while doing DMA transfers from
a tasklet. There were also a set of minor cleanups.
The FSL UDC also had a scheduling in atomic context bug fix, but that's all.
Thanks to Sebastian, the dummy_hcd now works better than ever with support for
scatterlists and streams. Sebastian also added SuperSpeed descriptors to the
serial gadgets.
The highlight on this merge is the addition of a generic API for mapping and
unmapping usb_requests. This will avoid code duplication on all UDC controllers
and also kills all the defines for DMA_ADDR_INVALID which UDC controllers
sprinkled around. A few of the UDC controllers were already converted to use
this new API.
Conflicts:
drivers/usb/dwc3/gadget.c
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r-- | drivers/usb/renesas_usbhs/common.c | 11 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/common.h | 1 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 29 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/fifo.h | 3 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod.c | 2 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 79 |
6 files changed, 46 insertions, 79 deletions
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index e9a5b1d2615e..a165490bae48 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -413,8 +413,7 @@ static int usbhs_probe(struct platform_device *pdev) | |||
413 | struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; | 413 | struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; |
414 | struct renesas_usbhs_driver_callback *dfunc; | 414 | struct renesas_usbhs_driver_callback *dfunc; |
415 | struct usbhs_priv *priv; | 415 | struct usbhs_priv *priv; |
416 | struct resource *res; | 416 | struct resource *res, *irq_res; |
417 | unsigned int irq; | ||
418 | int ret; | 417 | int ret; |
419 | 418 | ||
420 | /* check platform information */ | 419 | /* check platform information */ |
@@ -426,8 +425,8 @@ static int usbhs_probe(struct platform_device *pdev) | |||
426 | 425 | ||
427 | /* platform data */ | 426 | /* platform data */ |
428 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 427 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
429 | irq = platform_get_irq(pdev, 0); | 428 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
430 | if (!res || (int)irq <= 0) { | 429 | if (!res || !irq_res) { |
431 | dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); | 430 | dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); |
432 | return -ENODEV; | 431 | return -ENODEV; |
433 | } | 432 | } |
@@ -476,7 +475,9 @@ static int usbhs_probe(struct platform_device *pdev) | |||
476 | /* | 475 | /* |
477 | * priv settings | 476 | * priv settings |
478 | */ | 477 | */ |
479 | priv->irq = irq; | 478 | priv->irq = irq_res->start; |
479 | if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE) | ||
480 | priv->irqflags = IRQF_SHARED; | ||
480 | priv->pdev = pdev; | 481 | priv->pdev = pdev; |
481 | INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); | 482 | INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); |
482 | spin_lock_init(usbhs_priv_to_lock(priv)); | 483 | spin_lock_init(usbhs_priv_to_lock(priv)); |
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index d79b3e27db95..3f3ccd358753 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -242,6 +242,7 @@ struct usbhs_priv { | |||
242 | 242 | ||
243 | void __iomem *base; | 243 | void __iomem *base; |
244 | unsigned int irq; | 244 | unsigned int irq; |
245 | unsigned long irqflags; | ||
245 | 246 | ||
246 | struct renesas_usbhs_platform_callback pfunc; | 247 | struct renesas_usbhs_platform_callback pfunc; |
247 | struct renesas_usbhs_driver_param dparam; | 248 | struct renesas_usbhs_driver_param dparam; |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 72339bd6fcab..3648c82a17fe 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) | 23 | #define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) |
24 | #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) | 24 | #define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) |
25 | #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) | 25 | #define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) |
26 | #define usbhsf_is_cfifo(p, f) (usbhsf_get_cfifo(p) == f) | ||
26 | 27 | ||
27 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ | 28 | #define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ |
28 | 29 | ||
@@ -75,8 +76,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, | |||
75 | pipe->handler = &usbhsf_null_handler; | 76 | pipe->handler = &usbhsf_null_handler; |
76 | } | 77 | } |
77 | 78 | ||
78 | list_del_init(&pkt->node); | 79 | list_move_tail(&pkt->node, &pipe->list); |
79 | list_add_tail(&pkt->node, &pipe->list); | ||
80 | 80 | ||
81 | /* | 81 | /* |
82 | * each pkt must hold own handler. | 82 | * each pkt must hold own handler. |
@@ -106,7 +106,7 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe) | |||
106 | if (list_empty(&pipe->list)) | 106 | if (list_empty(&pipe->list)) |
107 | return NULL; | 107 | return NULL; |
108 | 108 | ||
109 | return list_entry(pipe->list.next, struct usbhs_pkt, node); | 109 | return list_first_entry(&pipe->list, struct usbhs_pkt, node); |
110 | } | 110 | } |
111 | 111 | ||
112 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) | 112 | struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
@@ -305,7 +305,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe, | |||
305 | } | 305 | } |
306 | 306 | ||
307 | /* "base" will be used below */ | 307 | /* "base" will be used below */ |
308 | usbhs_write(priv, fifo->sel, base | MBW_32); | 308 | if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo)) |
309 | usbhs_write(priv, fifo->sel, base); | ||
310 | else | ||
311 | usbhs_write(priv, fifo->sel, base | MBW_32); | ||
309 | 312 | ||
310 | /* check ISEL and CURPIPE value */ | 313 | /* check ISEL and CURPIPE value */ |
311 | while (timeout--) { | 314 | while (timeout--) { |
@@ -762,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | |||
762 | } | 765 | } |
763 | 766 | ||
764 | static void usbhsf_dma_complete(void *arg); | 767 | static void usbhsf_dma_complete(void *arg); |
765 | static void usbhsf_dma_prepare_tasklet(unsigned long data) | 768 | static void xfer_work(struct work_struct *work) |
766 | { | 769 | { |
767 | struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; | 770 | struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work); |
768 | struct usbhs_pipe *pipe = pkt->pipe; | 771 | struct usbhs_pipe *pipe = pkt->pipe; |
769 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); | 772 | struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); |
770 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 773 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
@@ -844,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) | |||
844 | 847 | ||
845 | pkt->trans = len; | 848 | pkt->trans = len; |
846 | 849 | ||
847 | tasklet_init(&fifo->tasklet, | 850 | INIT_WORK(&pkt->work, xfer_work); |
848 | usbhsf_dma_prepare_tasklet, | 851 | schedule_work(&pkt->work); |
849 | (unsigned long)pkt); | ||
850 | |||
851 | tasklet_schedule(&fifo->tasklet); | ||
852 | 852 | ||
853 | return 0; | 853 | return 0; |
854 | 854 | ||
@@ -938,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) | |||
938 | 938 | ||
939 | pkt->trans = len; | 939 | pkt->trans = len; |
940 | 940 | ||
941 | tasklet_init(&fifo->tasklet, | 941 | INIT_WORK(&pkt->work, xfer_work); |
942 | usbhsf_dma_prepare_tasklet, | 942 | schedule_work(&pkt->work); |
943 | (unsigned long)pkt); | ||
944 | |||
945 | tasklet_schedule(&fifo->tasklet); | ||
946 | 943 | ||
947 | return 0; | 944 | return 0; |
948 | 945 | ||
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index f68609c0f489..c31731a843d1 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/sh_dma.h> | 21 | #include <linux/sh_dma.h> |
22 | #include <linux/workqueue.h> | ||
22 | #include <asm/dma.h> | 23 | #include <asm/dma.h> |
23 | #include "pipe.h" | 24 | #include "pipe.h" |
24 | 25 | ||
@@ -31,7 +32,6 @@ struct usbhs_fifo { | |||
31 | u32 ctr; /* xFIFOCTR */ | 32 | u32 ctr; /* xFIFOCTR */ |
32 | 33 | ||
33 | struct usbhs_pipe *pipe; | 34 | struct usbhs_pipe *pipe; |
34 | struct tasklet_struct tasklet; | ||
35 | 35 | ||
36 | struct dma_chan *tx_chan; | 36 | struct dma_chan *tx_chan; |
37 | struct dma_chan *rx_chan; | 37 | struct dma_chan *rx_chan; |
@@ -53,6 +53,7 @@ struct usbhs_pkt { | |||
53 | struct usbhs_pkt_handle *handler; | 53 | struct usbhs_pkt_handle *handler; |
54 | void (*done)(struct usbhs_priv *priv, | 54 | void (*done)(struct usbhs_priv *priv, |
55 | struct usbhs_pkt *pkt); | 55 | struct usbhs_pkt *pkt); |
56 | struct work_struct work; | ||
56 | dma_addr_t dma; | 57 | dma_addr_t dma; |
57 | void *buf; | 58 | void *buf; |
58 | int length; | 59 | int length; |
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 1b97fb12694b..0871e816df45 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c | |||
@@ -152,7 +152,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv) | |||
152 | 152 | ||
153 | /* irq settings */ | 153 | /* irq settings */ |
154 | ret = request_irq(priv->irq, usbhs_interrupt, | 154 | ret = request_irq(priv->irq, usbhs_interrupt, |
155 | 0, dev_name(dev), priv); | 155 | priv->irqflags, dev_name(dev), priv); |
156 | if (ret) { | 156 | if (ret) { |
157 | dev_err(dev, "irq request err\n"); | 157 | dev_err(dev, "irq request err\n"); |
158 | goto mod_init_gadget_err; | 158 | goto mod_init_gadget_err; |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 7542aa94a462..00bd2a5e0362 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -165,69 +165,32 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep, | |||
165 | /* | 165 | /* |
166 | * dma map/unmap | 166 | * dma map/unmap |
167 | */ | 167 | */ |
168 | static int usbhsg_dma_map(struct device *dev, | 168 | static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) |
169 | struct usbhs_pkt *pkt, | ||
170 | enum dma_data_direction dir) | ||
171 | { | ||
172 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); | ||
173 | struct usb_request *req = &ureq->req; | ||
174 | |||
175 | if (pkt->dma != DMA_ADDR_INVALID) { | ||
176 | dev_err(dev, "dma is already mapped\n"); | ||
177 | return -EIO; | ||
178 | } | ||
179 | |||
180 | if (req->dma == DMA_ADDR_INVALID) { | ||
181 | pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir); | ||
182 | } else { | ||
183 | dma_sync_single_for_device(dev, req->dma, req->length, dir); | ||
184 | pkt->dma = req->dma; | ||
185 | } | ||
186 | |||
187 | if (dma_mapping_error(dev, pkt->dma)) { | ||
188 | dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma); | ||
189 | return -EIO; | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int usbhsg_dma_unmap(struct device *dev, | ||
196 | struct usbhs_pkt *pkt, | ||
197 | enum dma_data_direction dir) | ||
198 | { | 169 | { |
199 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); | 170 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); |
200 | struct usb_request *req = &ureq->req; | 171 | struct usb_request *req = &ureq->req; |
201 | |||
202 | if (pkt->dma == DMA_ADDR_INVALID) { | ||
203 | dev_err(dev, "dma is not mapped\n"); | ||
204 | return -EIO; | ||
205 | } | ||
206 | |||
207 | if (req->dma == DMA_ADDR_INVALID) | ||
208 | dma_unmap_single(dev, pkt->dma, pkt->length, dir); | ||
209 | else | ||
210 | dma_sync_single_for_cpu(dev, req->dma, req->length, dir); | ||
211 | |||
212 | pkt->dma = DMA_ADDR_INVALID; | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | ||
218 | { | ||
219 | struct usbhs_pipe *pipe = pkt->pipe; | 172 | struct usbhs_pipe *pipe = pkt->pipe; |
220 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); | 173 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); |
221 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | 174 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); |
222 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
223 | enum dma_data_direction dir; | 175 | enum dma_data_direction dir; |
176 | int ret = 0; | ||
224 | 177 | ||
225 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 178 | dir = usbhs_pipe_is_dir_host(pipe); |
226 | 179 | ||
227 | if (map) | 180 | if (map) { |
228 | return usbhsg_dma_map(dev, pkt, dir); | 181 | /* it can not use scatter/gather */ |
229 | else | 182 | WARN_ON(req->num_sgs); |
230 | return usbhsg_dma_unmap(dev, pkt, dir); | 183 | |
184 | ret = usb_gadget_map_request(&gpriv->gadget, req, dir); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | |||
188 | pkt->dma = req->dma; | ||
189 | } else { | ||
190 | usb_gadget_unmap_request(&gpriv->gadget, req, dir); | ||
191 | } | ||
192 | |||
193 | return ret; | ||
231 | } | 194 | } |
232 | 195 | ||
233 | /* | 196 | /* |
@@ -657,8 +620,6 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | |||
657 | 620 | ||
658 | usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); | 621 | usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); |
659 | 622 | ||
660 | ureq->req.dma = DMA_ADDR_INVALID; | ||
661 | |||
662 | return &ureq->req; | 623 | return &ureq->req; |
663 | } | 624 | } |
664 | 625 | ||
@@ -941,6 +902,11 @@ static int usbhsg_stop(struct usbhs_priv *priv) | |||
941 | return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); | 902 | return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); |
942 | } | 903 | } |
943 | 904 | ||
905 | static void usbhs_mod_gadget_release(struct device *pdev) | ||
906 | { | ||
907 | /* do nothing */ | ||
908 | } | ||
909 | |||
944 | int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | 910 | int usbhs_mod_gadget_probe(struct usbhs_priv *priv) |
945 | { | 911 | { |
946 | struct usbhsg_gpriv *gpriv; | 912 | struct usbhsg_gpriv *gpriv; |
@@ -989,6 +955,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
989 | */ | 955 | */ |
990 | dev_set_name(&gpriv->gadget.dev, "gadget"); | 956 | dev_set_name(&gpriv->gadget.dev, "gadget"); |
991 | gpriv->gadget.dev.parent = dev; | 957 | gpriv->gadget.dev.parent = dev; |
958 | gpriv->gadget.dev.release = usbhs_mod_gadget_release; | ||
992 | gpriv->gadget.name = "renesas_usbhs_udc"; | 959 | gpriv->gadget.name = "renesas_usbhs_udc"; |
993 | gpriv->gadget.ops = &usbhsg_gadget_ops; | 960 | gpriv->gadget.ops = &usbhsg_gadget_ops; |
994 | gpriv->gadget.max_speed = USB_SPEED_HIGH; | 961 | gpriv->gadget.max_speed = USB_SPEED_HIGH; |