Skip to content

Commit

Permalink
usb: gadget: f_subset: convert to new function interface with backwar…
Browse files Browse the repository at this point in the history
…d compatibility

Converting ecm subset to the new function interface requires converting
the USB subset's function code and its users.

This patch converts the f_subset.c to the new function interface.

The file is now compiled into a separate usb_f_subset.ko module.

The old function interface is provided by means of a preprocessor
conditional directives. After all users are converted, the old interface
can be removed.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Andrzej Pietrasiewicz authored and Felipe Balbi committed Jun 10, 2013
1 parent cf99e8c commit 8cedba7
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 15 deletions.
3 changes: 3 additions & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ config USB_F_PHONET
config USB_F_EEM
tristate

config USB_F_SUBSET
tristate

choice
tristate "USB Gadget Drivers"
default USB_ETH
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ usb_f_phonet-y := f_phonet.o
obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o
usb_f_eem-y := f_eem.o
obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o
usb_f_ecm_subset-y := f_subset.o
obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o

#
# USB gadget drivers
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/gadget/ether.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static inline bool has_rndis(void)
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "u_ecm.h"
#define USB_FSUBSET_INCLUDED
#include "f_subset.c"
#ifdef USB_ETH_RNDIS
#include "f_rndis.c"
Expand Down
136 changes: 121 additions & 15 deletions drivers/usb/gadget/f_subset.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@

#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>

#include "u_ether.h"

#include "u_gether.h"

/*
* This function packages a simple "CDC Subset" Ethernet port with no real
Expand Down Expand Up @@ -298,6 +299,35 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
int status;
struct usb_ep *ep;

#ifndef USB_FSUBSET_INCLUDED
struct f_gether_opts *gether_opts;

gether_opts = container_of(f->fi, struct f_gether_opts, func_inst);

/*
* 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 gether_opts->bound access
*/
if (!gether_opts->bound) {
gether_set_gadget(gether_opts->net, cdev->gadget);
status = gether_register_netdev(gether_opts->net);
if (status)
return status;
gether_opts->bound = true;
}
#endif
/* maybe allocate device-global string IDs */
if (geth_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, geth_string_defs);
if (status < 0)
return status;
subset_data_intf.iInterface = geth_string_defs[0].id;
ether_desc.iMACAddress = geth_string_defs[1].id;
}

/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
Expand Down Expand Up @@ -360,8 +390,10 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}

#ifdef USB_FSUBSET_INCLUDED

static void
geth_unbind(struct usb_configuration *c, struct usb_function *f)
geth_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
Expand All @@ -387,18 +419,6 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct f_gether *geth;
int status;

if (!ethaddr)
return -EINVAL;

/* maybe allocate device-global string IDs */
if (geth_string_defs[0].id == 0) {
status = usb_string_ids_tab(c->cdev, geth_string_defs);
if (status < 0)
return status;
subset_data_intf.iInterface = geth_string_defs[0].id;
ether_desc.iMACAddress = geth_string_defs[1].id;
}

/* allocate and initialize one new instance */
geth = kzalloc(sizeof *geth, GFP_KERNEL);
if (!geth)
Expand All @@ -414,7 +434,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
geth->port.func.name = "cdc_subset";
geth->port.func.strings = geth_strings;
geth->port.func.bind = geth_bind;
geth->port.func.unbind = geth_unbind;
geth->port.func.unbind = geth_old_unbind;
geth->port.func.set_alt = geth_set_alt;
geth->port.func.disable = geth_disable;

Expand All @@ -423,3 +443,89 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
kfree(geth);
return status;
}

#else

static void geth_free_inst(struct usb_function_instance *f)
{
struct f_gether_opts *opts;

opts = container_of(f, struct f_gether_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
kfree(opts);
}

static struct usb_function_instance *geth_alloc_inst(void)
{
struct f_gether_opts *opts;

opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);

opts->func_inst.free_func_inst = geth_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net))
return ERR_CAST(opts->net);

return &opts->func_inst;
}

static void geth_free(struct usb_function *f)
{
struct f_gether *eth;

eth = func_to_geth(f);
kfree(eth);
}

static void geth_unbind(struct usb_configuration *c, struct usb_function *f)
{
geth_string_defs[0].id = 0;
usb_free_all_descriptors(f);
}

static struct usb_function *geth_alloc(struct usb_function_instance *fi)
{
struct f_gether *geth;
struct f_gether_opts *opts;
int status;

/* allocate and initialize one new instance */
geth = kzalloc(sizeof(*geth), GFP_KERNEL);
if (!geth)
return ERR_PTR(-ENOMEM);

opts = container_of(fi, struct f_gether_opts, func_inst);

/* export host's Ethernet address in CDC format */
status = gether_get_host_addr_cdc(opts->net, geth->ethaddr,
sizeof(geth->ethaddr));
if (status < 12) {
kfree(geth);
return ERR_PTR(-EINVAL);
}
geth_string_defs[1].s = geth->ethaddr;

geth->port.ioport = netdev_priv(opts->net);
geth->port.cdc_filter = DEFAULT_FILTER;

geth->port.func.name = "cdc_subset";
geth->port.func.strings = geth_strings;
geth->port.func.bind = geth_bind;
geth->port.func.unbind = geth_unbind;
geth->port.func.set_alt = geth_set_alt;
geth->port.func.disable = geth_disable;
geth->port.func.free_func = geth_free;

return &geth->port.func;
}

DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");

#endif
1 change: 1 addition & 0 deletions drivers/usb/gadget/g_ffs.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#define USBF_ECM_INCLUDED
# include "f_ecm.c"
#define USB_FSUBSET_INCLUDED
# include "f_subset.c"
# ifdef USB_ETH_RNDIS
# include "f_rndis.c"
Expand Down
27 changes: 27 additions & 0 deletions drivers/usb/gadget/u_gether.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* u_gether.h
*
* Utility definitions for the subset function
*
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef U_GETHER_H
#define U_GETHER_H

#include <linux/usb/composite.h>

struct f_gether_opts {
struct usb_function_instance func_inst;
struct net_device *net;
bool bound;
};

#endif /* U_GETHER_H */

0 comments on commit 8cedba7

Please sign in to comment.