diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-06 02:18:00 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-06 02:18:00 +0400 |
commit | 64dc9e2e7320f079b97c46b106133b58b8e18d40 (patch) | |
tree | ab010dc1337d44e29c2b32b7f11788620a91fe4f /drivers/usb/gadget/f_serial.c | |
parent | 01a60e76b6392547ad3dca3ac05b9c886fa5da45 (diff) | |
parent | 9b192de60b5a584ee4ed967fb6758773c75e4643 (diff) | |
download | linux-64dc9e2e7320f079b97c46b106133b58b8e18d40.tar.xz |
Merge tag 'usb-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
usb: patches for v3.10 merge window
Here is the big Gadget & PHY pull request. Many of us have
been really busy lately getting multiple drivers to a better
position.
Since this pull request is so large, I will divide it in sections
so it's easier to grasp what's included.
- cleanups:
. UDC drivers no longer touch gadget->dev, that's now udc-core
responsibility
. Many more UDC drivers converted to usb_gadget_map/unmap_request()
. UDC drivers no longer initialize DMA-related fields from gadget's
device structure
. UDC drivers don't touch gadget.dev.driver directly
. UDC drivers don't assign gadget.dev.release directly
. Removal of some unused DMA_ADDR_INVALID
. Introduction of CONFIG_USB_PHY
. All phy drivers have been moved to drivers/usb/phy and renamed to
a common naming scheme
. Fix PHY layer so it never returns a NULL pointer, also fix all
callers to avoid using IS_ERR_OR_NULL()
. Sparse fixes all over the place
. drivers/usb/otg/ has been deleted
. Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock
usage
- new features:
. UDC core now provides a generic way for tracking and reporting
UDC's state (not attached, resuming, suspended, addressed,
default, etc)
. twl4030-usb learned that it shouldn't be enabled during init
. Full DT support for DWC3 has been implemented
. ab8500-usb learned about pinctrl framework
. nop PHY learned about DeviceTree and regulators
. DWC3 learned about suspend/resume
. DWC3 can now be compiled in host-only and gadget-only (as well as
DRD) configurations
. UVC now enables streaming endpoint based on negotiated speed
. isp1301 now implements the PHY API properly
. configfs-based interface for gadget drivers which will lead to
the removal of all code which just combines functions together
to build functional gadget drivers.
. f_serial and f_obex were converted to new configfs interface while
maintaining old interface around.
- non-critical fixes:
. UVC gadget driver got fixes for Endpoint usage and stream calculation
. ab8500-usb fixed unbalanced clock and regulator API usage
. twl4030-usb got a fix for when OMAP3 is booted with cable connected
. fusb300_udc got a fix for DMA usage
. UVC got fixes for two assertions of the USB Video Class Compliance
specification revision 1.1
. build warning issues caused by recent addition of __must_check to
regulator API
These are all changes which deserve a mention, all other changes are related
to these one or minor spelling fixes and other similar tasks.
Signed-of-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/f_serial.c')
-rw-r--r-- | drivers/usb/gadget/f_serial.c | 174 |
1 files changed, 130 insertions, 44 deletions
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index da33cfb3031d..981113c9924d 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -12,6 +12,7 @@ #include <linux/slab.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/device.h> #include "u_serial.h" @@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f) /* interface descriptor: */ -static struct usb_interface_descriptor gser_interface_desc __initdata = { +static struct usb_interface_descriptor gser_interface_desc = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, /* .bInterfaceNumber = DYNAMIC */ @@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = { /* full speed support: */ -static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *gser_fs_function[] __initdata = { +static struct usb_descriptor_header *gser_fs_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_fs_in_desc, (struct usb_descriptor_header *) &gser_fs_out_desc, @@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = { /* high speed support: */ -static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *gser_hs_function[] __initdata = { +static struct usb_descriptor_header *gser_hs_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_hs_in_desc, (struct usb_descriptor_header *) &gser_hs_out_desc, NULL, }; -static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = { +static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = { .bLength = sizeof gser_ss_bulk_comp_desc, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, }; -static struct usb_descriptor_header *gser_ss_function[] __initdata = { +static struct usb_descriptor_header *gser_ss_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_ss_in_desc, (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, @@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f) /* serial function driver setup/binding */ -static int __init -gser_bind(struct usb_configuration *c, struct usb_function *f) +static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; + /* REVISIT might want instance-specific strings to help + * distinguish instances ... + */ + + /* maybe allocate device-global string ID */ + if (gser_string_defs[0].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + gser_string_defs[0].id = status; + } + /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) @@ -246,44 +258,115 @@ fail: return status; } -static void -gser_unbind(struct usb_configuration *c, struct usb_function *f) +static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) { - usb_free_all_descriptors(f); - kfree(func_to_gser(f)); + return container_of(to_config_group(item), struct f_serial_opts, + func_inst.group); } -/** - * gser_bind_config - add a generic serial function to a configuration - * @c: the configuration to support the serial instance - * @port_num: /dev/ttyGS* port this interface will use - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - */ -int __init gser_bind_config(struct usb_configuration *c, u8 port_num) +CONFIGFS_ATTR_STRUCT(f_serial_opts); +static ssize_t f_serial_attr_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) { - struct f_gser *gser; - int status; + struct f_serial_opts *opts = to_f_serial_opts(item); + struct f_serial_opts_attribute *f_serial_opts_attr = + container_of(attr, struct f_serial_opts_attribute, attr); + ssize_t ret = 0; - /* REVISIT might want instance-specific strings to help - * distinguish instances ... - */ + if (f_serial_opts_attr->show) + ret = f_serial_opts_attr->show(opts, page); - /* maybe allocate device-global string ID */ - if (gser_string_defs[0].id == 0) { - status = usb_string_id(c->cdev); - if (status < 0) - return status; - gser_string_defs[0].id = status; + return ret; +} + +static void serial_attr_release(struct config_item *item) +{ + struct f_serial_opts *opts = to_f_serial_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations serial_item_ops = { + .release = serial_attr_release, + .show_attribute = f_serial_attr_show, +}; + +static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page) +{ + return sprintf(page, "%u\n", opts->port_num); +} + +static struct f_serial_opts_attribute f_serial_port_num = + __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show); + +static struct configfs_attribute *acm_attrs[] = { + &f_serial_port_num.attr, + NULL, +}; + +static struct config_item_type serial_func_type = { + .ct_item_ops = &serial_item_ops, + .ct_attrs = acm_attrs, + .ct_owner = THIS_MODULE, +}; + +static void gser_free_inst(struct usb_function_instance *f) +{ + struct f_serial_opts *opts; + + opts = container_of(f, struct f_serial_opts, func_inst); + gserial_free_line(opts->port_num); + kfree(opts); +} + +static struct usb_function_instance *gser_alloc_inst(void) +{ + struct f_serial_opts *opts; + int ret; + + opts = kzalloc(sizeof(*opts), GFP_KERNEL); + if (!opts) + return ERR_PTR(-ENOMEM); + + opts->func_inst.free_func_inst = gser_free_inst; + ret = gserial_alloc_line(&opts->port_num); + if (ret) { + kfree(opts); + return ERR_PTR(ret); } + config_group_init_type_name(&opts->func_inst.group, "", + &serial_func_type); + + return &opts->func_inst; +} + +static void gser_free(struct usb_function *f) +{ + struct f_gser *serial; + + serial = func_to_gser(f); + kfree(serial); +} + +static void gser_unbind(struct usb_configuration *c, struct usb_function *f) +{ + usb_free_all_descriptors(f); +} + +struct usb_function *gser_alloc(struct usb_function_instance *fi) +{ + struct f_gser *gser; + struct f_serial_opts *opts; /* allocate and initialize one new instance */ - gser = kzalloc(sizeof *gser, GFP_KERNEL); + gser = kzalloc(sizeof(*gser), GFP_KERNEL); if (!gser) - return -ENOMEM; + return ERR_PTR(-ENOMEM); - gser->port_num = port_num; + opts = container_of(fi, struct f_serial_opts, func_inst); + + gser->port_num = opts->port_num; gser->port.func.name = "gser"; gser->port.func.strings = gser_strings; @@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num) gser->port.func.unbind = gser_unbind; gser->port.func.set_alt = gser_set_alt; gser->port.func.disable = gser_disable; + gser->port.func.free_func = gser_free; - status = usb_add_function(c, &gser->port.func); - if (status) - kfree(gser); - return status; + return &gser->port.func; } + +DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Al Borchers"); +MODULE_AUTHOR("David Brownell"); |