提交 80c82ffe 编写于 作者: G Greg Kroah-Hartman

Merge tag 'fixes-for-v4.14-rc3' of...

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
...@@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = { ...@@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = {
{ .compatible = "rockchip,rk3399-dwc3" }, { .compatible = "rockchip,rk3399-dwc3" },
{ .compatible = "xlnx,zynqmp-dwc3" }, { .compatible = "xlnx,zynqmp-dwc3" },
{ .compatible = "cavium,octeon-7130-usb-uctl" }, { .compatible = "cavium,octeon-7130-usb-uctl" },
{ .compatible = "sprd,sc9860-dwc3" },
{ /* Sentinel */ } { /* Sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
......
...@@ -46,7 +46,8 @@ ...@@ -46,7 +46,8 @@
static void ffs_data_get(struct ffs_data *ffs); static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs); static void ffs_data_put(struct ffs_data *ffs);
/* Creates new ffs_data object. */ /* Creates new ffs_data object. */
static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc)); static struct ffs_data *__must_check ffs_data_new(const char *dev_name)
__attribute__((malloc));
/* Opened counter handling. */ /* Opened counter handling. */
static void ffs_data_opened(struct ffs_data *ffs); 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,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
struct usb_request *req) struct usb_request *req)
{ {
struct ffs_io_data *io_data = req->context; struct ffs_io_data *io_data = req->context;
struct ffs_data *ffs = io_data->ffs;
ENTER(); ENTER();
INIT_WORK(&io_data->work, ffs_user_copy_worker); INIT_WORK(&io_data->work, ffs_user_copy_worker);
schedule_work(&io_data->work); queue_work(ffs->io_completion_wq, &io_data->work);
} }
static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) 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,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
if (unlikely(ret < 0)) if (unlikely(ret < 0))
return ERR_PTR(ret); return ERR_PTR(ret);
ffs = ffs_data_new(); ffs = ffs_data_new(dev_name);
if (unlikely(!ffs)) if (unlikely(!ffs))
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ffs->file_perms = data.perms; ffs->file_perms = data.perms;
...@@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs) ...@@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)
BUG_ON(waitqueue_active(&ffs->ev.waitq) || BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
waitqueue_active(&ffs->ep0req_completion.wait) || waitqueue_active(&ffs->ep0req_completion.wait) ||
waitqueue_active(&ffs->wait)); waitqueue_active(&ffs->wait));
destroy_workqueue(ffs->io_completion_wq);
kfree(ffs->dev_name); kfree(ffs->dev_name);
kfree(ffs); kfree(ffs);
} }
...@@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs) ...@@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
ffs_data_put(ffs); ffs_data_put(ffs);
} }
static struct ffs_data *ffs_data_new(void) static struct ffs_data *ffs_data_new(const char *dev_name)
{ {
struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
if (unlikely(!ffs)) if (unlikely(!ffs))
...@@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void) ...@@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void)
ENTER(); ENTER();
ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
if (!ffs->io_completion_wq) {
kfree(ffs);
return NULL;
}
refcount_set(&ffs->ref, 1); refcount_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0); atomic_set(&ffs->opened, 0);
ffs->state = FFS_READ_DESCRIPTORS; ffs->state = FFS_READ_DESCRIPTORS;
......
...@@ -279,6 +279,7 @@ struct ffs_data { ...@@ -279,6 +279,7 @@ struct ffs_data {
} file_perms; } file_perms;
struct eventfd_ctx *ffs_eventfd; struct eventfd_ctx *ffs_eventfd;
struct workqueue_struct *io_completion_wq;
bool no_disconnect; bool no_disconnect;
struct work_struct reset_work; struct work_struct reset_work;
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include "atmel_usba_udc.h" #include "atmel_usba_udc.h"
#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \
| IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)
#ifdef CONFIG_USB_GADGET_DEBUG_FS #ifdef CONFIG_USB_GADGET_DEBUG_FS
#include <linux/debugfs.h> #include <linux/debugfs.h>
...@@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev) ...@@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev)
IRQ_NOAUTOEN); IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(&pdev->dev, ret = devm_request_threaded_irq(&pdev->dev,
gpio_to_irq(udc->vbus_pin), NULL, gpio_to_irq(udc->vbus_pin), NULL,
usba_vbus_irq_thread, IRQF_ONESHOT, usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS,
"atmel_usba_udc", udc); "atmel_usba_udc", udc);
if (ret) { if (ret) {
udc->vbus_pin = -ENODEV; udc->vbus_pin = -ENODEV;
......
...@@ -237,6 +237,8 @@ struct dummy_hcd { ...@@ -237,6 +237,8 @@ struct dummy_hcd {
struct usb_device *udev; struct usb_device *udev;
struct list_head urbp_list; struct list_head urbp_list;
struct urbp *next_frame_urbp;
u32 stream_en_ep; u32 stream_en_ep;
u8 num_stream[30 / 2]; u8 num_stream[30 / 2];
...@@ -253,11 +255,13 @@ struct dummy { ...@@ -253,11 +255,13 @@ struct dummy {
*/ */
struct dummy_ep ep[DUMMY_ENDPOINTS]; struct dummy_ep ep[DUMMY_ENDPOINTS];
int address; int address;
int callback_usage;
struct usb_gadget gadget; struct usb_gadget gadget;
struct usb_gadget_driver *driver; struct usb_gadget_driver *driver;
struct dummy_request fifo_req; struct dummy_request fifo_req;
u8 fifo_buf[FIFO_SIZE]; u8 fifo_buf[FIFO_SIZE];
u16 devstatus; u16 devstatus;
unsigned ints_enabled:1;
unsigned udc_suspended:1; unsigned udc_suspended:1;
unsigned pullup:1; unsigned pullup:1;
...@@ -439,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd) ...@@ -439,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
(~dum_hcd->old_status) & dum_hcd->port_status; (~dum_hcd->old_status) & dum_hcd->port_status;
/* Report reset and disconnect events to the driver */ /* Report reset and disconnect events to the driver */
if (dum->driver && (disconnect || reset)) { if (dum->ints_enabled && (disconnect || reset)) {
stop_activity(dum); stop_activity(dum);
++dum->callback_usage;
spin_unlock(&dum->lock);
if (reset) if (reset)
usb_gadget_udc_reset(&dum->gadget, dum->driver); usb_gadget_udc_reset(&dum->gadget, dum->driver);
else else
dum->driver->disconnect(&dum->gadget); dum->driver->disconnect(&dum->gadget);
spin_lock(&dum->lock);
--dum->callback_usage;
} }
} else if (dum_hcd->active != dum_hcd->old_active) { } else if (dum_hcd->active != dum_hcd->old_active &&
dum->ints_enabled) {
++dum->callback_usage;
spin_unlock(&dum->lock);
if (dum_hcd->old_active && dum->driver->suspend) if (dum_hcd->old_active && dum->driver->suspend)
dum->driver->suspend(&dum->gadget); dum->driver->suspend(&dum->gadget);
else if (!dum_hcd->old_active && dum->driver->resume) else if (!dum_hcd->old_active && dum->driver->resume)
dum->driver->resume(&dum->gadget); dum->driver->resume(&dum->gadget);
spin_lock(&dum->lock);
--dum->callback_usage;
} }
dum_hcd->old_status = dum_hcd->port_status; dum_hcd->old_status = dum_hcd->port_status;
...@@ -971,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g, ...@@ -971,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g,
* can't enumerate without help from the driver we're binding. * can't enumerate without help from the driver we're binding.
*/ */
spin_lock_irq(&dum->lock);
dum->devstatus = 0; dum->devstatus = 0;
dum->driver = driver; dum->driver = driver;
dum->ints_enabled = 1;
spin_unlock_irq(&dum->lock);
return 0; return 0;
} }
...@@ -983,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g) ...@@ -983,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g)
struct dummy *dum = dum_hcd->dum; struct dummy *dum = dum_hcd->dum;
spin_lock_irq(&dum->lock); spin_lock_irq(&dum->lock);
dum->ints_enabled = 0;
stop_activity(dum);
/* emulate synchronize_irq(): wait for callbacks to finish */
while (dum->callback_usage > 0) {
spin_unlock_irq(&dum->lock);
usleep_range(1000, 2000);
spin_lock_irq(&dum->lock);
}
dum->driver = NULL; dum->driver = NULL;
spin_unlock_irq(&dum->lock); spin_unlock_irq(&dum->lock);
...@@ -1036,7 +1062,12 @@ static int dummy_udc_probe(struct platform_device *pdev) ...@@ -1036,7 +1062,12 @@ static int dummy_udc_probe(struct platform_device *pdev)
memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
dum->gadget.name = gadget_name; dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops; dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER; if (mod_data.is_super_speed)
dum->gadget.max_speed = USB_SPEED_SUPER;
else if (mod_data.is_high_speed)
dum->gadget.max_speed = USB_SPEED_HIGH;
else
dum->gadget.max_speed = USB_SPEED_FULL;
dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.parent = &pdev->dev;
init_dummy_udc_hw(dum); init_dummy_udc_hw(dum);
...@@ -1245,6 +1276,8 @@ static int dummy_urb_enqueue( ...@@ -1245,6 +1276,8 @@ static int dummy_urb_enqueue(
list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
urb->hcpriv = urbp; urb->hcpriv = urbp;
if (!dum_hcd->next_frame_urbp)
dum_hcd->next_frame_urbp = urbp;
if (usb_pipetype(urb->pipe) == PIPE_CONTROL) if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
urb->error_count = 1; /* mark as a new urb */ urb->error_count = 1; /* mark as a new urb */
...@@ -1520,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address) ...@@ -1520,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
dum->ss_hcd : dum->hs_hcd))) dum->ss_hcd : dum->hs_hcd)))
return NULL; return NULL;
if (!dum->ints_enabled)
return NULL;
if ((address & ~USB_DIR_IN) == 0) if ((address & ~USB_DIR_IN) == 0)
return &dum->ep[0]; return &dum->ep[0];
for (i = 1; i < DUMMY_ENDPOINTS; i++) { for (i = 1; i < DUMMY_ENDPOINTS; i++) {
...@@ -1761,6 +1796,7 @@ static void dummy_timer(unsigned long _dum_hcd) ...@@ -1761,6 +1796,7 @@ static void dummy_timer(unsigned long _dum_hcd)
spin_unlock_irqrestore(&dum->lock, flags); spin_unlock_irqrestore(&dum->lock, flags);
return; return;
} }
dum_hcd->next_frame_urbp = NULL;
for (i = 0; i < DUMMY_ENDPOINTS; i++) { for (i = 0; i < DUMMY_ENDPOINTS; i++) {
if (!ep_info[i].name) if (!ep_info[i].name)
...@@ -1777,6 +1813,10 @@ static void dummy_timer(unsigned long _dum_hcd) ...@@ -1777,6 +1813,10 @@ static void dummy_timer(unsigned long _dum_hcd)
int type; int type;
int status = -EINPROGRESS; int status = -EINPROGRESS;
/* stop when we reach URBs queued after the timer interrupt */
if (urbp == dum_hcd->next_frame_urbp)
break;
urb = urbp->urb; urb = urbp->urb;
if (urb->unlinked) if (urb->unlinked)
goto return_urb; goto return_urb;
...@@ -1856,10 +1896,12 @@ static void dummy_timer(unsigned long _dum_hcd) ...@@ -1856,10 +1896,12 @@ static void dummy_timer(unsigned long _dum_hcd)
* until setup() returns; no reentrancy issues etc. * until setup() returns; no reentrancy issues etc.
*/ */
if (value > 0) { if (value > 0) {
++dum->callback_usage;
spin_unlock(&dum->lock); spin_unlock(&dum->lock);
value = dum->driver->setup(&dum->gadget, value = dum->driver->setup(&dum->gadget,
&setup); &setup);
spin_lock(&dum->lock); spin_lock(&dum->lock);
--dum->callback_usage;
if (value >= 0) { if (value >= 0) {
/* no delays (max 64KB data stage) */ /* no delays (max 64KB data stage) */
...@@ -2560,8 +2602,6 @@ static struct hc_driver dummy_hcd = { ...@@ -2560,8 +2602,6 @@ static struct hc_driver dummy_hcd = {
.product_desc = "Dummy host controller", .product_desc = "Dummy host controller",
.hcd_priv_size = sizeof(struct dummy_hcd), .hcd_priv_size = sizeof(struct dummy_hcd),
.flags = HCD_USB3 | HCD_SHARED,
.reset = dummy_setup, .reset = dummy_setup,
.start = dummy_start, .start = dummy_start,
.stop = dummy_stop, .stop = dummy_stop,
...@@ -2590,8 +2630,12 @@ static int dummy_hcd_probe(struct platform_device *pdev) ...@@ -2590,8 +2630,12 @@ static int dummy_hcd_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
dum = *((void **)dev_get_platdata(&pdev->dev)); dum = *((void **)dev_get_platdata(&pdev->dev));
if (!mod_data.is_super_speed) if (mod_data.is_super_speed)
dummy_hcd.flags = HCD_USB3 | HCD_SHARED;
else if (mod_data.is_high_speed)
dummy_hcd.flags = HCD_USB2; dummy_hcd.flags = HCD_USB2;
else
dummy_hcd.flags = HCD_USB11;
hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
if (!hs_hcd) if (!hs_hcd)
return -ENOMEM; return -ENOMEM;
......
...@@ -1038,7 +1038,7 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, ...@@ -1038,7 +1038,7 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
usb3_ep->ep.maxpacket); usb3_ep->ep.maxpacket);
u8 *buf = usb3_req->req.buf + usb3_req->req.actual; u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
u32 tmp = 0; u32 tmp = 0;
bool is_last; bool is_last = !len ? true : false;
if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0) if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0)
return -EBUSY; return -EBUSY;
...@@ -1059,7 +1059,8 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, ...@@ -1059,7 +1059,8 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
usb3_write(usb3, tmp, fifo_reg); usb3_write(usb3, tmp, fifo_reg);
} }
is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); if (!is_last)
is_last = usb3_is_transfer_complete(usb3_ep, usb3_req);
/* Send the data */ /* Send the data */
usb3_set_px_con_send(usb3_ep, len, is_last); usb3_set_px_con_send(usb3_ep, len, is_last);
...@@ -1150,7 +1151,8 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep, ...@@ -1150,7 +1151,8 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep,
usb3_set_p0_con_for_ctrl_read_data(usb3); usb3_set_p0_con_for_ctrl_read_data(usb3);
} else { } else {
usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
usb3_set_p0_con_for_ctrl_write_data(usb3); if (usb3_req->req.length)
usb3_set_p0_con_for_ctrl_write_data(usb3);
} }
usb3_p0_xfer(usb3_ep, usb3_req); usb3_p0_xfer(usb3_ep, usb3_req);
...@@ -2053,7 +2055,16 @@ static u32 usb3_calc_ramarea(int ram_size) ...@@ -2053,7 +2055,16 @@ static u32 usb3_calc_ramarea(int ram_size)
static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep, static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep,
const struct usb_endpoint_descriptor *desc) const struct usb_endpoint_descriptor *desc)
{ {
return usb3_ep->rammap_val | PN_RAMMAP_MPKT(usb_endpoint_maxp(desc)); int i;
const u32 max_packet_array[] = {8, 16, 32, 64, 512};
u32 mpkt = PN_RAMMAP_MPKT(1024);
for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) {
if (usb_endpoint_maxp(desc) <= max_packet_array[i])
mpkt = PN_RAMMAP_MPKT(max_packet_array[i]);
}
return usb3_ep->rammap_val | mpkt;
} }
static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep, static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep,
......
...@@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, ...@@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
struct usbhs_fifo *fifo) struct usbhs_fifo *fifo)
{ {
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
int ret = 0;
if (!usbhs_pipe_is_dcp(pipe)) if (!usbhs_pipe_is_dcp(pipe)) {
usbhsf_fifo_barrier(priv, fifo); /*
* This driver checks the pipe condition first to avoid -EBUSY
* from usbhsf_fifo_barrier() with about 10 msec delay in
* the interrupt handler if the pipe is RX direction and empty.
*/
if (usbhs_pipe_is_dir_in(pipe))
ret = usbhs_pipe_is_accessible(pipe);
if (!ret)
ret = usbhsf_fifo_barrier(priv, fifo);
}
usbhs_write(priv, fifo->ctr, BCLR); /*
* if non-DCP pipe, this driver should set BCLR when
* usbhsf_fifo_barrier() returns 0.
*/
if (!ret)
usbhs_write(priv, fifo->ctr, BCLR);
} }
static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册