aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/udc-core.c72
-rw-r--r--include/linux/usb/gadget.h2
2 files changed, 53 insertions, 21 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 4d90a800063c..e7c591621a3b 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -311,26 +311,10 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
311 311
312/* ------------------------------------------------------------------------- */ 312/* ------------------------------------------------------------------------- */
313 313
314int usb_gadget_probe_driver(struct usb_gadget_driver *driver) 314static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
315{ 315{
316 struct usb_udc *udc = NULL; 316 int ret;
317 int ret;
318
319 if (!driver || !driver->bind || !driver->setup)
320 return -EINVAL;
321 317
322 mutex_lock(&udc_lock);
323 list_for_each_entry(udc, &udc_list, list) {
324 /* For now we take the first one */
325 if (!udc->driver)
326 goto found;
327 }
328
329 pr_debug("couldn't find an available UDC\n");
330 mutex_unlock(&udc_lock);
331 return -ENODEV;
332
333found:
334 dev_dbg(&udc->dev, "registering UDC driver [%s]\n", 318 dev_dbg(&udc->dev, "registering UDC driver [%s]\n",
335 driver->function); 319 driver->function);
336 320
@@ -352,18 +336,64 @@ found:
352 ret = usb_gadget_start(udc->gadget, driver, driver->bind); 336 ret = usb_gadget_start(udc->gadget, driver, driver->bind);
353 if (ret) 337 if (ret)
354 goto err1; 338 goto err1;
355
356 } 339 }
357 340
358 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); 341 kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
359 mutex_unlock(&udc_lock);
360 return 0; 342 return 0;
361
362err1: 343err1:
363 dev_err(&udc->dev, "failed to start %s: %d\n", 344 dev_err(&udc->dev, "failed to start %s: %d\n",
364 udc->driver->function, ret); 345 udc->driver->function, ret);
365 udc->driver = NULL; 346 udc->driver = NULL;
366 udc->dev.driver = NULL; 347 udc->dev.driver = NULL;
348 return ret;
349}
350
351int udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
352{
353 struct usb_udc *udc = NULL;
354 int ret = -ENODEV;
355
356 mutex_lock(&udc_lock);
357 list_for_each_entry(udc, &udc_list, list) {
358 ret = strcmp(name, dev_name(&udc->dev));
359 if (!ret)
360 break;
361 }
362 if (ret) {
363 ret = -ENODEV;
364 goto out;
365 }
366 if (udc->driver) {
367 ret = -EBUSY;
368 goto out;
369 }
370 ret = udc_bind_to_driver(udc, driver);
371out:
372 mutex_unlock(&udc_lock);
373 return ret;
374}
375EXPORT_SYMBOL_GPL(udc_attach_driver);
376
377int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
378{
379 struct usb_udc *udc = NULL;
380 int ret;
381
382 if (!driver || !driver->bind || !driver->setup)
383 return -EINVAL;
384
385 mutex_lock(&udc_lock);
386 list_for_each_entry(udc, &udc_list, list) {
387 /* For now we take the first one */
388 if (!udc->driver)
389 goto found;
390 }
391
392 pr_debug("couldn't find an available UDC\n");
393 mutex_unlock(&udc_lock);
394 return -ENODEV;
395found:
396 ret = udc_bind_to_driver(udc, driver);
367 mutex_unlock(&udc_lock); 397 mutex_unlock(&udc_lock);
368 return ret; 398 return ret;
369} 399}
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 0af6569b8cc6..62156701e4f1 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -880,6 +880,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
880 880
881extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget); 881extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
882extern void usb_del_gadget_udc(struct usb_gadget *gadget); 882extern void usb_del_gadget_udc(struct usb_gadget *gadget);
883extern int udc_attach_driver(const char *name,
884 struct usb_gadget_driver *driver);
883 885
884/*-------------------------------------------------------------------------*/ 886/*-------------------------------------------------------------------------*/
885 887