diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-09-29 04:25:46 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-09-29 04:25:46 -0400 |
| commit | 80c82ffebd2ec3f91a2daa24b561392de7fda895 (patch) | |
| tree | 7fc2358e6676cd431186eb88005b7778e1035834 | |
| parent | 8fec9355a968ad240f3a2e9ad55b823cf1cc52ff (diff) | |
| parent | c3cdce45f8d3dfa5c3467894aa89798314920328 (diff) | |
Merge tag 'fixes-for-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus
Felipe writes:
usb: fixes for v4.14-rc3
Alan Stern fixed 3 old bugs on dummy_hcd which were reported recently.
Yoshihiro Shimoda continues his work on the renensas_usb3 driver by
fixing several bugs all over the place. The most important of which is
a fix for 2-stage control transfers, previously renesas_usb3 would,
anyway, try to move a 0-length data stage, which is wrong.
Apart from these, there are two minor bug fixes (atmel udc and ffs)
and a new device ID for dwc3-of-simple.c
| -rw-r--r-- | drivers/usb/dwc3/dwc3-of-simple.c | 1 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 17 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/u_fs.h | 1 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/atmel_usba_udc.c | 4 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/dummy_hcd.c | 56 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/renesas_usb3.c | 19 | ||||
| -rw-r--r-- | drivers/usb/renesas_usbhs/fifo.c | 21 |
7 files changed, 101 insertions, 18 deletions
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 4cef7d4f9cd0..a26d1fde0f5e 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c | |||
| @@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = { | |||
| 177 | { .compatible = "rockchip,rk3399-dwc3" }, | 177 | { .compatible = "rockchip,rk3399-dwc3" }, |
| 178 | { .compatible = "xlnx,zynqmp-dwc3" }, | 178 | { .compatible = "xlnx,zynqmp-dwc3" }, |
| 179 | { .compatible = "cavium,octeon-7130-usb-uctl" }, | 179 | { .compatible = "cavium,octeon-7130-usb-uctl" }, |
| 180 | { .compatible = "sprd,sc9860-dwc3" }, | ||
| 180 | { /* Sentinel */ } | 181 | { /* Sentinel */ } |
| 181 | }; | 182 | }; |
| 182 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); | 183 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9990944a7245..8b342587f8ad 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
| @@ -46,7 +46,8 @@ | |||
| 46 | static void ffs_data_get(struct ffs_data *ffs); | 46 | static void ffs_data_get(struct ffs_data *ffs); |
| 47 | static void ffs_data_put(struct ffs_data *ffs); | 47 | static void ffs_data_put(struct ffs_data *ffs); |
| 48 | /* Creates new ffs_data object. */ | 48 | /* Creates new ffs_data object. */ |
| 49 | static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc)); | 49 | static struct ffs_data *__must_check ffs_data_new(const char *dev_name) |
| 50 | __attribute__((malloc)); | ||
| 50 | 51 | ||
| 51 | /* Opened counter handling. */ | 52 | /* Opened counter handling. */ |
| 52 | static void ffs_data_opened(struct ffs_data *ffs); | 53 | static void ffs_data_opened(struct ffs_data *ffs); |
| @@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, | |||
| 780 | struct usb_request *req) | 781 | struct usb_request *req) |
| 781 | { | 782 | { |
| 782 | struct ffs_io_data *io_data = req->context; | 783 | struct ffs_io_data *io_data = req->context; |
| 784 | struct ffs_data *ffs = io_data->ffs; | ||
| 783 | 785 | ||
| 784 | ENTER(); | 786 | ENTER(); |
| 785 | 787 | ||
| 786 | INIT_WORK(&io_data->work, ffs_user_copy_worker); | 788 | INIT_WORK(&io_data->work, ffs_user_copy_worker); |
| 787 | schedule_work(&io_data->work); | 789 | queue_work(ffs->io_completion_wq, &io_data->work); |
| 788 | } | 790 | } |
| 789 | 791 | ||
| 790 | static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) | 792 | static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) |
| @@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, | |||
| 1500 | if (unlikely(ret < 0)) | 1502 | if (unlikely(ret < 0)) |
| 1501 | return ERR_PTR(ret); | 1503 | return ERR_PTR(ret); |
| 1502 | 1504 | ||
| 1503 | ffs = ffs_data_new(); | 1505 | ffs = ffs_data_new(dev_name); |
| 1504 | if (unlikely(!ffs)) | 1506 | if (unlikely(!ffs)) |
| 1505 | return ERR_PTR(-ENOMEM); | 1507 | return ERR_PTR(-ENOMEM); |
| 1506 | ffs->file_perms = data.perms; | 1508 | ffs->file_perms = data.perms; |
| @@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs) | |||
| 1610 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || | 1612 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || |
| 1611 | waitqueue_active(&ffs->ep0req_completion.wait) || | 1613 | waitqueue_active(&ffs->ep0req_completion.wait) || |
| 1612 | waitqueue_active(&ffs->wait)); | 1614 | waitqueue_active(&ffs->wait)); |
| 1615 | destroy_workqueue(ffs->io_completion_wq); | ||
| 1613 | kfree(ffs->dev_name); | 1616 | kfree(ffs->dev_name); |
| 1614 | kfree(ffs); | 1617 | kfree(ffs); |
| 1615 | } | 1618 | } |
| @@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs) | |||
| 1642 | ffs_data_put(ffs); | 1645 | ffs_data_put(ffs); |
| 1643 | } | 1646 | } |
| 1644 | 1647 | ||
| 1645 | static struct ffs_data *ffs_data_new(void) | 1648 | static struct ffs_data *ffs_data_new(const char *dev_name) |
| 1646 | { | 1649 | { |
| 1647 | struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); | 1650 | struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); |
| 1648 | if (unlikely(!ffs)) | 1651 | if (unlikely(!ffs)) |
| @@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void) | |||
| 1650 | 1653 | ||
| 1651 | ENTER(); | 1654 | ENTER(); |
| 1652 | 1655 | ||
| 1656 | ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name); | ||
| 1657 | if (!ffs->io_completion_wq) { | ||
| 1658 | kfree(ffs); | ||
| 1659 | return NULL; | ||
| 1660 | } | ||
| 1661 | |||
| 1653 | refcount_set(&ffs->ref, 1); | 1662 | refcount_set(&ffs->ref, 1); |
| 1654 | atomic_set(&ffs->opened, 0); | 1663 | atomic_set(&ffs->opened, 0); |
| 1655 | ffs->state = FFS_READ_DESCRIPTORS; | 1664 | ffs->state = FFS_READ_DESCRIPTORS; |
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 540f1c48c1a8..79f70ebf85dc 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h | |||
| @@ -279,6 +279,7 @@ struct ffs_data { | |||
| 279 | } file_perms; | 279 | } file_perms; |
| 280 | 280 | ||
| 281 | struct eventfd_ctx *ffs_eventfd; | 281 | struct eventfd_ctx *ffs_eventfd; |
| 282 | struct workqueue_struct *io_completion_wq; | ||
| 282 | bool no_disconnect; | 283 | bool no_disconnect; |
| 283 | struct work_struct reset_work; | 284 | struct work_struct reset_work; |
| 284 | 285 | ||
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 98d71400f8a1..a884c022df7a 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/of_gpio.h> | 29 | #include <linux/of_gpio.h> |
| 30 | 30 | ||
| 31 | #include "atmel_usba_udc.h" | 31 | #include "atmel_usba_udc.h" |
| 32 | #define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \ | ||
| 33 | | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING) | ||
| 32 | 34 | ||
| 33 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 35 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
| 34 | #include <linux/debugfs.h> | 36 | #include <linux/debugfs.h> |
| @@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev) | |||
| 2361 | IRQ_NOAUTOEN); | 2363 | IRQ_NOAUTOEN); |
| 2362 | ret = devm_request_threaded_irq(&pdev->dev, | 2364 | ret = devm_request_threaded_irq(&pdev->dev, |
| 2363 | gpio_to_irq(udc->vbus_pin), NULL, | 2365 | gpio_to_irq(udc->vbus_pin), NULL, |
| 2364 | usba_vbus_irq_thread, IRQF_ONESHOT, | 2366 | usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, |
| 2365 | "atmel_usba_udc", udc); | 2367 | "atmel_usba_udc", udc); |
| 2366 | if (ret) { | 2368 | if (ret) { |
| 2367 | udc->vbus_pin = -ENODEV; | 2369 | udc->vbus_pin = -ENODEV; |
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index b1e21b3be6e1..b17618a55f1b 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c | |||
| @@ -237,6 +237,8 @@ struct dummy_hcd { | |||
| 237 | 237 | ||
| 238 | struct usb_device *udev; | 238 | struct usb_device *udev; |
| 239 | struct list_head urbp_list; | 239 | struct list_head urbp_list; |
| 240 | struct urbp *next_frame_urbp; | ||
| 241 | |||
| 240 | u32 stream_en_ep; | 242 | u32 stream_en_ep; |
| 241 | u8 num_stream[30 / 2]; | 243 | u8 num_stream[30 / 2]; |
| 242 | 244 | ||
| @@ -253,11 +255,13 @@ struct dummy { | |||
| 253 | */ | 255 | */ |
| 254 | struct dummy_ep ep[DUMMY_ENDPOINTS]; | 256 | struct dummy_ep ep[DUMMY_ENDPOINTS]; |
| 255 | int address; | 257 | int address; |
| 258 | int callback_usage; | ||
| 256 | struct usb_gadget gadget; | 259 | struct usb_gadget gadget; |
| 257 | struct usb_gadget_driver *driver; | 260 | struct usb_gadget_driver *driver; |
| 258 | struct dummy_request fifo_req; | 261 | struct dummy_request fifo_req; |
| 259 | u8 fifo_buf[FIFO_SIZE]; | 262 | u8 fifo_buf[FIFO_SIZE]; |
| 260 | u16 devstatus; | 263 | u16 devstatus; |
| 264 | unsigned ints_enabled:1; | ||
| 261 | unsigned udc_suspended:1; | 265 | unsigned udc_suspended:1; |
| 262 | unsigned pullup:1; | 266 | unsigned pullup:1; |
| 263 | 267 | ||
| @@ -439,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd) | |||
| 439 | (~dum_hcd->old_status) & dum_hcd->port_status; | 443 | (~dum_hcd->old_status) & dum_hcd->port_status; |
| 440 | 444 | ||
| 441 | /* Report reset and disconnect events to the driver */ | 445 | /* Report reset and disconnect events to the driver */ |
| 442 | if (dum->driver && (disconnect || reset)) { | 446 | if (dum->ints_enabled && (disconnect || reset)) { |
| 443 | stop_activity(dum); | 447 | stop_activity(dum); |
| 448 | ++dum->callback_usage; | ||
| 449 | spin_unlock(&dum->lock); | ||
| 444 | if (reset) | 450 | if (reset) |
| 445 | usb_gadget_udc_reset(&dum->gadget, dum->driver); | 451 | usb_gadget_udc_reset(&dum->gadget, dum->driver); |
| 446 | else | 452 | else |
| 447 | dum->driver->disconnect(&dum->gadget); | 453 | dum->driver->disconnect(&dum->gadget); |
| 454 | spin_lock(&dum->lock); | ||
| 455 | --dum->callback_usage; | ||
| 448 | } | 456 | } |
| 449 | } else if (dum_hcd->active != dum_hcd->old_active) { | 457 | } else if (dum_hcd->active != dum_hcd->old_active && |
| 458 | dum->ints_enabled) { | ||
| 459 | ++dum->callback_usage; | ||
| 460 | spin_unlock(&dum->lock); | ||
| 450 | if (dum_hcd->old_active && dum->driver->suspend) | 461 | if (dum_hcd->old_active && dum->driver->suspend) |
| 451 | dum->driver->suspend(&dum->gadget); | 462 | dum->driver->suspend(&dum->gadget); |
| 452 | else if (!dum_hcd->old_active && dum->driver->resume) | 463 | else if (!dum_hcd->old_active && dum->driver->resume) |
| 453 | dum->driver->resume(&dum->gadget); | 464 | dum->driver->resume(&dum->gadget); |
| 465 | spin_lock(&dum->lock); | ||
| 466 | --dum->callback_usage; | ||
| 454 | } | 467 | } |
| 455 | 468 | ||
| 456 | dum_hcd->old_status = dum_hcd->port_status; | 469 | dum_hcd->old_status = dum_hcd->port_status; |
| @@ -971,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g, | |||
| 971 | * can't enumerate without help from the driver we're binding. | 984 | * can't enumerate without help from the driver we're binding. |
| 972 | */ | 985 | */ |
| 973 | 986 | ||
| 987 | spin_lock_irq(&dum->lock); | ||
| 974 | dum->devstatus = 0; | 988 | dum->devstatus = 0; |
| 975 | dum->driver = driver; | 989 | dum->driver = driver; |
| 990 | dum->ints_enabled = 1; | ||
| 991 | spin_unlock_irq(&dum->lock); | ||
| 976 | 992 | ||
| 977 | return 0; | 993 | return 0; |
| 978 | } | 994 | } |
| @@ -983,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g) | |||
| 983 | struct dummy *dum = dum_hcd->dum; | 999 | struct dummy *dum = dum_hcd->dum; |
| 984 | 1000 | ||
| 985 | spin_lock_irq(&dum->lock); | 1001 | spin_lock_irq(&dum->lock); |
| 1002 | dum->ints_enabled = 0; | ||
| 1003 | stop_activity(dum); | ||
| 1004 | |||
| 1005 | /* emulate synchronize_irq(): wait for callbacks to finish */ | ||
| 1006 | while (dum->callback_usage > 0) { | ||
| 1007 | spin_unlock_irq(&dum->lock); | ||
| 1008 | usleep_range(1000, 2000); | ||
| 1009 | spin_lock_irq(&dum->lock); | ||
| 1010 | } | ||
| 1011 | |||
| 986 | dum->driver = NULL; | 1012 | dum->driver = NULL; |
| 987 | spin_unlock_irq(&dum->lock); | 1013 | spin_unlock_irq(&dum->lock); |
| 988 | 1014 | ||
| @@ -1036,7 +1062,12 @@ static int dummy_udc_probe(struct platform_device *pdev) | |||
| 1036 | memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); | 1062 | memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); |
| 1037 | dum->gadget.name = gadget_name; | 1063 | dum->gadget.name = gadget_name; |
| 1038 | dum->gadget.ops = &dummy_ops; | 1064 | dum->gadget.ops = &dummy_ops; |
| 1039 | dum->gadget.max_speed = USB_SPEED_SUPER; | 1065 | if (mod_data.is_super_speed) |
| 1066 | dum->gadget.max_speed = USB_SPEED_SUPER; | ||
| 1067 | else if (mod_data.is_high_speed) | ||
| 1068 | dum->gadget.max_speed = USB_SPEED_HIGH; | ||
| 1069 | else | ||
| 1070 | dum->gadget.max_speed = USB_SPEED_FULL; | ||
| 1040 | 1071 | ||
| 1041 | dum->gadget.dev.parent = &pdev->dev; | 1072 | dum->gadget.dev.parent = &pdev->dev; |
| 1042 | init_dummy_udc_hw(dum); | 1073 | init_dummy_udc_hw(dum); |
| @@ -1245,6 +1276,8 @@ static int dummy_urb_enqueue( | |||
| 1245 | 1276 | ||
| 1246 | list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); | 1277 | list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); |
| 1247 | urb->hcpriv = urbp; | 1278 | urb->hcpriv = urbp; |
| 1279 | if (!dum_hcd->next_frame_urbp) | ||
| 1280 | dum_hcd->next_frame_urbp = urbp; | ||
| 1248 | if (usb_pipetype(urb->pipe) == PIPE_CONTROL) | 1281 | if (usb_pipetype(urb->pipe) == PIPE_CONTROL) |
| 1249 | urb->error_count = 1; /* mark as a new urb */ | 1282 | urb->error_count = 1; /* mark as a new urb */ |
| 1250 | 1283 | ||
| @@ -1520,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address) | |||
| 1520 | if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? | 1553 | if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? |
| 1521 | dum->ss_hcd : dum->hs_hcd))) | 1554 | dum->ss_hcd : dum->hs_hcd))) |
| 1522 | return NULL; | 1555 | return NULL; |
| 1556 | if (!dum->ints_enabled) | ||
| 1557 | return NULL; | ||
| 1523 | if ((address & ~USB_DIR_IN) == 0) | 1558 | if ((address & ~USB_DIR_IN) == 0) |
| 1524 | return &dum->ep[0]; | 1559 | return &dum->ep[0]; |
| 1525 | for (i = 1; i < DUMMY_ENDPOINTS; i++) { | 1560 | for (i = 1; i < DUMMY_ENDPOINTS; i++) { |
| @@ -1761,6 +1796,7 @@ static void dummy_timer(unsigned long _dum_hcd) | |||
| 1761 | spin_unlock_irqrestore(&dum->lock, flags); | 1796 | spin_unlock_irqrestore(&dum->lock, flags); |
| 1762 | return; | 1797 | return; |
| 1763 | } | 1798 | } |
| 1799 | dum_hcd->next_frame_urbp = NULL; | ||
| 1764 | 1800 | ||
| 1765 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { | 1801 | for (i = 0; i < DUMMY_ENDPOINTS; i++) { |
| 1766 | if (!ep_info[i].name) | 1802 | if (!ep_info[i].name) |
| @@ -1777,6 +1813,10 @@ restart: | |||
| 1777 | int type; | 1813 | int type; |
| 1778 | int status = -EINPROGRESS; | 1814 | int status = -EINPROGRESS; |
| 1779 | 1815 | ||
| 1816 | /* stop when we reach URBs queued after the timer interrupt */ | ||
| 1817 | if (urbp == dum_hcd->next_frame_urbp) | ||
| 1818 | break; | ||
| 1819 | |||
| 1780 | urb = urbp->urb; | 1820 | urb = urbp->urb; |
| 1781 | if (urb->unlinked) | 1821 | if (urb->unlinked) |
| 1782 | goto return_urb; | 1822 | goto return_urb; |
| @@ -1856,10 +1896,12 @@ restart: | |||
| 1856 | * until setup() returns; no reentrancy issues etc. | 1896 | * until setup() returns; no reentrancy issues etc. |
| 1857 | */ | 1897 | */ |
| 1858 | if (value > 0) { | 1898 | if (value > 0) { |
| 1899 | ++dum->callback_usage; | ||
| 1859 | spin_unlock(&dum->lock); | 1900 | spin_unlock(&dum->lock); |
| 1860 | value = dum->driver->setup(&dum->gadget, | 1901 | value = dum->driver->setup(&dum->gadget, |
| 1861 | &setup); | 1902 | &setup); |
| 1862 | spin_lock(&dum->lock); | 1903 | spin_lock(&dum->lock); |
| 1904 | --dum->callback_usage; | ||
| 1863 | 1905 | ||
| 1864 | if (value >= 0) { | 1906 | if (value >= 0) { |
| 1865 | /* no delays (max 64KB data stage) */ | 1907 | /* no delays (max 64KB data stage) */ |
| @@ -2560,8 +2602,6 @@ static struct hc_driver dummy_hcd = { | |||
| 2560 | .product_desc = "Dummy host controller", | 2602 | .product_desc = "Dummy host controller", |
| 2561 | .hcd_priv_size = sizeof(struct dummy_hcd), | 2603 | .hcd_priv_size = sizeof(struct dummy_hcd), |
| 2562 | 2604 | ||
| 2563 | .flags = HCD_USB3 | HCD_SHARED, | ||
| 2564 | |||
| 2565 | .reset = dummy_setup, | 2605 | .reset = dummy_setup, |
| 2566 | .start = dummy_start, | 2606 | .start = dummy_start, |
| 2567 | .stop = dummy_stop, | 2607 | .stop = dummy_stop, |
| @@ -2590,8 +2630,12 @@ static int dummy_hcd_probe(struct platform_device *pdev) | |||
| 2590 | dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); | 2630 | dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); |
| 2591 | dum = *((void **)dev_get_platdata(&pdev->dev)); | 2631 | dum = *((void **)dev_get_platdata(&pdev->dev)); |
| 2592 | 2632 | ||
| 2593 | if (!mod_data.is_super_speed) | 2633 | if (mod_data.is_super_speed) |
| 2634 | dummy_hcd.flags = HCD_USB3 | HCD_SHARED; | ||
| 2635 | else if (mod_data.is_high_speed) | ||
| 2594 | dummy_hcd.flags = HCD_USB2; | 2636 | dummy_hcd.flags = HCD_USB2; |
| 2637 | else | ||
| 2638 | dummy_hcd.flags = HCD_USB11; | ||
| 2595 | hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); | 2639 | hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); |
| 2596 | if (!hs_hcd) | 2640 | if (!hs_hcd) |
| 2597 | return -ENOMEM; | 2641 | return -ENOMEM; |
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index df37c1e6e9d5..63a206122058 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c | |||
| @@ -1038,7 +1038,7 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, | |||
| 1038 | usb3_ep->ep.maxpacket); | 1038 | usb3_ep->ep.maxpacket); |
| 1039 | u8 *buf = usb3_req->req.buf + usb3_req->req.actual; | 1039 | u8 *buf = usb3_req->req.buf + usb3_req->req.actual; |
| 1040 | u32 tmp = 0; | 1040 | u32 tmp = 0; |
| 1041 | bool is_last; | 1041 | bool is_last = !len ? true : false; |
| 1042 | 1042 | ||
| 1043 | if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0) | 1043 | if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0) |
| 1044 | return -EBUSY; | 1044 | return -EBUSY; |
| @@ -1059,7 +1059,8 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, | |||
| 1059 | usb3_write(usb3, tmp, fifo_reg); | 1059 | usb3_write(usb3, tmp, fifo_reg); |
| 1060 | } | 1060 | } |
| 1061 | 1061 | ||
| 1062 | is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); | 1062 | if (!is_last) |
| 1063 | is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); | ||
| 1063 | /* Send the data */ | 1064 | /* Send the data */ |
| 1064 | usb3_set_px_con_send(usb3_ep, len, is_last); | 1065 | usb3_set_px_con_send(usb3_ep, len, is_last); |
| 1065 | 1066 | ||
| @@ -1150,7 +1151,8 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep, | |||
| 1150 | usb3_set_p0_con_for_ctrl_read_data(usb3); | 1151 | usb3_set_p0_con_for_ctrl_read_data(usb3); |
| 1151 | } else { | 1152 | } else { |
| 1152 | usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); | 1153 | usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); |
| 1153 | usb3_set_p0_con_for_ctrl_write_data(usb3); | 1154 | if (usb3_req->req.length) |
| 1155 | usb3_set_p0_con_for_ctrl_write_data(usb3); | ||
| 1154 | } | 1156 | } |
| 1155 | 1157 | ||
| 1156 | usb3_p0_xfer(usb3_ep, usb3_req); | 1158 | usb3_p0_xfer(usb3_ep, usb3_req); |
| @@ -2053,7 +2055,16 @@ static u32 usb3_calc_ramarea(int ram_size) | |||
| 2053 | static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep, | 2055 | static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep, |
| 2054 | const struct usb_endpoint_descriptor *desc) | 2056 | const struct usb_endpoint_descriptor *desc) |
| 2055 | { | 2057 | { |
| 2056 | return usb3_ep->rammap_val | PN_RAMMAP_MPKT(usb_endpoint_maxp(desc)); | 2058 | int i; |
| 2059 | const u32 max_packet_array[] = {8, 16, 32, 64, 512}; | ||
| 2060 | u32 mpkt = PN_RAMMAP_MPKT(1024); | ||
| 2061 | |||
| 2062 | for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) { | ||
| 2063 | if (usb_endpoint_maxp(desc) <= max_packet_array[i]) | ||
| 2064 | mpkt = PN_RAMMAP_MPKT(max_packet_array[i]); | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | return usb3_ep->rammap_val | mpkt; | ||
| 2057 | } | 2068 | } |
| 2058 | 2069 | ||
| 2059 | static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep, | 2070 | static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep, |
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index d1af831f43eb..68f26904c316 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c | |||
| @@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, | |||
| 282 | struct usbhs_fifo *fifo) | 282 | struct usbhs_fifo *fifo) |
| 283 | { | 283 | { |
| 284 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); | 284 | struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
| 285 | int ret = 0; | ||
| 285 | 286 | ||
| 286 | if (!usbhs_pipe_is_dcp(pipe)) | 287 | if (!usbhs_pipe_is_dcp(pipe)) { |
| 287 | usbhsf_fifo_barrier(priv, fifo); | 288 | /* |
| 289 | * This driver checks the pipe condition first to avoid -EBUSY | ||
| 290 | * from usbhsf_fifo_barrier() with about 10 msec delay in | ||
| 291 | * the interrupt handler if the pipe is RX direction and empty. | ||
| 292 | */ | ||
| 293 | if (usbhs_pipe_is_dir_in(pipe)) | ||
| 294 | ret = usbhs_pipe_is_accessible(pipe); | ||
| 295 | if (!ret) | ||
| 296 | ret = usbhsf_fifo_barrier(priv, fifo); | ||
| 297 | } | ||
| 288 | 298 | ||
| 289 | usbhs_write(priv, fifo->ctr, BCLR); | 299 | /* |
| 300 | * if non-DCP pipe, this driver should set BCLR when | ||
| 301 | * usbhsf_fifo_barrier() returns 0. | ||
| 302 | */ | ||
| 303 | if (!ret) | ||
| 304 | usbhs_write(priv, fifo->ctr, BCLR); | ||
| 290 | } | 305 | } |
| 291 | 306 | ||
| 292 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, | 307 | static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, |
