Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80c82ffe authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

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
parents 8fec9355 c3cdce45
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = {
	{ .compatible = "rockchip,rk3399-dwc3" },
	{ .compatible = "xlnx,zynqmp-dwc3" },
	{ .compatible = "cavium,octeon-7130-usb-uctl" },
	{ .compatible = "sprd,sc9860-dwc3" },
	{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
+13 −4
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@
static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs);
/* 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. */
static void ffs_data_opened(struct ffs_data *ffs);
@@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
					 struct usb_request *req)
{
	struct ffs_io_data *io_data = req->context;
	struct ffs_data *ffs = io_data->ffs;

	ENTER();

	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)
@@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
	if (unlikely(ret < 0))
		return ERR_PTR(ret);

	ffs = ffs_data_new();
	ffs = ffs_data_new(dev_name);
	if (unlikely(!ffs))
		return ERR_PTR(-ENOMEM);
	ffs->file_perms = data.perms;
@@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)
		BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
		       waitqueue_active(&ffs->ep0req_completion.wait) ||
		       waitqueue_active(&ffs->wait));
		destroy_workqueue(ffs->io_completion_wq);
		kfree(ffs->dev_name);
		kfree(ffs);
	}
@@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *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);
	if (unlikely(!ffs))
@@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void)

	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);
	atomic_set(&ffs->opened, 0);
	ffs->state = FFS_READ_DESCRIPTORS;
+1 −0
Original line number Diff line number Diff line
@@ -279,6 +279,7 @@ struct ffs_data {
	}				file_perms;

	struct eventfd_ctx *ffs_eventfd;
	struct workqueue_struct *io_completion_wq;
	bool no_disconnect;
	struct work_struct reset_work;

+3 −1
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#include <linux/of_gpio.h>

#include "atmel_usba_udc.h"
#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \
			   | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)

#ifdef CONFIG_USB_GADGET_DEBUG_FS
#include <linux/debugfs.h>
@@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev)
					IRQ_NOAUTOEN);
			ret = devm_request_threaded_irq(&pdev->dev,
					gpio_to_irq(udc->vbus_pin), NULL,
					usba_vbus_irq_thread, IRQF_ONESHOT,
					usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS,
					"atmel_usba_udc", udc);
			if (ret) {
				udc->vbus_pin = -ENODEV;
+50 −6
Original line number Diff line number Diff line
@@ -237,6 +237,8 @@ struct dummy_hcd {

	struct usb_device		*udev;
	struct list_head		urbp_list;
	struct urbp			*next_frame_urbp;

	u32				stream_en_ep;
	u8				num_stream[30 / 2];

@@ -253,11 +255,13 @@ struct dummy {
	 */
	struct dummy_ep			ep[DUMMY_ENDPOINTS];
	int				address;
	int				callback_usage;
	struct usb_gadget		gadget;
	struct usb_gadget_driver	*driver;
	struct dummy_request		fifo_req;
	u8				fifo_buf[FIFO_SIZE];
	u16				devstatus;
	unsigned			ints_enabled:1;
	unsigned			udc_suspended:1;
	unsigned			pullup:1;

@@ -439,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
				(~dum_hcd->old_status) & dum_hcd->port_status;

		/* Report reset and disconnect events to the driver */
		if (dum->driver && (disconnect || reset)) {
		if (dum->ints_enabled && (disconnect || reset)) {
			stop_activity(dum);
			++dum->callback_usage;
			spin_unlock(&dum->lock);
			if (reset)
				usb_gadget_udc_reset(&dum->gadget, dum->driver);
			else
				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)
			dum->driver->suspend(&dum->gadget);
		else if (!dum_hcd->old_active &&  dum->driver->resume)
			dum->driver->resume(&dum->gadget);
		spin_lock(&dum->lock);
		--dum->callback_usage;
	}

	dum_hcd->old_status = dum_hcd->port_status;
@@ -971,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g,
	 * can't enumerate without help from the driver we're binding.
	 */

	spin_lock_irq(&dum->lock);
	dum->devstatus = 0;
	dum->driver = driver;
	dum->ints_enabled = 1;
	spin_unlock_irq(&dum->lock);

	return 0;
}
@@ -983,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g)
	struct dummy		*dum = dum_hcd->dum;

	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;
	spin_unlock_irq(&dum->lock);

@@ -1036,7 +1062,12 @@ static int dummy_udc_probe(struct platform_device *pdev)
	memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
	dum->gadget.name = gadget_name;
	dum->gadget.ops = &dummy_ops;
	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;
	init_dummy_udc_hw(dum);
@@ -1245,6 +1276,8 @@ static int dummy_urb_enqueue(

	list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
	urb->hcpriv = urbp;
	if (!dum_hcd->next_frame_urbp)
		dum_hcd->next_frame_urbp = urbp;
	if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
		urb->error_count = 1;		/* mark as a new urb */

@@ -1520,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
	if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
			dum->ss_hcd : dum->hs_hcd)))
		return NULL;
	if (!dum->ints_enabled)
		return NULL;
	if ((address & ~USB_DIR_IN) == 0)
		return &dum->ep[0];
	for (i = 1; i < DUMMY_ENDPOINTS; i++) {
@@ -1761,6 +1796,7 @@ static void dummy_timer(unsigned long _dum_hcd)
		spin_unlock_irqrestore(&dum->lock, flags);
		return;
	}
	dum_hcd->next_frame_urbp = NULL;

	for (i = 0; i < DUMMY_ENDPOINTS; i++) {
		if (!ep_info[i].name)
@@ -1777,6 +1813,10 @@ static void dummy_timer(unsigned long _dum_hcd)
		int			type;
		int			status = -EINPROGRESS;

		/* stop when we reach URBs queued after the timer interrupt */
		if (urbp == dum_hcd->next_frame_urbp)
			break;

		urb = urbp->urb;
		if (urb->unlinked)
			goto return_urb;
@@ -1856,10 +1896,12 @@ static void dummy_timer(unsigned long _dum_hcd)
			 * until setup() returns; no reentrancy issues etc.
			 */
			if (value > 0) {
				++dum->callback_usage;
				spin_unlock(&dum->lock);
				value = dum->driver->setup(&dum->gadget,
						&setup);
				spin_lock(&dum->lock);
				--dum->callback_usage;

				if (value >= 0) {
					/* no delays (max 64KB data stage) */
@@ -2560,8 +2602,6 @@ static struct hc_driver dummy_hcd = {
	.product_desc =		"Dummy host controller",
	.hcd_priv_size =	sizeof(struct dummy_hcd),

	.flags =		HCD_USB3 | HCD_SHARED,

	.reset =		dummy_setup,
	.start =		dummy_start,
	.stop =			dummy_stop,
@@ -2590,8 +2630,12 @@ static int dummy_hcd_probe(struct platform_device *pdev)
	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
	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;
	else
		dummy_hcd.flags = HCD_USB11;
	hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
	if (!hs_hcd)
		return -ENOMEM;
Loading