Re: [PATCH 01/19] usb: gadget: introduce UDC Class

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Thu, Jun 16, 2011 at 12:20:50PM +0300, Roger Quadros wrote:
> >diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
> >new file mode 100644
> >index 0000000..534f767
> >--- /dev/null
> >+++ b/drivers/usb/gadget/udc-core.c
> >@@ -0,0 +1,412 @@
> >+/**
> >+ * udc.c - Core UDC Framework
> >+ *
> >+ * Copyright (C) 2010 Texas Instruments
> >+ * Author: Felipe Balbi<balbi@xxxxxx>
> >+ *
> >+ * This program is free software: you can redistribute it and/or modify
> >+ * it under the terms of the GNU General Public License version 2  of
> >+ * the License as published by the Free Software Foundation.
> >+ *
> >+ * This program is distributed in the hope that it will be useful,
> >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >+ * GNU General Public License for more details.
> >+ *
> >+ * You should have received a copy of the GNU General Public License
> >+ * along with this program.  If not, see<http://www.gnu.org/licenses/>.
> >+ */
> >+
> >+#include<linux/kernel.h>
> >+#include<linux/module.h>
> >+#include<linux/device.h>
> >+#include<linux/list.h>
> >+#include<linux/err.h>
> >+
> >+#include<linux/usb/ch9.h>
> >+#include<linux/usb/gadget.h>
> >+
> >+/**
> >+ * struct usb_udc - describes one usb device controller
> >+ * @driver - the gadget driver pointer. For use by the class code
> >+ * @dev - the child device to the actual controller
> >+ * @gadget - the gadget. For use by the class code
> >+ * @list - for use by the udc class driver
> >+ * @name - a human friendly name representation
> 
> name is missing in the data structure

will fix.

> >+ *
> >+ * This represents the internal data structure which is used by the UDC-class
> >+ * to hold information about udc driver and gadget together.
> >+ */
> >+struct usb_udc {
> >+       struct usb_gadget_driver        *driver;
> >+       struct usb_gadget               *gadget;
> >+       struct device                   dev;
> >+       struct list_head                list;
> >+};
> >+
> >+static struct class *udc_class;
> >+static struct device_type udc_device_type;
> >+static LIST_HEAD(udc_list);
> >+static DEFINE_MUTEX(udc_lock);
> >+
> >+/* ------------------------------------------------------------------------- */
> >+
> >+/**
> >+ * usb_gadget_start - tells usb device controller to start up
> >+ * @gadget: The device we want to get started
> Shouldn't it be called "The gadget" rather than "The device".
> The device would refer to the UDC device. no?
> 
> Description for other parameters are missing

will fix.

> >+ *
> >+ * This call is issued by the UDC Class driver when it's about
> >+ * to register a gadget driver to the device controller, before
> >+ * calling gadget driver's bind() method.
> >+ *
> >+ * It allows the controller to be powered off until extrictly
> 
> did you mean explicitly?

strictly.

> >+ * necessary to have it powered on.
> >+ *
> >+ * Returns zero on success, else negative errno.
> >+ */
> >+static inline int usb_gadget_start(struct usb_gadget *gadget,
> >+               struct usb_gadget_driver *drv, int (*bind)(struct usb_gadget *))
> >+{
> >+       return gadget->ops->start(drv, bind);
> >+}
> >+
> >+/**
> >+ * usb_gadget_stop - tells usb device controller we don't need it anymore
> >+ * @gadget: The device we want to stop activity
> The device -> The gadget.
> 
> Description for 2nd parameter is missing

will fix.

> >+ * This call is issued by the UDC Class driver after calling
> >+ * gadget driver's unbind() method.
> >+ *
> >+ * The details are implementation specific, but it can go as
> >+ * far as powering off UDC completely and disable its data
> >+ * line pullups.
> >+ */
> >+static inline void usb_gadget_stop(struct usb_gadget *gadget,
> >+               struct usb_gadget_driver *driver)
> >+{
> >+       gadget->ops->stop(driver);
> >+}
> >+
> >+/**
> >+ * usb_udc_release - release the usb_udc struct
> >+ * @dev: the dev member within usb_udc
> >+ *
> >+ * This is called by driver's core in order to free memory once the last
> >+ * reference is released.
> >+ */
> >+static void usb_udc_release(struct device *dev)
> >+{
> >+       struct usb_udc *udc;
> >+
> >+       udc = container_of(dev, struct usb_udc, dev);
> >+       dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
> >+       kfree(udc);
> >+}
> >+
> >+/**
> >+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
> >+ * @parent: the parent device to this udc. Usually the controller
> >+ * driver's device.
> >+ * @gadget: the gadget to be added to the list
> >+ *
> >+ * Returns zero on success, negative errno otherwise.
> >+ */
> >+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
> >+{
> >+       struct usb_udc          *udc;
> >+       int                     ret = -ENOMEM;
> >+
> >+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
> >+       if (!udc)
> >+               goto err1;
> >+
> >+       device_initialize(&udc->dev);
> >+       udc->dev.release = usb_udc_release;
> >+       udc->dev.class = udc_class;
> >+       udc->dev.parent = parent;
> >+       ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
> >+       if (ret)
> >+               goto err2;
> >+
> >+       udc->gadget = gadget;
> >+
> >+       mutex_lock(&udc_lock);
> >+       list_add_tail(&udc->list,&udc_list);
> >+
> >+       ret = device_add(&udc->dev);
> >+       if (ret)
> >+               goto err3;
> >+
> >+       kobject_uevent(&udc->dev.kobj, KOBJ_ADD);
> 
> Not necessary. device_add() generates the uevent for you.

good catch.

> >+       mutex_unlock(&udc_lock);
> >+       return 0;
> >+err3:
> >+       list_del(&udc->list);
> >+       mutex_unlock(&udc_lock);
> >+
> >+err2:
> >+       put_device(&udc->dev);
> 
> memory leaks here. need to free udc.

true, will fix.

> >+err1:
> >+       return ret;
> >+}
> >+EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
> >+
> >+static void usb_gadget_remove_driver(struct usb_udc *udc)
> >+{
> >+       dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n",
> >+                       udc->gadget->name);
> >+
> >+       kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
> 
> Do you really need this? It will be immediately followed by a
> KOBJ_REMOVE since you call device_unregister() soon after.

