* parameters are in UTF-8 (superset of ASCII's 7 bit characters).
  */
 
-static ushort __initdata idVendor;
+static ushort idVendor;
 module_param(idVendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(idVendor, "USB Vendor ID");
 
-static ushort __initdata idProduct;
+static ushort idProduct;
 module_param(idProduct, ushort, S_IRUGO);
 MODULE_PARM_DESC(idProduct, "USB Product ID");
 
-static ushort __initdata bcdDevice;
+static ushort bcdDevice;
 module_param(bcdDevice, ushort, S_IRUGO);
 MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
 
-static char *__initdata iManufacturer;
+static char *iManufacturer;
 module_param(iManufacturer, charp, S_IRUGO);
 MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
 
-static char *__initdata iProduct;
+static char *iProduct;
 module_param(iProduct, charp, S_IRUGO);
 MODULE_PARM_DESC(iProduct, "USB Product string");
 
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
+
 /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *__initdata dev_addr;
+static char *dev_addr;
 module_param(dev_addr, charp, S_IRUGO);
 MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
 
 /* this address is invisible to ifconfig */
-static char *__initdata host_addr;
+static char *host_addr;
 module_param(host_addr, charp, S_IRUGO);
 MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 
 #define STRING_CDC                     7
 #define STRING_SUBSET                  8
 #define STRING_RNDIS                   9
+#define STRING_SERIALNUMBER            10
 
 /* holds our biggest descriptor (or RNDIS response) */
 #define USB_BUFSIZ     256
 
 static char                            manufacturer [50];
 static char                            product_desc [40] = DRIVER_DESC;
+static char                            serial_number [20];
 
 #ifdef DEV_CONFIG_CDC
 /* address that the host will use ... usually assigned at random */
 static struct usb_string               strings [] = {
        { STRING_MANUFACTURER,  manufacturer, },
        { STRING_PRODUCT,       product_desc, },
+       { STRING_SERIALNUMBER,  serial_number, },
        { STRING_DATA,          "Ethernet Data", },
 #ifdef DEV_CONFIG_CDC
        { STRING_CDC,           "CDC Ethernet", },
        return 0;
 }
 
-static void __init get_ether_addr (const char *str, u8 *dev_addr)
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
 {
        if (str) {
                unsigned        i;
                        dev_addr [i] = num;
                }
                if (is_valid_ether_addr (dev_addr))
-                       return;
+                       return 0;
        }
        random_ether_addr(dev_addr);
+       return 1;
 }
 
 static int __init
                strlcpy (manufacturer, iManufacturer, sizeof manufacturer);
        if (iProduct)
                strlcpy (product_desc, iProduct, sizeof product_desc);
+       if (iSerialNumber) {
+               device_desc.iSerialNumber = STRING_SERIALNUMBER,
+               strlcpy(serial_number, iSerialNumber, sizeof serial_number);
+       }
 
        /* all we really need is bulk IN/OUT */
        usb_ep_autoconfig_reset (gadget);
         * The host side address is used with CDC and RNDIS, and commonly
         * ends up in a persistent config database.
         */
-       get_ether_addr(dev_addr, net->dev_addr);
+       if (get_ether_addr(dev_addr, net->dev_addr))
+               dev_warn(&gadget->dev,
+                       "using random %s ethernet address\n", "self");
        if (cdc || rndis) {
-               get_ether_addr(host_addr, dev->host_mac);
+               if (get_ether_addr(host_addr, dev->host_mac))
+                       dev_warn(&gadget->dev,
+                               "using random %s ethernet address\n", "host");
 #ifdef DEV_CONFIG_CDC
                snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
                        dev->host_mac [0], dev->host_mac [1],