Skip to content

Commit

Permalink
usb gadget: link fixes for network gadget
Browse files Browse the repository at this point in the history
Change how the Ethernet/RNDIS gadget driver builds:  don't
use separate compilation, since it works poorly when key
parts are library code (with init sections etc).  Instead
be as close as we can to "gcc --combine ...".

This is a bit more complicated than most of the others
because it had to resolve a few symbol collisions.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Oct 16, 2008
1 parent 8a1ce2c commit 33376c1
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 145 deletions.
8 changes: 1 addition & 7 deletions drivers/usb/gadget/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,15 @@ obj-$(CONFIG_USB_M66592) += m66592-udc.o
#
# USB gadget drivers
#
C_UTILS = composite.o usbstring.o config.o epautoconf.o

g_zero-objs := zero.o
g_ether-objs := ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
g_ether-objs := ether.o
g_serial-objs := serial.o
g_midi-objs := gmidi.o
gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o
g_printer-objs := printer.o
g_cdc-objs := cdc2.o

ifeq ($(CONFIG_USB_ETH_RNDIS),y)
g_ether-objs += f_rndis.o rndis.o
endif

obj-$(CONFIG_USB_ZERO) += g_zero.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
Expand Down
28 changes: 26 additions & 2 deletions drivers/usb/gadget/ether.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,28 @@ static inline bool has_rndis(void)

/*-------------------------------------------------------------------------*/

/*
* Kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "composite.c"
#include "usbstring.c"
#include "config.c"
#include "epautoconf.c"

#include "f_ecm.c"
#include "f_subset.c"
#ifdef CONFIG_USB_ETH_RNDIS
#include "f_rndis.c"
#include "rndis.c"
#endif
#include "u_ether.c"

/*-------------------------------------------------------------------------*/

/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
* Instead: allocate your own, using normal USB-IF procedures.
*/
Expand Down Expand Up @@ -293,7 +315,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
* but if the controller isn't recognized at all then
* that assumption is a bit more likely to be wrong.
*/
WARNING(cdev, "controller '%s' not recognized; trying %s\n",
dev_warn(&gadget->dev,
"controller '%s' not recognized; trying %s\n",
gadget->name,
eth_config_driver.label);
device_desc.bcdDevice =
Expand Down Expand Up @@ -332,7 +355,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
if (status < 0)
goto fail;

INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
DRIVER_DESC);

return 0;

Expand Down
108 changes: 54 additions & 54 deletions drivers/usb/gadget/f_ecm.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
}

/* peak (theoretical) bulk transfer rate in bits-per-second */
static inline unsigned bitrate(struct usb_gadget *g)
static inline unsigned ecm_bitrate(struct usb_gadget *g)
{
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return 13 * 512 * 8 * 1000 * 8;
Expand All @@ -107,7 +107,7 @@ static inline unsigned bitrate(struct usb_gadget *g)
*/

#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */


/* interface descriptor: */
Expand All @@ -125,8 +125,8 @@ static struct usb_interface_descriptor ecm_control_intf __initdata = {
/* .iInterface = DYNAMIC */
};

static struct usb_cdc_header_desc header_desc __initdata = {
.bLength = sizeof header_desc,
static struct usb_cdc_header_desc ecm_header_desc __initdata = {
.bLength = sizeof ecm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,

Expand All @@ -141,8 +141,8 @@ static struct usb_cdc_union_desc ecm_union_desc __initdata = {
/* .bSlaveInterface0 = DYNAMIC */
};

static struct usb_cdc_ether_desc ether_desc __initdata = {
.bLength = sizeof ether_desc,
static struct usb_cdc_ether_desc ecm_desc __initdata = {
.bLength = sizeof ecm_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ETHERNET_TYPE,

Expand Down Expand Up @@ -186,60 +186,60 @@ static struct usb_interface_descriptor ecm_data_intf __initdata = {

/* full speed support: */

static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
.wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};

static struct usb_endpoint_descriptor fs_in_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};

static struct usb_endpoint_descriptor fs_out_desc __initdata = {
static struct usb_endpoint_descriptor fs_ecm_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};

static struct usb_descriptor_header *eth_fs_function[] __initdata = {
static struct usb_descriptor_header *ecm_fs_function[] __initdata = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &header_desc,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ether_desc,
(struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &fs_notify_desc,
(struct usb_descriptor_header *) &fs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
(struct usb_descriptor_header *) &fs_in_desc,
(struct usb_descriptor_header *) &fs_out_desc,
(struct usb_descriptor_header *) &fs_ecm_in_desc,
(struct usb_descriptor_header *) &fs_ecm_out_desc,
NULL,
};

/* high speed support: */

static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
.wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_in_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

Expand All @@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};

static struct usb_endpoint_descriptor hs_out_desc __initdata = {
static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

Expand All @@ -257,19 +257,19 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
.wMaxPacketSize = __constant_cpu_to_le16(512),
};

static struct usb_descriptor_header *eth_hs_function[] __initdata = {
static struct usb_descriptor_header *ecm_hs_function[] __initdata = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &header_desc,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ether_desc,
(struct usb_descriptor_header *) &ecm_desc,
/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &hs_notify_desc,
(struct usb_descriptor_header *) &hs_ecm_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
(struct usb_descriptor_header *) &hs_in_desc,
(struct usb_descriptor_header *) &hs_out_desc,
(struct usb_descriptor_header *) &hs_ecm_in_desc,
(struct usb_descriptor_header *) &hs_ecm_out_desc,
NULL,
};

Expand Down Expand Up @@ -329,14 +329,14 @@ static void ecm_do_notify(struct f_ecm *ecm)
event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
event->wValue = cpu_to_le16(0);
event->wLength = cpu_to_le16(8);
req->length = STATUS_BYTECOUNT;
req->length = ECM_STATUS_BYTECOUNT;

/* SPEED_CHANGE data is up/down speeds in bits/sec */
data = req->buf + sizeof *event;
data[0] = cpu_to_le32(bitrate(cdev->gadget));
data[0] = cpu_to_le32(ecm_bitrate(cdev->gadget));
data[1] = data[0];

DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
DBG(cdev, "notify speed %d\n", ecm_bitrate(cdev->gadget));
ecm->notify_state = ECM_NOTIFY_NONE;
break;
}
Expand Down Expand Up @@ -628,13 +628,13 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENODEV;

/* allocate instance-specific endpoints */
ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_in_desc);
if (!ep)
goto fail;
ecm->port.in_ep = ep;
ep->driver_data = cdev; /* claim */

ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
if (!ep)
goto fail;
ecm->port.out_ep = ep;
Expand All @@ -644,7 +644,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
* don't treat it that way. It's simpler, and some newer CDC
* profiles (wireless handsets) no longer treat it as optional.
*/
ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_notify_desc);
if (!ep)
goto fail;
ecm->notify = ep;
Expand All @@ -656,47 +656,47 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
if (!ecm->notify_req)
goto fail;
ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
ecm->notify_req->buf = kmalloc(ECM_STATUS_BYTECOUNT, GFP_KERNEL);
if (!ecm->notify_req->buf)
goto fail;
ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete;

/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(eth_fs_function);
f->descriptors = usb_copy_descriptors(ecm_fs_function);
if (!f->descriptors)
goto fail;

ecm->fs.in = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_in_desc);
ecm->fs.out = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_out_desc);
ecm->fs.notify = usb_find_endpoint(eth_fs_function,
f->descriptors, &fs_notify_desc);
ecm->fs.in = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_in_desc);
ecm->fs.out = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_out_desc);
ecm->fs.notify = usb_find_endpoint(ecm_fs_function,
f->descriptors, &fs_ecm_notify_desc);

/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_in_desc.bEndpointAddress =
fs_in_desc.bEndpointAddress;
hs_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
hs_notify_desc.bEndpointAddress =
fs_notify_desc.bEndpointAddress;
hs_ecm_in_desc.bEndpointAddress =
fs_ecm_in_desc.bEndpointAddress;
hs_ecm_out_desc.bEndpointAddress =
fs_ecm_out_desc.bEndpointAddress;
hs_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress;

/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
if (!f->hs_descriptors)
goto fail;

ecm->hs.in = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_in_desc);
ecm->hs.out = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_out_desc);
ecm->hs.notify = usb_find_endpoint(eth_hs_function,
f->hs_descriptors, &hs_notify_desc);
ecm->hs.in = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_in_desc);
ecm->hs.out = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_out_desc);
ecm->hs.notify = usb_find_endpoint(ecm_hs_function,
f->hs_descriptors, &hs_ecm_notify_desc);
}

/* NOTE: all that is done without knowing or caring about
Expand Down Expand Up @@ -795,7 +795,7 @@ int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (status < 0)
return status;
ecm_string_defs[1].id = status;
ether_desc.iMACAddress = status;
ecm_desc.iMACAddress = status;
}

/* allocate and initialize one new instance */
Expand Down
Loading

0 comments on commit 33376c1

Please sign in to comment.