this can be called without removing the UDC driver. You can change a
gadget driver without unloading musb.

> >+       usb_gadget_stop(udc->gadget, udc->driver);
> >+
> >+       udc->driver = NULL;
> >+       udc->dev.driver = NULL;
> >+}
> >+
> >+/**
> >+ * usb_del_gadget_udc - deletes @udc from udc_list
> >+ * @udc: the udc to be removed.
> should be @gadget.

good catch.

> 
> >+ *
> >+ * This, will call usb_gadget_unregister_driver() if
> >+ * the @udc is still busy.
> >+ */
> >+void usb_del_gadget_udc(struct usb_gadget *gadget)
> >+{
> >+       struct usb_udc          *udc = NULL;
> >+
> >+       dev_vdbg(gadget->dev.parent, "unregistering gadget\n");
> isn't is better if this print is moved to after found: ?

yeah, will do.

> >+       mutex_lock(&udc_lock);
> >+       list_for_each_entry(udc,&udc_list, list)
> >+               if (udc->gadget == gadget)
> >+                       goto found;
> >+
> >+       dev_err(gadget->dev.parent, "gadget not registered.\n");
> >+       mutex_unlock(&udc_lock);
> >+       return;
> >+found:
> >+       list_del(&udc->list);
> >+       mutex_unlock(&udc_lock);
> >+
> >+       if (udc->driver)
> >+               usb_gadget_remove_driver(udc);
> >+
> >+       kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
> 
> Not required. device_del() does it for you when you do a
> device_unregister() below.

ok.

> >+       device_unregister(&udc->dev);
> >+}
> >+EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
> >+
> >+/* ------------------------------------------------------------------------- */
> >+
> missing description?

it was on purpose... but I can add, no problem.

-- 
balbi

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux