aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org> 2023-11-03 16:00:42 -1000
committerGravatar Linus Torvalds <torvalds@linux-foundation.org> 2023-11-03 16:00:42 -1000
commit2c40c1c6adab90ee4660caf03722b3a3ec67767b (patch)
treee83a44653acf861672e3352c91c8fa57f9930813 /drivers/usb/gadget
parentMerge tag 'tty-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/greg... (diff)
parentusb: gadget: uvc: Add missing initialization of ssp config descriptor (diff)
downloadlinux-2c40c1c6adab90ee4660caf03722b3a3ec67767b.tar.gz
linux-2c40c1c6adab90ee4660caf03722b3a3ec67767b.tar.bz2
linux-2c40c1c6adab90ee4660caf03722b3a3ec67767b.zip
Merge tag 'usb-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/Thunderbolt updates from Greg KH: "Here is the "big" set of USB and Thunderbolt changes for 6.7-rc1. Nothing really major in here, just lots of constant development for new hardware. Included in here are: - Thunderbolt (i.e. USB4) fixes for reported issues and support for new hardware types and devices - USB typec additions of new drivers and cleanups for some existing ones - xhci cleanups and expanded tracing support and some platform specific updates - USB "La Jolla Cove Adapter (LJCA)" support added, and the gpio, spi, and i2c drivers for that type of device (all acked by the respective subsystem maintainers.) - lots of USB gadget driver updates and cleanups - new USB dwc3 platforms supported, as well as other dwc3 fixes and cleanups - USB chipidea driver updates - other smaller driver cleanups and additions, full details in the shortlog All of these have been in the linux-next tree for a while with no reported problems" * tag 'usb-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (167 commits) usb: gadget: uvc: Add missing initialization of ssp config descriptor usb: storage: set 1.50 as the lower bcdDevice for older "Super Top" compatibility usb: raw-gadget: report suspend, resume, reset, and disconnect events usb: raw-gadget: don't disable device if usb_ep_queue fails usb: raw-gadget: properly handle interrupted requests usb:cdnsp: remove TRB_FLUSH_ENDPOINT command usb: gadget: aspeed_udc: Convert to platform remove callback returning void dt-bindings: usb: fsa4480: Add compatible for OCP96011 usb: typec: fsa4480: Add support to swap SBU orientation dt-bindings: usb: fsa4480: Add data-lanes property to endpoint usb: typec: tcpm: Fix NULL pointer dereference in tcpm_pd_svdm() Revert "dt-bindings: usb: Add bindings for multiport properties on DWC3 controller" Revert "dt-bindings: usb: qcom,dwc3: Add bindings for SC8280 Multiport" thunderbolt: Fix one kernel-doc comment usb: gadget: f_ncm: Always set current gadget in ncm_bind() usb: core: Remove duplicated check in usb_hub_create_port_device usb: typec: tcpm: Add additional checks for contaminant arm64: dts: rockchip: rk3588s: Add USB3 host controller usb: dwc3: add optional PHY interface clocks dt-bindings: usb: add rk3588 compatible to rockchip,dwc3 ...
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/function/f_ncm.c27
-rw-r--r--drivers/usb/gadget/function/f_uac2.c16
-rw-r--r--drivers/usb/gadget/function/f_uvc.c14
-rw-r--r--drivers/usb/gadget/function/u_ether.c2
-rw-r--r--drivers/usb/gadget/function/u_uac2.h8
-rw-r--r--drivers/usb/gadget/legacy/inode.c17
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c91
-rw-r--r--drivers/usb/gadget/udc/aspeed_udc.c19
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c3
-rw-r--r--drivers/usb/gadget/udc/core.c19
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c10
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c3
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c7
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c3
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c3
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c3
16 files changed, 178 insertions, 67 deletions
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index e6ab8cc225ff..cc0ed29a4adc 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1410,7 +1410,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_ncm *ncm = func_to_ncm(f);
struct usb_string *us;
- int status;
+ int status = 0;
struct usb_ep *ep;
struct f_ncm_opts *ncm_opts;
@@ -1428,22 +1428,17 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
}
- /*
- * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
- * configurations are bound in sequence with list_for_each_entry,
- * in each configuration its functions are bound in sequence
- * with list_for_each_entry, so we assume no race condition
- * with regard to ncm_opts->bound access
- */
- if (!ncm_opts->bound) {
- mutex_lock(&ncm_opts->lock);
- gether_set_gadget(ncm_opts->net, cdev->gadget);
+ mutex_lock(&ncm_opts->lock);
+ gether_set_gadget(ncm_opts->net, cdev->gadget);
+ if (!ncm_opts->bound)
status = gether_register_netdev(ncm_opts->net);
- mutex_unlock(&ncm_opts->lock);
- if (status)
- goto fail;
- ncm_opts->bound = true;
- }
+ mutex_unlock(&ncm_opts->lock);
+
+ if (status)
+ goto fail;
+
+ ncm_opts->bound = true;
+
us = usb_gstrings_attach(cdev, ncm_strings,
ARRAY_SIZE(ncm_string_defs));
if (IS_ERR(us)) {
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 0219cd79493a..f9a0f07a7476 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -212,7 +212,7 @@ static struct uac2_input_terminal_descriptor io_in_it_desc = {
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
/* .bTerminalID = DYNAMIC */
- .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE),
+ /* .wTerminalType = DYNAMIC */
.bAssocTerminal = 0,
/* .bCSourceID = DYNAMIC */
.iChannelNames = 0,
@@ -240,7 +240,7 @@ static struct uac2_output_terminal_descriptor io_out_ot_desc = {
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
/* .bTerminalID = DYNAMIC */
- .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER),
+ /* .wTerminalType = DYNAMIC */
.bAssocTerminal = 0,
/* .bSourceID = DYNAMIC */
/* .bCSourceID = DYNAMIC */
@@ -977,6 +977,9 @@ static void setup_descriptor(struct f_uac2_opts *opts)
iad_desc.bInterfaceCount++;
}
+ io_in_it_desc.wTerminalType = cpu_to_le16(opts->c_terminal_type);
+ io_out_ot_desc.wTerminalType = cpu_to_le16(opts->p_terminal_type);
+
setup_headers(opts, fs_audio_desc, USB_SPEED_FULL);
setup_headers(opts, hs_audio_desc, USB_SPEED_HIGH);
setup_headers(opts, ss_audio_desc, USB_SPEED_SUPER);
@@ -2095,6 +2098,9 @@ UAC2_ATTRIBUTE(s16, c_volume_res);
UAC2_ATTRIBUTE(u32, fb_max);
UAC2_ATTRIBUTE_STRING(function_name);
+UAC2_ATTRIBUTE(s16, p_terminal_type);
+UAC2_ATTRIBUTE(s16, c_terminal_type);
+
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
&f_uac2_opts_attr_p_srate,
@@ -2122,6 +2128,9 @@ static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_function_name,
+ &f_uac2_opts_attr_p_terminal_type,
+ &f_uac2_opts_attr_c_terminal_type,
+
NULL,
};
@@ -2180,6 +2189,9 @@ static struct usb_function_instance *afunc_alloc_inst(void)
snprintf(opts->function_name, sizeof(opts->function_name), "Source/Sink");
+ opts->p_terminal_type = UAC2_DEF_P_TERM_TYPE;
+ opts->c_terminal_type = UAC2_DEF_C_TERM_TYPE;
+
return &opts->func_inst;
}
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index faa398109431..786379f1b7b7 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -516,6 +516,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
void *mem;
switch (speed) {
+ case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER:
uvc_control_desc = uvc->desc.ss_control;
uvc_streaming_cls = uvc->desc.ss_streaming;
@@ -564,7 +565,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
bytes += uvc_interrupt_ep.bLength + uvc_interrupt_cs_ep.bLength;
n_desc += 2;
- if (speed == USB_SPEED_SUPER) {
+ if (speed == USB_SPEED_SUPER ||
+ speed == USB_SPEED_SUPER_PLUS) {
bytes += uvc_ss_interrupt_comp.bLength;
n_desc += 1;
}
@@ -619,7 +621,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
if (uvc->enable_interrupt_ep) {
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep);
- if (speed == USB_SPEED_SUPER)
+ if (speed == USB_SPEED_SUPER ||
+ speed == USB_SPEED_SUPER_PLUS)
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_interrupt_comp);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_cs_ep);
@@ -795,6 +798,13 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
+ f->ssp_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER_PLUS);
+ if (IS_ERR(f->ssp_descriptors)) {
+ ret = PTR_ERR(f->ssp_descriptors);
+ f->ssp_descriptors = NULL;
+ goto error;
+ }
+
/* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 4bb0553da658..9d1c40c152d8 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -1200,7 +1200,7 @@ void gether_disconnect(struct gether *link)
DBG(dev, "%s\n", __func__);
- netif_stop_queue(dev->net);
+ netif_device_detach(dev->net);
netif_carrier_off(dev->net);
/* disable endpoints, forcing (synchronous) completion
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index 0510c9bad58d..5e81bdd6c5fb 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -35,6 +35,11 @@
#define UAC2_DEF_REQ_NUM 2
#define UAC2_DEF_INT_REQ_NUM 10
+#define UAC2_DEF_P_TERM_TYPE 0x301
+ /* UAC_OUTPUT_TERMINAL_SPEAKER */
+#define UAC2_DEF_C_TERM_TYPE 0x201
+ /* UAC_INPUT_TERMINAL_MICROPHONE*/
+
struct f_uac2_opts {
struct usb_function_instance func_inst;
int p_chmask;
@@ -65,6 +70,9 @@ struct f_uac2_opts {
char function_name[32];
+ s16 p_terminal_type;
+ s16 c_terminal_type;
+
struct mutex lock;
int refcnt;
};
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index cdc0926100fd..03179b1880fd 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -31,6 +31,12 @@
#include <linux/usb/gadgetfs.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h> /* for USB_GADGET_DELAYED_STATUS */
+
+/* Undef helpers from linux/usb/composite.h as gadgetfs redefines them */
+#undef DBG
+#undef ERROR
+#undef INFO
/*
@@ -1511,7 +1517,16 @@ delegate:
event->u.setup = *ctrl;
ep0_readable (dev);
spin_unlock (&dev->lock);
- return 0;
+ /*
+ * Return USB_GADGET_DELAYED_STATUS as a workaround to
+ * stop some UDC drivers (e.g. dwc3) from automatically
+ * proceeding with the status stage for 0-length
+ * transfers.
+ * Should be removed once all UDC drivers are fixed to
+ * always delay the status stage until a response is
+ * queued to EP0.
+ */
+ return w_length == 0 ? USB_GADGET_DELAYED_STATUS : 0;
}
}
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index e549022642e5..399fca32a8ac 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -25,6 +25,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/ch11.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
#include <uapi/linux/usb/raw_gadget.h>
@@ -64,7 +65,7 @@ static int raw_event_queue_add(struct raw_event_queue *queue,
struct usb_raw_event *event;
spin_lock_irqsave(&queue->lock, flags);
- if (WARN_ON(queue->size >= RAW_EVENT_QUEUE_SIZE)) {
+ if (queue->size >= RAW_EVENT_QUEUE_SIZE) {
spin_unlock_irqrestore(&queue->lock, flags);
return -ENOMEM;
}
@@ -310,9 +311,10 @@ static int gadget_bind(struct usb_gadget *gadget,
dev->eps_num = i;
spin_unlock_irqrestore(&dev->lock, flags);
+ dev_dbg(&gadget->dev, "gadget connected\n");
ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL);
if (ret < 0) {
- dev_err(&gadget->dev, "failed to queue event\n");
+ dev_err(&gadget->dev, "failed to queue connect event\n");
set_gadget_data(gadget, NULL);
return ret;
}
@@ -357,20 +359,65 @@ static int gadget_setup(struct usb_gadget *gadget,
ret = raw_queue_event(dev, USB_RAW_EVENT_CONTROL, sizeof(*ctrl), ctrl);
if (ret < 0)
- dev_err(&gadget->dev, "failed to queue event\n");
+ dev_err(&gadget->dev, "failed to queue control event\n");
goto out;
out_unlock:
spin_unlock_irqrestore(&dev->lock, flags);
out:
+ if (ret == 0 && ctrl->wLength == 0) {
+ /*
+ * Return USB_GADGET_DELAYED_STATUS as a workaround to stop
+ * some UDC drivers (e.g. dwc3) from automatically proceeding
+ * with the status stage for 0-length transfers.
+ * Should be removed once all UDC drivers are fixed to always
+ * delay the status stage until a response is queued to EP0.
+ */
+ return USB_GADGET_DELAYED_STATUS;
+ }
return ret;
}
-/* These are currently unused but present in case UDC driver requires them. */
-static void gadget_disconnect(struct usb_gadget *gadget) { }
-static void gadget_suspend(struct usb_gadget *gadget) { }
-static void gadget_resume(struct usb_gadget *gadget) { }
-static void gadget_reset(struct usb_gadget *gadget) { }
+static void gadget_disconnect(struct usb_gadget *gadget)
+{
+ struct raw_dev *dev = get_gadget_data(gadget);
+ int ret;
+
+ dev_dbg(&gadget->dev, "gadget disconnected\n");
+ ret = raw_queue_event(dev, USB_RAW_EVENT_DISCONNECT, 0, NULL);
+ if (ret < 0)
+ dev_err(&gadget->dev, "failed to queue disconnect event\n");
+}
+static void gadget_suspend(struct usb_gadget *gadget)
+{
+ struct raw_dev *dev = get_gadget_data(gadget);
+ int ret;
+
+ dev_dbg(&gadget->dev, "gadget suspended\n");
+ ret = raw_queue_event(dev, USB_RAW_EVENT_SUSPEND, 0, NULL);
+ if (ret < 0)
+ dev_err(&gadget->dev, "failed to queue suspend event\n");
+}
+static void gadget_resume(struct usb_gadget *gadget)
+{
+ struct raw_dev *dev = get_gadget_data(gadget);
+ int ret;
+
+ dev_dbg(&gadget->dev, "gadget resumed\n");
+ ret = raw_queue_event(dev, USB_RAW_EVENT_RESUME, 0, NULL);
+ if (ret < 0)
+ dev_err(&gadget->dev, "failed to queue resume event\n");
+}
+static void gadget_reset(struct usb_gadget *gadget)
+{
+ struct raw_dev *dev = get_gadget_data(gadget);
+ int ret;
+
+ dev_dbg(&gadget->dev, "gadget reset\n");
+ ret = raw_queue_event(dev, USB_RAW_EVENT_RESET, 0, NULL);
+ if (ret < 0)
+ dev_err(&gadget->dev, "failed to queue reset event\n");
+}
/*----------------------------------------------------------------------*/
@@ -663,12 +710,12 @@ static int raw_process_ep0_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
if (WARN_ON(in && dev->ep0_out_pending)) {
ret = -ENODEV;
dev->state = STATE_DEV_FAILED;
- goto out_done;
+ goto out_unlock;
}
if (WARN_ON(!in && dev->ep0_in_pending)) {
ret = -ENODEV;
dev->state = STATE_DEV_FAILED;
- goto out_done;
+ goto out_unlock;
}
dev->req->buf = data;
@@ -682,8 +729,7 @@ static int raw_process_ep0_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
dev_err(&dev->gadget->dev,
"fail, usb_ep_queue returned %d\n", ret);
spin_lock_irqsave(&dev->lock, flags);
- dev->state = STATE_DEV_FAILED;
- goto out_done;
+ goto out_queue_failed;
}
ret = wait_for_completion_interruptible(&dev->ep0_done);
@@ -692,13 +738,16 @@ static int raw_process_ep0_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
usb_ep_dequeue(dev->gadget->ep0, dev->req);
wait_for_completion(&dev->ep0_done);
spin_lock_irqsave(&dev->lock, flags);
- goto out_done;
+ if (dev->ep0_status == -ECONNRESET)
+ dev->ep0_status = -EINTR;
+ goto out_interrupted;
}
spin_lock_irqsave(&dev->lock, flags);
- ret = dev->ep0_status;
-out_done:
+out_interrupted:
+ ret = dev->ep0_status;
+out_queue_failed:
dev->ep0_urb_queued = false;
out_unlock:
spin_unlock_irqrestore(&dev->lock, flags);
@@ -1066,8 +1115,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
dev_err(&dev->gadget->dev,
"fail, usb_ep_queue returned %d\n", ret);
spin_lock_irqsave(&dev->lock, flags);
- dev->state = STATE_DEV_FAILED;
- goto out_done;
+ goto out_queue_failed;
}
ret = wait_for_completion_interruptible(&done);
@@ -1076,13 +1124,16 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io,
usb_ep_dequeue(ep->ep, ep->req);
wait_for_completion(&done);
spin_lock_irqsave(&dev->lock, flags);
- goto out_done;
+ if (ep->status == -ECONNRESET)
+ ep->status = -EINTR;
+ goto out_interrupted;
}
spin_lock_irqsave(&dev->lock, flags);
- ret = ep->status;
-out_done:
+out_interrupted:
+ ret = ep->status;
+out_queue_failed:
ep->urb_queued = false;
out_unlock:
spin_unlock_irqrestore(&dev->lock, flags);
diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
index 2ef89a442f50..3916c8e2ba01 100644
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -1432,15 +1432,24 @@ static void ast_udc_init_hw(struct ast_udc_dev *udc)
ast_udc_write(udc, 0, AST_UDC_EP0_CTRL);
}
-static int ast_udc_remove(struct platform_device *pdev)
+static void ast_udc_remove(struct platform_device *pdev)
{
struct ast_udc_dev *udc = platform_get_drvdata(pdev);
unsigned long flags;
u32 ctrl;
usb_del_gadget_udc(&udc->gadget);
- if (udc->driver)
- return -EBUSY;
+ if (udc->driver) {
+ /*
+ * This is broken as only some cleanup is skipped, *udev is
+ * freed and the register mapping goes away. Any further usage
+ * probably crashes. Also the device is unbound, so the skipped
+ * cleanup is never catched up later.
+ */
+ dev_alert(&pdev->dev,
+ "Driver is busy and still going away. Fasten your seat belts!\n");
+ return;
+ }
spin_lock_irqsave(&udc->lock, flags);
@@ -1459,8 +1468,6 @@ static int ast_udc_remove(struct platform_device *pdev)
udc->ep0_buf_dma);
udc->ep0_buf = NULL;
-
- return 0;
}
static int ast_udc_probe(struct platform_device *pdev)
@@ -1581,7 +1588,7 @@ MODULE_DEVICE_TABLE(of, ast_udc_of_dt_ids);
static struct platform_driver ast_udc_driver = {
.probe = ast_udc_probe,
- .remove = ast_udc_remove,
+ .remove_new = ast_udc_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_udc_of_dt_ids,
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index 922b4187004b..30ea4a9d5301 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -2000,6 +2000,7 @@ static int at91udc_resume(struct platform_device *pdev)
#endif
static struct platform_driver at91_udc_driver = {
+ .probe = at91udc_probe,
.remove = at91udc_remove,
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
@@ -2010,7 +2011,7 @@ static struct platform_driver at91_udc_driver = {
},
};
-module_platform_driver_probe(at91_udc_driver, at91udc_probe);
+module_platform_driver(at91_udc_driver);
MODULE_DESCRIPTION("AT91 udc driver");
MODULE_AUTHOR("Thomas Rathbone, David Brownell");
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 7166d1117742..ded9531f141b 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1126,12 +1126,12 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
/* ------------------------------------------------------------------------- */
/* Acquire connect_lock before calling this function. */
-static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
+static int usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
{
if (udc->vbus)
- usb_gadget_connect_locked(udc->gadget);
+ return usb_gadget_connect_locked(udc->gadget);
else
- usb_gadget_disconnect_locked(udc->gadget);
+ return usb_gadget_disconnect_locked(udc->gadget);
}
static void vbus_event_work(struct work_struct *work)
@@ -1605,12 +1605,23 @@ static int gadget_bind_driver(struct device *dev)
}
usb_gadget_enable_async_callbacks(udc);
udc->allow_connect = true;
- usb_udc_connect_control_locked(udc);
+ ret = usb_udc_connect_control_locked(udc);
+ if (ret)
+ goto err_connect_control;
+
mutex_unlock(&udc->connect_lock);
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
return 0;
+ err_connect_control:
+ udc->allow_connect = false;
+ usb_gadget_disable_async_callbacks(udc);
+ if (gadget->irq)
+ synchronize_irq(gadget->irq);
+ usb_gadget_udc_stop_locked(udc);
+ mutex_unlock(&udc->connect_lock);
+
err_start:
driver->unbind(udc->gadget);
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 4aae86b47edf..4e88681a79b6 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -27,9 +27,10 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/moduleparam.h>
+#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -2471,17 +2472,12 @@ static const struct of_device_id qe_udc_match[];
static int qe_udc_probe(struct platform_device *ofdev)
{
struct qe_udc *udc;
- const struct of_device_id *match;
struct device_node *np = ofdev->dev.of_node;
struct qe_ep *ep;
unsigned int ret = 0;
unsigned int i;
const void *prop;
- match = of_match_device(qe_udc_match, &ofdev->dev);
- if (!match)
- return -EINVAL;
-
prop = of_get_property(np, "mode", NULL);
if (!prop || strcmp(prop, "peripheral"))
return -ENODEV;
@@ -2493,7 +2489,7 @@ static int qe_udc_probe(struct platform_device *ofdev)
return -ENOMEM;
}
- udc->soc_type = (unsigned long)match->data;
+ udc->soc_type = (unsigned long)device_get_match_data(&ofdev->dev);
udc->usb_regs = of_iomap(np, 0);
if (!udc->usb_regs) {
ret = -ENOMEM;
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index ee5705d336e3..2693a10eb0c7 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2666,6 +2666,7 @@ static const struct platform_device_id fsl_udc_devtype[] = {
};
MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
static struct platform_driver udc_driver = {
+ .probe = fsl_udc_probe,
.remove = fsl_udc_remove,
.id_table = fsl_udc_devtype,
/* these suspend and resume are not usb suspend and resume */
@@ -2679,7 +2680,7 @@ static struct platform_driver udc_driver = {
},
};
-module_platform_driver_probe(udc_driver, fsl_udc_probe);
+module_platform_driver(udc_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index bd03d475f927..873265634ccc 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1506,10 +1506,11 @@ clean_up:
}
static struct platform_driver fusb300_driver = {
- .remove_new = fusb300_remove,
- .driver = {
+ .probe = fusb300_probe,
+ .remove_new = fusb300_remove,
+ .driver = {
.name = udc_name,
},
};
-module_platform_driver_probe(fusb300_driver, fusb300_probe);
+module_platform_driver(fusb300_driver);
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index fe62db32dd0e..a917cc9a32ab 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3254,6 +3254,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
#endif
static struct platform_driver lpc32xx_udc_driver = {
+ .probe = lpc32xx_udc_probe,
.remove = lpc32xx_udc_remove,
.shutdown = lpc32xx_udc_shutdown,
.suspend = lpc32xx_udc_suspend,
@@ -3264,7 +3265,7 @@ static struct platform_driver lpc32xx_udc_driver = {
},
};
-module_platform_driver_probe(lpc32xx_udc_driver, lpc32xx_udc_probe);
+module_platform_driver(lpc32xx_udc_driver);
MODULE_DESCRIPTION("LPC32XX udc driver");
MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index e05f45a4b56b..bfaa5291e6c8 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1687,10 +1687,11 @@ clean_up:
/*-------------------------------------------------------------------------*/
static struct platform_driver m66592_driver = {
+ .probe = m66592_probe,
.remove_new = m66592_remove,
.driver = {
.name = udc_name,
},
};
-module_platform_driver_probe(m66592_driver, m66592_probe);
+module_platform_driver(m66592_driver);
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index 51b665f15c8e..db4a10a979f9 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1964,13 +1964,14 @@ clean_up2:
/*-------------------------------------------------------------------------*/
static struct platform_driver r8a66597_driver = {
+ .probe = r8a66597_probe,
.remove_new = r8a66597_remove,
.driver = {
.name = udc_name,
},
};
-module_platform_driver_probe(r8a66597_driver, r8a66597_probe);
+module_platform_driver(r8a66597_driver);
MODULE_DESCRIPTION("R8A66597 USB gadget driver");
MODULE_LICENSE("GPL");