浏览代码

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (128 commits)
  USB: fix codingstyle issues in drivers/usb/core/*.c
  USB: fix codingstyle issues in drivers/usb/core/message.c
  USB: fix codingstyle issues in drivers/usb/core/hcd-pci.c
  USB: fix codingstyle issues in drivers/usb/core/devio.c
  USB: fix codingstyle issues in drivers/usb/core/devices.c
  USB: fix codingstyle issues in drivers/usb/core/*.h
  USB: fix codingstyle issues in include/linux/usb/
  USB: fix codingstyle issues in include/linux/usb.h
  USB: mark USB drivers as being GPL only
  USB: use a real vendor and product id for root hubs
  USB: mount options: fix usbfs
  USB: Fix usb_serial_driver structure for Kobil cardreader driver.
  usb: ehci should use u16 for isochronous intervals
  usb: ehci, remove false clear-reset path
  USB: Use menuconfig objects
  usb: ohci-sm501 driver
  usb: dma bounce buffer support
  USB: last abuses of intfdata in close for usb-serial drivers
  USB: kl5kusb105 don't flush to logically disconnected devices
  USB: oti6858: cleanup
  ...
Linus Torvalds 17 年之前
父节点
当前提交
b6cf160c4b
共有 100 个文件被更改,包括 5929 次插入1611 次删除
  1. 33 0
      Documentation/ABI/testing/sysfs-bus-usb
  2. 0 16
      Documentation/feature-removal-schedule.txt
  3. 510 0
      Documentation/usb/gadget_printer.txt
  4. 84 0
      Documentation/usb/iuu_phoenix.txt
  5. 2 7
      arch/arm/mach-pxa/tosa.c
  6. 0 23
      drivers/block/ub.c
  7. 5 0
      drivers/usb/Kconfig
  8. 4 5
      drivers/usb/atm/Kconfig
  9. 3 3
      drivers/usb/atm/ueagle-atm.c
  10. 78 16
      drivers/usb/class/cdc-acm.c
  11. 2 0
      drivers/usb/class/cdc-acm.h
  12. 15 0
      drivers/usb/core/Kconfig
  13. 12 8
      drivers/usb/core/buffer.c
  14. 8 6
      drivers/usb/core/config.c
  15. 82 72
      drivers/usb/core/devices.c
  16. 209 150
      drivers/usb/core/devio.c
  17. 23 21
      drivers/usb/core/driver.c
  18. 2 2
      drivers/usb/core/file.c
  19. 78 67
      drivers/usb/core/hcd-pci.c
  20. 176 40
      drivers/usb/core/hcd.c
  21. 48 44
      drivers/usb/core/hcd.h
  22. 49 39
      drivers/usb/core/hub.c
  23. 9 9
      drivers/usb/core/hub.h
  24. 36 6
      drivers/usb/core/inode.c
  25. 215 215
      drivers/usb/core/message.c
  26. 1 1
      drivers/usb/core/notify.c
  27. 3 3
      drivers/usb/core/otg_whitelist.h
  28. 59 10
      drivers/usb/core/sysfs.c
  29. 19 18
      drivers/usb/core/urb.c
  30. 44 73
      drivers/usb/core/usb.c
  31. 11 10
      drivers/usb/core/usb.h
  32. 29 4
      drivers/usb/gadget/Kconfig
  33. 3 0
      drivers/usb/gadget/Makefile
  34. 2 1
      drivers/usb/gadget/amd5536udc.c
  35. 65 22
      drivers/usb/gadget/at91_udc.c
  36. 6 11
      drivers/usb/gadget/at91_udc.h
  37. 4 7
      drivers/usb/gadget/atmel_usba_udc.c
  38. 2 5
      drivers/usb/gadget/atmel_usba_udc.h
  39. 11 27
      drivers/usb/gadget/dummy_hcd.c
  40. 3 3
      drivers/usb/gadget/ether.c
  41. 5 9
      drivers/usb/gadget/file_storage.c
  42. 2 2
      drivers/usb/gadget/fsl_usb2_udc.c
  43. 3 3
      drivers/usb/gadget/fsl_usb2_udc.h
  44. 3 3
      drivers/usb/gadget/gmidi.c
  45. 1 0
      drivers/usb/gadget/goku_udc.c
  46. 1 1
      drivers/usb/gadget/inode.c
  47. 1 0
      drivers/usb/gadget/lh7a40x_udc.c
  48. 79 25
      drivers/usb/gadget/m66592-udc.c
  49. 54 0
      drivers/usb/gadget/m66592-udc.h
  50. 1 1
      drivers/usb/gadget/net2280.c
  51. 50 23
      drivers/usb/gadget/omap_udc.c
  52. 4 9
      drivers/usb/gadget/omap_udc.h
  53. 1592 0
      drivers/usb/gadget/printer.c
  54. 67 74
      drivers/usb/gadget/pxa2xx_udc.c
  55. 15 10
      drivers/usb/gadget/pxa2xx_udc.h
  56. 8 12
      drivers/usb/gadget/rndis.c
  57. 2 2
      drivers/usb/gadget/s3c2410_udc.c
  58. 79 74
      drivers/usb/gadget/serial.c
  59. 2 2
      drivers/usb/gadget/zero.c
  60. 11 11
      drivers/usb/host/Kconfig
  61. 1 0
      drivers/usb/host/ehci-au1xxx.c
  62. 188 43
      drivers/usb/host/ehci-dbg.c
  63. 2 1
      drivers/usb/host/ehci-fsl.c
  64. 118 41
      drivers/usb/host/ehci-hcd.c
  65. 61 37
      drivers/usb/host/ehci-hub.c
  66. 152 0
      drivers/usb/host/ehci-ixp4xx.c
  67. 272 0
      drivers/usb/host/ehci-orion.c
  68. 2 1
      drivers/usb/host/ehci-pci.c
  69. 238 0
      drivers/usb/host/ehci-ppc-of.c
  70. 1 0
      drivers/usb/host/ehci-ppc-soc.c
  71. 1 0
      drivers/usb/host/ehci-ps3.c
  72. 13 12
      drivers/usb/host/ehci-q.c
  73. 84 68
      drivers/usb/host/ehci-sched.c
  74. 30 10
      drivers/usb/host/ehci.h
  75. 0 1
      drivers/usb/host/isp116x-hcd.c
  76. 31 0
      drivers/usb/host/ohci-at91.c
  77. 184 29
      drivers/usb/host/ohci-dbg.c
  78. 30 4
      drivers/usb/host/ohci-hcd.c
  79. 143 0
      drivers/usb/host/ohci-sh.c
  80. 264 0
      drivers/usb/host/ohci-sm501.c
  81. 7 0
      drivers/usb/host/ohci.h
  82. 1 1
      drivers/usb/host/r8a66597.h
  83. 0 2
      drivers/usb/image/mdc800.c
  84. 5 2
      drivers/usb/misc/cypress_cy7c63.c
  85. 1 1
      drivers/usb/misc/iowarrior.c
  86. 16 14
      drivers/usb/misc/legousbtower.c
  87. 1 28
      drivers/usb/misc/sisusbvga/sisusb.c
  88. 0 3
      drivers/usb/misc/sisusbvga/sisusb.h
  89. 10 10
      drivers/usb/misc/usbtest.c
  90. 12 10
      drivers/usb/mon/mon_bin.c
  91. 25 12
      drivers/usb/serial/Kconfig
  92. 1 0
      drivers/usb/serial/Makefile
  93. 4 1
      drivers/usb/serial/airprime.c
  94. 3 1
      drivers/usb/serial/ark3116.c
  95. 16 21
      drivers/usb/serial/belkin_sa.c
  96. 54 36
      drivers/usb/serial/console.c
  97. 10 1
      drivers/usb/serial/cp2101.c
  98. 0 1
      drivers/usb/serial/cyberjack.c
  99. 16 9
      drivers/usb/serial/cypress_m8.c
  100. 7 6
      drivers/usb/serial/digi_acceleport.c

+ 33 - 0
Documentation/ABI/testing/sysfs-bus-usb

@@ -52,3 +52,36 @@ Description:
 		facility is inherently dangerous, it is disabled by default
 		facility is inherently dangerous, it is disabled by default
 		for all devices except hubs.  For more information, see
 		for all devices except hubs.  For more information, see
 		Documentation/usb/persist.txt.
 		Documentation/usb/persist.txt.
+
+What:		/sys/bus/usb/device/.../power/connected_duration
+Date:		January 2008
+KernelVersion:	2.6.25
+Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		is present.  When read, it returns the total time (in msec)
+		that the USB device has been connected to the machine.  This
+		file is read-only.
+Users:
+		PowerTOP <power@bughost.org>
+		http://www.lesswatts.org/projects/powertop/
+
+What:		/sys/bus/usb/device/.../power/active_duration
+Date:		January 2008
+KernelVersion:	2.6.25
+Contact:	Sarah Sharp <sarah.a.sharp@intel.com>
+Description:
+		If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+		is present.  When read, it returns the total time (in msec)
+		that the USB device has been active, i.e. not in a suspended
+		state.  This file is read-only.
+
+		Tools can use this file and the connected_duration file to
+		compute the percentage of time that a device has been active.
+		For example,
+		echo $((100 * `cat active_duration` / `cat connected_duration`))
+		will give an integer percentage.  Note that this does not
+		account for counter wrap.
+Users:
+		PowerTOP <power@bughost.org>
+		http://www.lesswatts.org/projects/powertop/

+ 0 - 16
Documentation/feature-removal-schedule.txt

@@ -156,22 +156,6 @@ Who:	Arjan van de Ven <arjan@linux.intel.com>
 
 
 ---------------------------
 ---------------------------
 
 
-What:	USB driver API moves to EXPORT_SYMBOL_GPL
-When:	February 2008
-Files:	include/linux/usb.h, drivers/usb/core/driver.c
-Why:	The USB subsystem has changed a lot over time, and it has been
-	possible to create userspace USB drivers using usbfs/libusb/gadgetfs
-	that operate as fast as the USB bus allows.  Because of this, the USB
-	subsystem will not be allowing closed source kernel drivers to
-	register with it, after this grace period is over.  If anyone needs
-	any help in converting their closed source drivers over to use the
-	userspace filesystems, please contact the
-	linux-usb-devel@lists.sourceforge.net mailing list, and the developers
-	there will be glad to help you out.
-Who:	Greg Kroah-Hartman <gregkh@suse.de>
-
----------------------------
-
 What:	vm_ops.nopage
 What:	vm_ops.nopage
 When:	Soon, provided in-kernel callers have been converted
 When:	Soon, provided in-kernel callers have been converted
 Why:	This interface is replaced by vm_ops.fault, but it has been around
 Why:	This interface is replaced by vm_ops.fault, but it has been around

+ 510 - 0
Documentation/usb/gadget_printer.txt

@@ -0,0 +1,510 @@
+
+                       Linux USB Printer Gadget Driver
+                                 06/04/2007
+
+              Copyright (C) 2007 Craig W. Nadler <craig@nadler.us>
+
+
+
+GENERAL
+=======
+
+This driver may be used if you are writing printer firmware using Linux as
+the embedded OS. This driver has nothing to do with using a printer with
+your Linux host system.
+
+You will need a USB device controller and a Linux driver for it that accepts
+a gadget / "device class" driver using the Linux USB Gadget API. After the
+USB device controller driver is loaded then load the printer gadget driver.
+This will present a printer interface to the USB Host that your USB Device
+port is connected to.
+
+This driver is structured for printer firmware that runs in user mode. The
+user mode printer firmware will read and write data from the kernel mode
+printer gadget driver using a device file. The printer returns a printer status
+byte when the USB HOST sends a device request to get the printer status.  The
+user space firmware can read or write this status byte using a device file
+/dev/g_printer . Both blocking and non-blocking read/write calls are supported.
+
+
+
+
+HOWTO USE THIS DRIVER
+=====================
+
+To load the USB device controller driver and the printer gadget driver. The
+following example uses the Netchip 2280 USB device controller driver:
+
+modprobe net2280
+modprobe g_printer
+
+
+The follow command line parameter can be used when loading the printer gadget
+(ex: modprobe g_printer idVendor=0x0525 idProduct=0xa4a8 ):
+
+idVendor - This is the Vendor ID used in the device descriptor. The default is
+	the Netchip vendor id 0x0525. YOU MUST CHANGE TO YOUR OWN VENDOR ID
+	BEFORE RELEASING A PRODUCT. If you plan to release a product and don't
+	already have a Vendor ID please see www.usb.org for details on how to
+	get one.
+
+idProduct - This is the Product ID used in the device descriptor. The default
+	is 0xa4a8, you should change this to an ID that's not used by any of
+	your other USB products if you have any. It would be a good idea to
+	start numbering your products starting with say 0x0001.
+
+bcdDevice - This is the version number of your product. It would be a good idea
+	to put your firmware version here.
+
+iManufacturer - A string containing the name of the Vendor.
+
+iProduct - A string containing the Product Name.
+
+iSerialNum - A string containing the Serial Number. This should be changed for
+	each unit of your product.
+
+iPNPstring -  The PNP ID string used for this printer. You will want to set
+	either on the command line or hard code the PNP ID string used for
+	your printer product.
+
+qlen - The number of 8k buffers to use per endpoint. The default is 10, you
+	should tune this for your product. You may also want to tune the
+	size of each buffer for your product.
+
+
+
+
+USING THE EXAMPLE CODE
+======================
+
+This example code talks to stdout, instead of a print engine.
+
+To compile the test code below:
+
+1) save it to a file called prn_example.c
+2) compile the code with the follow command:
+	 gcc prn_example.c -o prn_example
+
+
+
+To read printer data from the host to stdout:
+
+	# prn_example -read_data
+
+
+To write printer data from a file (data_file) to the host:
+
+	# cat data_file | prn_example -write_data
+
+
+To get the current printer status for the gadget driver:
+
+	# prn_example -get_status
+
+	Printer status is:
+	     Printer is NOT Selected
+	     Paper is Out
+	     Printer OK
+
+
+To set printer to Selected/On-line:
+
+	# prn_example -selected
+
+
+To set printer to Not Selected/Off-line:
+
+	# prn_example -not_selected
+
+
+To set paper status to paper out:
+
+	# prn_example -paper_out
+
+
+To set paper status to paper loaded:
+
+	# prn_example -paper_loaded
+
+
+To set error status to printer OK:
+
+	# prn_example -no_error
+
+
+To set error status to ERROR:
+
+	# prn_example -error
+
+
+
+
+EXAMPLE CODE
+============
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <linux/poll.h>
+#include <sys/ioctl.h>
+#include <linux/usb/g_printer.h>
+
+#define PRINTER_FILE			"/dev/g_printer"
+#define BUF_SIZE			512
+
+
+/*
+ * 'usage()' - Show program usage.
+ */
+
+static void
+usage(const char *option)		/* I - Option string or NULL */
+{
+	if (option) {
+		fprintf(stderr,"prn_example: Unknown option \"%s\"!\n",
+				option);
+	}
+
+	fputs("\n", stderr);
+	fputs("Usage: prn_example -[options]\n", stderr);
+	fputs("Options:\n", stderr);
+	fputs("\n", stderr);
+	fputs("-get_status    Get the current printer status.\n", stderr);
+	fputs("-selected      Set the selected status to selected.\n", stderr);
+	fputs("-not_selected  Set the selected status to NOT selected.\n",
+			stderr);
+	fputs("-error         Set the error status to error.\n", stderr);
+	fputs("-no_error      Set the error status to NO error.\n", stderr);
+	fputs("-paper_out     Set the paper status to paper out.\n", stderr);
+	fputs("-paper_loaded  Set the paper status to paper loaded.\n",
+			stderr);
+	fputs("-read_data     Read printer data from driver.\n", stderr);
+	fputs("-write_data    Write printer sata to driver.\n", stderr);
+	fputs("-NB_read_data  (Non-Blocking) Read printer data from driver.\n",
+			stderr);
+	fputs("\n\n", stderr);
+
+	exit(1);
+}
+
+
+static int
+read_printer_data()
+{
+	struct pollfd	fd[1];
+
+	/* Open device file for printer gadget. */
+	fd[0].fd = open(PRINTER_FILE, O_RDWR);
+	if (fd[0].fd < 0) {
+		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+		close(fd[0].fd);
+		return(-1);
+	}
+
+	fd[0].events = POLLIN | POLLRDNORM;
+
+	while (1) {
+		static char buf[BUF_SIZE];
+		int bytes_read;
+		int retval;
+
+		/* Wait for up to 1 second for data. */
+		retval = poll(fd, 1, 1000);
+
+		if (retval && (fd[0].revents & POLLRDNORM)) {
+
+			/* Read data from printer gadget driver. */
+			bytes_read = read(fd[0].fd, buf, BUF_SIZE);
+
+			if (bytes_read < 0) {
+				printf("Error %d reading from %s\n",
+						fd[0].fd, PRINTER_FILE);
+				close(fd[0].fd);
+				return(-1);
+			} else if (bytes_read > 0) {
+				/* Write data to standard OUTPUT (stdout). */
+				fwrite(buf, 1, bytes_read, stdout);
+				fflush(stdout);
+			}
+
+		}
+
+	}
+
+	/* Close the device file. */
+	close(fd[0].fd);
+
+	return 0;
+}
+
+
+static int
+write_printer_data()
+{
+	struct pollfd	fd[1];
+
+	/* Open device file for printer gadget. */
+	fd[0].fd = open (PRINTER_FILE, O_RDWR);
+	if (fd[0].fd < 0) {
+		printf("Error %d opening %s\n", fd[0].fd, PRINTER_FILE);
+		close(fd[0].fd);
+		return(-1);
+	}
+
+	fd[0].events = POLLOUT | POLLWRNORM;
+
+	while (1) {
+		int retval;
+		static char buf[BUF_SIZE];
+		/* Read data from standard INPUT (stdin). */
+		int bytes_read = fread(buf, 1, BUF_SIZE, stdin);
+
+		if (!bytes_read) {
+			break;
+		}
+
+		while (bytes_read) {
+
+			/* Wait for up to 1 second to sent data. */
+			retval = poll(fd, 1, 1000);
+
+			/* Write data to printer gadget driver. */
+			if (retval && (fd[0].revents & POLLWRNORM)) {
+				retval = write(fd[0].fd, buf, bytes_read);
+				if (retval < 0) {
+					printf("Error %d writing to %s\n",
+							fd[0].fd,
+							PRINTER_FILE);
+					close(fd[0].fd);
+					return(-1);
+				} else {
+					bytes_read -= retval;
+				}
+
+			}
+
+		}
+
+	}
+
+	/* Wait until the data has been sent. */
+	fsync(fd[0].fd);
+
+	/* Close the device file. */
+	close(fd[0].fd);
+
+	return 0;
+}
+
+
+static int
+read_NB_printer_data()
+{
+	int		fd;
+	static char	buf[BUF_SIZE];
+	int		bytes_read;
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR|O_NONBLOCK);
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	while (1) {
+		/* Read data from printer gadget driver. */
+		bytes_read = read(fd, buf, BUF_SIZE);
+		if (bytes_read <= 0) {
+			break;
+		}
+
+		/* Write data to standard OUTPUT (stdout). */
+		fwrite(buf, 1, bytes_read, stdout);
+		fflush(stdout);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return 0;
+}
+
+
+static int
+get_printer_status()
+{
+	int	retval;
+	int	fd;
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR);
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	/* Make the IOCTL call. */
+	retval = ioctl(fd, GADGET_GET_PRINTER_STATUS);
+	if (retval < 0) {
+		fprintf(stderr, "ERROR: Failed to set printer status\n");
+		return(-1);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return(retval);
+}
+
+
+static int
+set_printer_status(unsigned char buf, int clear_printer_status_bit)
+{
+	int	retval;
+	int	fd;
+
+	retval = get_printer_status();
+	if (retval < 0) {
+		fprintf(stderr, "ERROR: Failed to get printer status\n");
+		return(-1);
+	}
+
+	/* Open device file for printer gadget. */
+	fd = open(PRINTER_FILE, O_RDWR);
+
+	if (fd < 0) {
+		printf("Error %d opening %s\n", fd, PRINTER_FILE);
+		close(fd);
+		return(-1);
+	}
+
+	if (clear_printer_status_bit) {
+		retval &= ~buf;
+	} else {
+		retval |= buf;
+	}
+
+	/* Make the IOCTL call. */
+	if (ioctl(fd, GADGET_SET_PRINTER_STATUS, (unsigned char)retval)) {
+		fprintf(stderr, "ERROR: Failed to set printer status\n");
+		return(-1);
+	}
+
+	/* Close the device file. */
+	close(fd);
+
+	return 0;
+}
+
+
+static int
+display_printer_status()
+{
+	char	printer_status;
+
+	printer_status = get_printer_status();
+	if (printer_status < 0) {
+		fprintf(stderr, "ERROR: Failed to get printer status\n");
+		return(-1);
+	}
+
+	printf("Printer status is:\n");
+	if (printer_status & PRINTER_SELECTED) {
+		printf("     Printer is Selected\n");
+	} else {
+		printf("     Printer is NOT Selected\n");
+	}
+	if (printer_status & PRINTER_PAPER_EMPTY) {
+		printf("     Paper is Out\n");
+	} else {
+		printf("     Paper is Loaded\n");
+	}
+	if (printer_status & PRINTER_NOT_ERROR) {
+		printf("     Printer OK\n");
+	} else {
+		printf("     Printer ERROR\n");
+	}
+
+	return(0);
+}
+
+
+int
+main(int  argc, char *argv[])
+{
+	int	i;		/* Looping var */
+	int	retval = 0;
+
+	/* No Args */
+	if (argc == 1) {
+		usage(0);
+		exit(0);
+	}
+
+	for (i = 1; i < argc && !retval; i ++) {
+
+		if (argv[i][0] != '-') {
+			continue;
+		}
+
+		if (!strcmp(argv[i], "-get_status")) {
+			if (display_printer_status()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-paper_loaded")) {
+			if (set_printer_status(PRINTER_PAPER_EMPTY, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-paper_out")) {
+			if (set_printer_status(PRINTER_PAPER_EMPTY, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-selected")) {
+			if (set_printer_status(PRINTER_SELECTED, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-not_selected")) {
+			if (set_printer_status(PRINTER_SELECTED, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-error")) {
+			if (set_printer_status(PRINTER_NOT_ERROR, 1)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-no_error")) {
+			if (set_printer_status(PRINTER_NOT_ERROR, 0)) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-read_data")) {
+			if (read_printer_data()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-write_data")) {
+			if (write_printer_data()) {
+				retval = 1;
+			}
+
+		} else if (!strcmp(argv[i], "-NB_read_data")) {
+			if (read_NB_printer_data()) {
+				retval = 1;
+			}
+
+		} else {
+			usage(argv[i]);
+			retval = 1;
+		}
+	}
+
+	exit(retval);
+}

+ 84 - 0
Documentation/usb/iuu_phoenix.txt

@@ -0,0 +1,84 @@
+Infinity Usb Unlimited Readme
+-----------------------------
+
+Hi all,
+
+
+This module provide a serial interface to use your
+IUU unit in phoenix mode. Loading this module will
+bring a ttyUSB[0-x] interface. This driver must be
+used by your favorite application to pilot the IUU
+
+This driver is still in beta stage, so bugs can
+occur and your system may freeze. As far I now,
+I never had any problem with it, but I'm not a real
+guru, so don't blame me if your system is unstable
+
+You can plug more than one IUU. Every unit will
+have his own device file(/dev/ttyUSB0,/dev/ttyUSB1,...)
+
+
+
+How to tune the reader speed ?
+
+ A few parameters can be used at load time
+ To use parameters, just unload the module if it is
+ already loaded and use modprobe iuu_phoenix param=value.
+ In case of prebuilt module, use the command
+ insmod iuu_phoenix param=value.
+
+ Example:
+
+ modprobe iuu_phoenix clockmode=3
+
+ The parameters are:
+
+ parm:           clockmode:1=3Mhz579,2=3Mhz680,3=6Mhz (int)
+ parm:           boost:overclock boost percent 100 to 500 (int)
+ parm:           cdmode:Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, 4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING (int)
+ parm:           xmas:xmas color enabled or not (bool)
+ parm:           debug:Debug enabled or not (bool)
+
+-  clockmode will provide 3 different base settings commonly adopted by
+   different software:
+ 	1. 3Mhz579
+	2. 3Mhz680
+	3. 6Mhz
+
+-  boost provide a way to overclock the reader ( my favorite :-)  )
+   For example to have best performance than a simple clockmode=3, try this:
+
+      modprobe boost=195
+
+   This will put the reader in a base of 3Mhz579 but boosted a 195 % !
+   the real clock will be now : 6979050 Hz ( 6Mhz979 ) and will increase
+   the speed to a score 10 to 20% better than the simple clockmode=3 !!!
+
+
+-  cdmode permit to setup the signal used to inform the userland ( ioctl answer )
+   if the card is present or not. Eight signals are possible.
+
+-  xmas is completely useless except for your eyes. This is one of my friend who was
+   so sad to have a nice device like the iuu without seeing all color range available.
+   So I have added this option to permit him to see a lot of color ( each activity change the color
+   and the frequency randomly )
+
+-  debug will produce a lot of debugging messages...
+
+
+ Last notes:
+
+ Don't worry about the serial settings, the serial emulation
+ is an abstraction, so use any speed or parity setting will
+ work. ( This will not change anything ).Later I will perhaps
+ use this settings to deduce de boost but is that feature
+ really necessary ?
+ The autodetect feature used is the serial CD. If that doesn't
+ work for your software, disable detection mechanism in it.
+
+
+ Have fun !
+
+ Alain Degreffe
+
+ eczema(at)ecze.com

+ 2 - 7
arch/arm/mach-pxa/tosa.c

@@ -157,15 +157,10 @@ static void tosa_udc_command(int cmd)
 	}
 	}
 }
 }
 
 
-static int tosa_udc_is_connected(void)
-{
-	return ((GPLR(TOSA_GPIO_USB_IN) & GPIO_bit(TOSA_GPIO_USB_IN)) == 0);
-}
-
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
 	.udc_command		= tosa_udc_command,
 	.udc_command		= tosa_udc_command,
-	.udc_is_connected	= tosa_udc_is_connected,
+	.gpio_vbus		= TOSA_GPIO_USB_IN,
+	.gpio_vbus_inverted	= 1,
 };
 };
 
 
 /*
 /*

+ 0 - 23
drivers/block/ub.c

@@ -922,11 +922,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
 
 
-	/* Fill what we shouldn't be filling, because usb-storage did so. */
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
-
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		/* XXX Clear stalls */
 		ub_complete(&sc->work_done);
 		ub_complete(&sc->work_done);
@@ -1313,9 +1308,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 	sc->last_pipe = pipe;
 	sc->last_pipe = pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
 	    sg->length, ub_urb_complete, sc);
 	    sg->length, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		/* XXX Clear stalls */
@@ -1356,9 +1348,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 	sc->last_pipe = sc->recv_bulk_pipe;
 	sc->last_pipe = sc->recv_bulk_pipe;
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		/* XXX Clear stalls */
 		/* XXX Clear stalls */
@@ -1473,9 +1462,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
 
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
 		ub_complete(&sc->work_done);
 		ub_complete(&sc->work_done);
@@ -1953,9 +1939,6 @@ static int ub_sync_reset(struct ub_dev *sc)
 
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
 		printk(KERN_WARNING
@@ -2007,9 +1990,6 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
 
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
 	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
 	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
 		goto err_submit;
 		goto err_submit;
@@ -2077,9 +2057,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
 
 
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-	sc->work_urb.actual_length = 0;
-	sc->work_urb.error_count = 0;
-	sc->work_urb.status = 0;
 
 
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
 		printk(KERN_WARNING
 		printk(KERN_WARNING

+ 5 - 0
drivers/usb/Kconfig

@@ -42,6 +42,10 @@ config USB_ARCH_HAS_OHCI
 	default y if PPC_MPC52xx
 	default y if PPC_MPC52xx
 	# MIPS:
 	# MIPS:
 	default y if SOC_AU1X00
 	default y if SOC_AU1X00
+	# SH:
+	default y if CPU_SUBTYPE_SH7720
+	default y if CPU_SUBTYPE_SH7721
+	default y if CPU_SUBTYPE_SH7763
 	# more:
 	# more:
 	default PCI
 	default PCI
 
 
@@ -50,6 +54,7 @@ config USB_ARCH_HAS_EHCI
 	boolean
 	boolean
 	default y if PPC_83xx
 	default y if PPC_83xx
 	default y if SOC_AU1200
 	default y if SOC_AU1200
+	default y if ARCH_IXP4XX
 	default PCI
 	default PCI
 
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.

+ 4 - 5
drivers/usb/atm/Kconfig

@@ -2,10 +2,7 @@
 # USB/ATM DSL configuration
 # USB/ATM DSL configuration
 #
 #
 
 
-menu "USB DSL modem support"
-	depends on USB
-
-config USB_ATM
+menuconfig USB_ATM
 	tristate "USB DSL modem support"
 	tristate "USB DSL modem support"
 	depends on USB && ATM
 	depends on USB && ATM
 	select CRC32
 	select CRC32
@@ -18,6 +15,8 @@ config USB_ATM
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbatm.
 	  module will be called usbatm.
 
 
+if USB_ATM
+
 config USB_SPEEDTOUCH
 config USB_SPEEDTOUCH
 	tristate "Speedtouch USB support"
 	tristate "Speedtouch USB support"
 	depends on USB_ATM
 	depends on USB_ATM
@@ -70,4 +69,4 @@ config USB_XUSBATM
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called xusbatm.
 	  module will be called xusbatm.
 
 
-endmenu
+endif # USB_ATM

+ 3 - 3
drivers/usb/atm/ueagle-atm.c

@@ -999,7 +999,7 @@ static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot)
 		bi.dwAddress = swab32(blockidx->PageAddress);
 		bi.dwAddress = swab32(blockidx->PageAddress);
 
 
 		uea_dbg(INS_TO_USBDEV(sc),
 		uea_dbg(INS_TO_USBDEV(sc),
-		       "sending block %u for DSP page %u size %u adress %x\n",
+		       "sending block %u for DSP page %u size %u address %x\n",
 		       blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
 		       blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress));
 
 
 		/* send block info through the IDMA pipe */
 		/* send block info through the IDMA pipe */
@@ -1990,7 +1990,7 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
 	return;
 	return;
 
 
 bad2:
 bad2:
-	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
 			"Function : %d, Subfunction : %d\n",
 			"Function : %d, Subfunction : %d\n",
 			E1_FUNCTION_TYPE(cmv->bFunction),
 			E1_FUNCTION_TYPE(cmv->bFunction),
 			E1_FUNCTION_SUBTYPE(cmv->bFunction));
 			E1_FUNCTION_SUBTYPE(cmv->bFunction));
@@ -2038,7 +2038,7 @@ static void uea_dispatch_cmv_e4(struct uea_softc *sc, struct intr_pkt *intr)
 	return;
 	return;
 
 
 bad2:
 bad2:
-	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+	uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
 			"Function : %d, Subfunction : %d\n",
 			"Function : %d, Subfunction : %d\n",
 			E4_FUNCTION_TYPE(cmv->wFunction),
 			E4_FUNCTION_TYPE(cmv->wFunction),
 			E4_FUNCTION_SUBTYPE(cmv->wFunction));
 			E4_FUNCTION_SUBTYPE(cmv->wFunction));

+ 78 - 16
drivers/usb/class/cdc-acm.c

@@ -496,10 +496,19 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 	   otherwise it is scheduled, and with high data rates data can get lost. */
 	   otherwise it is scheduled, and with high data rates data can get lost. */
 	tty->low_latency = 1;
 	tty->low_latency = 1;
 
 
+	if (usb_autopm_get_interface(acm->control)) {
+		mutex_unlock(&open_mutex);
+		return -EIO;
+	}
+
+	mutex_lock(&acm->mutex);
+	mutex_unlock(&open_mutex);
 	if (acm->used++) {
 	if (acm->used++) {
+		usb_autopm_put_interface(acm->control);
 		goto done;
 		goto done;
         }
         }
 
 
+
 	acm->ctrlurb->dev = acm->dev;
 	acm->ctrlurb->dev = acm->dev;
 	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
 	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
 		dbg("usb_submit_urb(ctrl irq) failed");
 		dbg("usb_submit_urb(ctrl irq) failed");
@@ -526,14 +535,15 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 
 
 done:
 done:
 err_out:
 err_out:
-	mutex_unlock(&open_mutex);
+	mutex_unlock(&acm->mutex);
 	return rv;
 	return rv;
 
 
 full_bailout:
 full_bailout:
 	usb_kill_urb(acm->ctrlurb);
 	usb_kill_urb(acm->ctrlurb);
 bail_out:
 bail_out:
+	usb_autopm_put_interface(acm->control);
 	acm->used--;
 	acm->used--;
-	mutex_unlock(&open_mutex);
+	mutex_unlock(&acm->mutex);
 	return -EIO;
 	return -EIO;
 }
 }
 
 
@@ -570,6 +580,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 			usb_kill_urb(acm->writeurb);
 			usb_kill_urb(acm->writeurb);
 			for (i = 0; i < nr; i++)
 			for (i = 0; i < nr; i++)
 				usb_kill_urb(acm->ru[i].urb);
 				usb_kill_urb(acm->ru[i].urb);
+			usb_autopm_put_interface(acm->control);
 		} else
 		} else
 			acm_tty_unregister(acm);
 			acm_tty_unregister(acm);
 	}
 	}
@@ -904,7 +915,7 @@ next_desc:
 	}
 	}
 	
 	
 	if (data_interface_num != call_interface_num)
 	if (data_interface_num != call_interface_num)
-		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");
+		dev_dbg(&intf->dev,"Separate call control interface. That is not fully supported.\n");
 
 
 skip_normal_probe:
 skip_normal_probe:
 
 
@@ -980,6 +991,7 @@ skip_normal_probe:
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
 	spin_lock_init(&acm->write_lock);
 	spin_lock_init(&acm->read_lock);
 	spin_lock_init(&acm->read_lock);
+	mutex_init(&acm->mutex);
 	acm->write_ready = 1;
 	acm->write_ready = 1;
 	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
 
 
@@ -1096,6 +1108,25 @@ alloc_fail:
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
 
 
+static void stop_data_traffic(struct acm *acm)
+{
+	int i;
+
+	tasklet_disable(&acm->urb_task);
+
+	usb_kill_urb(acm->ctrlurb);
+	usb_kill_urb(acm->writeurb);
+	for (i = 0; i < acm->rx_buflimit; i++)
+		usb_kill_urb(acm->ru[i].urb);
+
+	INIT_LIST_HEAD(&acm->filled_read_bufs);
+	INIT_LIST_HEAD(&acm->spare_read_bufs);
+
+	tasklet_enable(&acm->urb_task);
+
+	cancel_work_sync(&acm->work);
+}
+
 static void acm_disconnect(struct usb_interface *intf)
 static void acm_disconnect(struct usb_interface *intf)
 {
 {
 	struct acm *acm = usb_get_intfdata(intf);
 	struct acm *acm = usb_get_intfdata(intf);
@@ -1123,19 +1154,7 @@ static void acm_disconnect(struct usb_interface *intf)
 	usb_set_intfdata(acm->control, NULL);
 	usb_set_intfdata(acm->control, NULL);
 	usb_set_intfdata(acm->data, NULL);
 	usb_set_intfdata(acm->data, NULL);
 
 
-	tasklet_disable(&acm->urb_task);
-
-	usb_kill_urb(acm->ctrlurb);
-	usb_kill_urb(acm->writeurb);
-	for (i = 0; i < acm->rx_buflimit; i++)
-		usb_kill_urb(acm->ru[i].urb);
-
-	INIT_LIST_HEAD(&acm->filled_read_bufs);
-	INIT_LIST_HEAD(&acm->spare_read_bufs);
-
-	tasklet_enable(&acm->urb_task);
-
-	flush_scheduled_work(); /* wait for acm_softint */
+	stop_data_traffic(acm);
 
 
 	acm_write_buffers_free(acm);
 	acm_write_buffers_free(acm);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
@@ -1156,6 +1175,46 @@ static void acm_disconnect(struct usb_interface *intf)
 		tty_hangup(acm->tty);
 		tty_hangup(acm->tty);
 }
 }
 
 
+static int acm_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct acm *acm = usb_get_intfdata(intf);
+
+	if (acm->susp_count++)
+		return 0;
+	/*
+	we treat opened interfaces differently,
+	we must guard against open
+	*/
+	mutex_lock(&acm->mutex);
+
+	if (acm->used)
+		stop_data_traffic(acm);
+
+	mutex_unlock(&acm->mutex);
+	return 0;
+}
+
+static int acm_resume(struct usb_interface *intf)
+{
+	struct acm *acm = usb_get_intfdata(intf);
+	int rv = 0;
+
+	if (--acm->susp_count)
+		return 0;
+
+	mutex_lock(&acm->mutex);
+	if (acm->used) {
+		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+		if (rv < 0)
+		goto err_out;
+
+		tasklet_schedule(&acm->urb_task);
+	}
+
+err_out:
+	mutex_unlock(&acm->mutex);
+	return rv;
+}
 /*
 /*
  * USB driver structure.
  * USB driver structure.
  */
  */
@@ -1208,7 +1267,10 @@ static struct usb_driver acm_driver = {
 	.name =		"cdc_acm",
 	.name =		"cdc_acm",
 	.probe =	acm_probe,
 	.probe =	acm_probe,
 	.disconnect =	acm_disconnect,
 	.disconnect =	acm_disconnect,
+	.suspend =	acm_suspend,
+	.resume =	acm_resume,
 	.id_table =	acm_ids,
 	.id_table =	acm_ids,
+	.supports_autosuspend = 1,
 };
 };
 
 
 /*
 /*

+ 2 - 0
drivers/usb/class/cdc-acm.h

@@ -107,6 +107,7 @@ struct acm {
 	int write_used;					/* number of non-empty write buffers */
 	int write_used;					/* number of non-empty write buffers */
 	int write_ready;				/* write urb is not running */
 	int write_ready;				/* write urb is not running */
 	spinlock_t write_lock;
 	spinlock_t write_lock;
+	struct mutex mutex;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
 	struct tasklet_struct urb_task;                 /* rx processing */
 	struct tasklet_struct urb_task;                 /* rx processing */
@@ -120,6 +121,7 @@ struct acm {
 	unsigned char throttle;				/* throttled by tty layer */
 	unsigned char throttle;				/* throttled by tty layer */
 	unsigned char clocal;				/* termios CLOCAL */
 	unsigned char clocal;				/* termios CLOCAL */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
+	unsigned int susp_count;			/* number of suspended interfaces */
 };
 };
 
 
 #define CDC_DATA_INTERFACE_TYPE	0x0a
 #define CDC_DATA_INTERFACE_TYPE	0x0a

+ 15 - 0
drivers/usb/core/Kconfig

@@ -9,6 +9,21 @@ config USB_DEBUG
 	  of debug messages to the system log. Select this if you are having a
 	  of debug messages to the system log. Select this if you are having a
 	  problem with USB support and want to see more of what is going on.
 	  problem with USB support and want to see more of what is going on.
 
 
+config USB_ANNOUNCE_NEW_DEVICES
+	bool "USB announce new devices"
+	depends on USB
+	default N
+	help
+	  Say Y here if you want the USB core to always announce the
+	  idVendor, idProduct, Manufacturer, Product, and SerialNumber
+	  strings for every new USB device to the syslog.  This option is
+	  usually used by distro vendors to help with debugging and to
+	  let users know what specific device was added to the machine
+	  in what location.
+
+	  If you do not want this kind of information sent to the system
+	  log, or have any doubts about this, say N here.
+
 comment "Miscellaneous USB options"
 comment "Miscellaneous USB options"
 	depends on USB
 	depends on USB
 
 

+ 12 - 8
drivers/usb/core/buffer.c

@@ -53,11 +53,13 @@ int hcd_buffer_create(struct usb_hcd *hcd)
 	char		name[16];
 	char		name[16];
 	int 		i, size;
 	int 		i, size;
 
 
-	if (!hcd->self.controller->dma_mask)
+	if (!hcd->self.controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM))
 		return 0;
 		return 0;
 
 
-	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
-		if (!(size = pool_max [i]))
+	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+		size = pool_max[i];
+		if (!size)
 			continue;
 			continue;
 		snprintf(name, sizeof name, "buffer-%d", size);
 		snprintf(name, sizeof name, "buffer-%d", size);
 		hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
 		hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
@@ -80,10 +82,10 @@ int hcd_buffer_create(struct usb_hcd *hcd)
  */
  */
 void hcd_buffer_destroy(struct usb_hcd *hcd)
 void hcd_buffer_destroy(struct usb_hcd *hcd)
 {
 {
-	int		i;
+	int i;
 
 
-	for (i = 0; i < HCD_BUFFER_POOLS; i++) { 
-		struct dma_pool		*pool = hcd->pool[i];
+	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+		struct dma_pool *pool = hcd->pool[i];
 		if (pool) {
 		if (pool) {
 			dma_pool_destroy(pool);
 			dma_pool_destroy(pool);
 			hcd->pool[i] = NULL;
 			hcd->pool[i] = NULL;
@@ -107,7 +109,8 @@ void *hcd_buffer_alloc(
 	int 			i;
 	int 			i;
 
 
 	/* some USB hosts just use PIO */
 	/* some USB hosts just use PIO */
-	if (!bus->controller->dma_mask) {
+	if (!bus->controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 		*dma = ~(dma_addr_t) 0;
 		*dma = ~(dma_addr_t) 0;
 		return kmalloc(size, mem_flags);
 		return kmalloc(size, mem_flags);
 	}
 	}
@@ -132,7 +135,8 @@ void hcd_buffer_free(
 	if (!addr)
 	if (!addr)
 		return;
 		return;
 
 
-	if (!bus->controller->dma_mask) {
+	if (!bus->controller->dma_mask &&
+	    !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 		kfree(addr);
 		kfree(addr);
 		return;
 		return;
 	}
 	}

+ 8 - 6
drivers/usb/core/config.c

@@ -238,7 +238,7 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
 
 
 	/* Allocate space for the right(?) number of endpoints */
 	/* Allocate space for the right(?) number of endpoints */
 	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
 	num_ep = num_ep_orig = alt->desc.bNumEndpoints;
-	alt->desc.bNumEndpoints = 0;		// Use as a counter
+	alt->desc.bNumEndpoints = 0;		/* Use as a counter */
 	if (num_ep > USB_MAXENDPOINTS) {
 	if (num_ep > USB_MAXENDPOINTS) {
 		dev_warn(ddev, "too many endpoints for config %d interface %d "
 		dev_warn(ddev, "too many endpoints for config %d interface %d "
 		    "altsetting %d: %d, using maximum allowed: %d\n",
 		    "altsetting %d: %d, using maximum allowed: %d\n",
@@ -246,7 +246,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
 		num_ep = USB_MAXENDPOINTS;
 		num_ep = USB_MAXENDPOINTS;
 	}
 	}
 
 
-	if (num_ep > 0) {	/* Can't allocate 0 bytes */
+	if (num_ep > 0) {
+		/* Can't allocate 0 bytes */
 		len = sizeof(struct usb_host_endpoint) * num_ep;
 		len = sizeof(struct usb_host_endpoint) * num_ep;
 		alt->endpoint = kzalloc(len, GFP_KERNEL);
 		alt->endpoint = kzalloc(len, GFP_KERNEL);
 		if (!alt->endpoint)
 		if (!alt->endpoint)
@@ -475,8 +476,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
 	return 0;
 	return 0;
 }
 }
 
 
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally on disconnect/destroy path
+/* hub-only!! ... and only exported for reset/reinit path.
+ * otherwise used internally on disconnect/destroy path
+ */
 void usb_destroy_configuration(struct usb_device *dev)
 void usb_destroy_configuration(struct usb_device *dev)
 {
 {
 	int c, i;
 	int c, i;
@@ -498,7 +500,7 @@ void usb_destroy_configuration(struct usb_device *dev)
 		kfree(cf->string);
 		kfree(cf->string);
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
 			if (cf->intf_cache[i])
-				kref_put(&cf->intf_cache[i]->ref, 
+				kref_put(&cf->intf_cache[i]->ref,
 					  usb_release_interface_cache);
 					  usb_release_interface_cache);
 		}
 		}
 	}
 	}
@@ -525,7 +527,7 @@ int usb_get_configuration(struct usb_device *dev)
 	unsigned int cfgno, length;
 	unsigned int cfgno, length;
 	unsigned char *buffer;
 	unsigned char *buffer;
 	unsigned char *bigbuffer;
 	unsigned char *bigbuffer;
- 	struct usb_config_descriptor *desc;
+	struct usb_config_descriptor *desc;
 
 
 	cfgno = 0;
 	cfgno = 0;
 	if (dev->authorized == 0)	/* Not really an error */
 	if (dev->authorized == 0)	/* Not really an error */

+ 82 - 72
drivers/usb/core/devices.c

@@ -89,7 +89,7 @@ static const char *format_string_serialnumber =
 static const char *format_bandwidth =
 static const char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
   "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
   "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-  
+
 static const char *format_device1 =
 static const char *format_device1 =
 /* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
 /* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
   "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
   "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
@@ -101,7 +101,7 @@ static const char *format_device2 =
 static const char *format_config =
 static const char *format_config =
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
 /* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
   "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-  
+
 static const char *format_iad =
 static const char *format_iad =
 /* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
 /* A:  FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
   "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
   "A:  FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
@@ -122,7 +122,7 @@ static const char *format_endpt =
  */
  */
 
 
 static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
 static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt = 0;
+static unsigned int conndiscevcnt;
 
 
 /* this struct stores the poll state for <mountpoint>/devices pollers */
 /* this struct stores the poll state for <mountpoint>/devices pollers */
 struct usb_device_status {
 struct usb_device_status {
@@ -172,12 +172,8 @@ static const char *class_decode(const int class)
 	return clas_info[ix].class_name;
 	return clas_info[ix].class_name;
 }
 }
 
 
-static char *usb_dump_endpoint_descriptor(
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_endpoint_descriptor *desc
-)
+static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
+				const struct usb_endpoint_descriptor *desc)
 {
 {
 	char dir, unit, *type;
 	char dir, unit, *type;
 	unsigned interval, bandwidth = 1;
 	unsigned interval, bandwidth = 1;
@@ -235,22 +231,24 @@ static char *usb_dump_endpoint_descriptor(
 
 
 	start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
 	start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
 			 desc->bmAttributes, type,
 			 desc->bmAttributes, type,
-			 (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * bandwidth,
+			 (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) *
+			 bandwidth,
 			 interval, unit);
 			 interval, unit);
 	return start;
 	return start;
 }
 }
 
 
 static char *usb_dump_interface_descriptor(char *start, char *end,
 static char *usb_dump_interface_descriptor(char *start, char *end,
-	const struct usb_interface_cache *intfc,
-	const struct usb_interface *iface,
-	int setno)
+					const struct usb_interface_cache *intfc,
+					const struct usb_interface *iface,
+					int setno)
 {
 {
-	const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc;
+	const struct usb_interface_descriptor *desc;
 	const char *driver_name = "";
 	const char *driver_name = "";
 	int active = 0;
 	int active = 0;
 
 
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
+	desc = &intfc->altsetting[setno].desc;
 	if (iface) {
 	if (iface) {
 		driver_name = (iface->dev.driver
 		driver_name = (iface->dev.driver
 				? iface->dev.driver->name
 				? iface->dev.driver->name
@@ -270,14 +268,10 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
 	return start;
 	return start;
 }
 }
 
 
-static char *usb_dump_interface(
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_interface_cache *intfc,
-	const struct usb_interface *iface,
-	int setno
-) {
+static char *usb_dump_interface(int speed, char *start, char *end,
+				const struct usb_interface_cache *intfc,
+				const struct usb_interface *iface, int setno)
+{
 	const struct usb_host_interface *desc = &intfc->altsetting[setno];
 	const struct usb_host_interface *desc = &intfc->altsetting[setno];
 	int i;
 	int i;
 
 
@@ -292,7 +286,7 @@ static char *usb_dump_interface(
 }
 }
 
 
 static char *usb_dump_iad_descriptor(char *start, char *end,
 static char *usb_dump_iad_descriptor(char *start, char *end,
-	const struct usb_interface_assoc_descriptor *iad)
+			const struct usb_interface_assoc_descriptor *iad)
 {
 {
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
@@ -311,13 +305,15 @@ static char *usb_dump_iad_descriptor(char *start, char *end,
  * 1. marking active interface altsettings (code lists all, but should mark
  * 1. marking active interface altsettings (code lists all, but should mark
  *    which ones are active, if any)
  *    which ones are active, if any)
  */
  */
-
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
+static char *usb_dump_config_descriptor(char *start, char *end,
+				const struct usb_config_descriptor *desc,
+				int active)
 {
 {
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
 	start += sprintf(start, format_config,
 	start += sprintf(start, format_config,
-			 active ? '*' : ' ',	/* mark active/actual/current cfg. */
+			 /* mark active/actual/current cfg. */
+			 active ? '*' : ' ',
 			 desc->bNumInterfaces,
 			 desc->bNumInterfaces,
 			 desc->bConfigurationValue,
 			 desc->bConfigurationValue,
 			 desc->bmAttributes,
 			 desc->bmAttributes,
@@ -325,13 +321,8 @@ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb
 	return start;
 	return start;
 }
 }
 
 
-static char *usb_dump_config (
-	int speed,
-	char *start,
-	char *end,
-	const struct usb_host_config *config,
-	int active
-)
+static char *usb_dump_config(int speed, char *start, char *end,
+			     const struct usb_host_config *config, int active)
 {
 {
 	int i, j;
 	int i, j;
 	struct usb_interface_cache *intfc;
 	struct usb_interface_cache *intfc;
@@ -339,7 +330,8 @@ static char *usb_dump_config (
 
 
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
-	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
+	if (!config)
+		/* getting these some in 2.3.7; none in 2.3.6 */
 		return start + sprintf(start, "(null Cfg. desc.)\n");
 		return start + sprintf(start, "(null Cfg. desc.)\n");
 	start = usb_dump_config_descriptor(start, end, &config->desc, active);
 	start = usb_dump_config_descriptor(start, end, &config->desc, active);
 	for (i = 0; i < USB_MAXIADS; i++) {
 	for (i = 0; i < USB_MAXIADS; i++) {
@@ -364,7 +356,8 @@ static char *usb_dump_config (
 /*
 /*
  * Dump the different USB descriptors.
  * Dump the different USB descriptors.
  */
  */
-static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
+static char *usb_dump_device_descriptor(char *start, char *end,
+				const struct usb_device_descriptor *desc)
 {
 {
 	u16 bcdUSB = le16_to_cpu(desc->bcdUSB);
 	u16 bcdUSB = le16_to_cpu(desc->bcdUSB);
 	u16 bcdDevice = le16_to_cpu(desc->bcdDevice);
 	u16 bcdDevice = le16_to_cpu(desc->bcdDevice);
@@ -374,7 +367,7 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb
 	start += sprintf(start, format_device1,
 	start += sprintf(start, format_device1,
 			  bcdUSB >> 8, bcdUSB & 0xff,
 			  bcdUSB >> 8, bcdUSB & 0xff,
 			  desc->bDeviceClass,
 			  desc->bDeviceClass,
-			  class_decode (desc->bDeviceClass),
+			  class_decode(desc->bDeviceClass),
 			  desc->bDeviceSubClass,
 			  desc->bDeviceSubClass,
 			  desc->bDeviceProtocol,
 			  desc->bDeviceProtocol,
 			  desc->bMaxPacketSize0,
 			  desc->bMaxPacketSize0,
@@ -391,12 +384,14 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb
 /*
 /*
  * Dump the different strings that this device holds.
  * Dump the different strings that this device holds.
  */
  */
-static char *usb_dump_device_strings(char *start, char *end, struct usb_device *dev)
+static char *usb_dump_device_strings(char *start, char *end,
+				     struct usb_device *dev)
 {
 {
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
 	if (dev->manufacturer)
 	if (dev->manufacturer)
-		start += sprintf(start, format_string_manufacturer, dev->manufacturer);
+		start += sprintf(start, format_string_manufacturer,
+				 dev->manufacturer);
 	if (start > end)
 	if (start > end)
 		goto out;
 		goto out;
 	if (dev->product)
 	if (dev->product)
@@ -405,7 +400,8 @@ static char *usb_dump_device_strings(char *start, char *end, struct usb_device *
 		goto out;
 		goto out;
 #ifdef ALLOW_SERIAL_NUMBER
 #ifdef ALLOW_SERIAL_NUMBER
 	if (dev->serial)
 	if (dev->serial)
-		start += sprintf(start, format_string_serialnumber, dev->serial);
+		start += sprintf(start, format_string_serialnumber,
+				 dev->serial);
 #endif
 #endif
  out:
  out:
 	return start;
 	return start;
@@ -417,12 +413,12 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
 
 
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
-		
+
 	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
 	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
 
 
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
-	
+
 	start = usb_dump_device_strings(start, end, dev);
 	start = usb_dump_device_strings(start, end, dev);
 
 
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
@@ -439,7 +435,8 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
 
 
 #ifdef PROC_EXTRA /* TBD: may want to add this code later */
 #ifdef PROC_EXTRA /* TBD: may want to add this code later */
 
 
-static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
+static char *usb_dump_hub_descriptor(char *start, char *end,
+				     const struct usb_hub_descriptor *desc)
 {
 {
 	int leng = USB_DT_HUB_NONVAR_SIZE;
 	int leng = USB_DT_HUB_NONVAR_SIZE;
 	unsigned char *ptr = (unsigned char *)desc;
 	unsigned char *ptr = (unsigned char *)desc;
@@ -455,13 +452,16 @@ static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hu
 	return start;
 	return start;
 }
 }
 
 
-static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
+static char *usb_dump_string(char *start, char *end,
+			     const struct usb_device *dev, char *id, int index)
 {
 {
 	if (start > end)
 	if (start > end)
 		return start;
 		return start;
 	start += sprintf(start, "Interface:");
 	start += sprintf(start, "Interface:");
-	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
-		start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
+	if (index <= dev->maxstring && dev->stringindex &&
+	    dev->stringindex[index])
+		start += sprintf(start, "%s: %.100s ", id,
+				 dev->stringindex[index]);
 	return start;
 	return start;
 }
 }
 
 
@@ -476,8 +476,10 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de
  * file_offset - the offset into the devices file on completion
  * file_offset - the offset into the devices file on completion
  * The caller must own the device lock.
  * The caller must own the device lock.
  */
  */
-static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
-				struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
+static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
+			       loff_t *skip_bytes, loff_t *file_offset,
+			       struct usb_device *usbdev, struct usb_bus *bus,
+			       int level, int index, int count)
 {
 {
 	int chix;
 	int chix;
 	int ret, cnt = 0;
 	int ret, cnt = 0;
@@ -485,17 +487,19 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
 	char *pages_start, *data_end, *speed;
 	char *pages_start, *data_end, *speed;
 	unsigned int length;
 	unsigned int length;
 	ssize_t total_written = 0;
 	ssize_t total_written = 0;
-	
+
 	/* don't bother with anything else if we're not writing any data */
 	/* don't bother with anything else if we're not writing any data */
 	if (*nbytes <= 0)
 	if (*nbytes <= 0)
 		return 0;
 		return 0;
-	
+
 	if (level > MAX_TOPO_LEVEL)
 	if (level > MAX_TOPO_LEVEL)
 		return 0;
 		return 0;
-	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
-        if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
-                return -ENOMEM;
-		
+	/* allocate 2^1 pages = 8K (on i386);
+	 * should be more than enough for one device */
+	pages_start = (char *)__get_free_pages(GFP_KERNEL, 1);
+	if (!pages_start)
+		return -ENOMEM;
+
 	if (usbdev->parent && usbdev->parent->devnum != -1)
 	if (usbdev->parent && usbdev->parent->devnum != -1)
 		parent_devnum = usbdev->parent->devnum;
 		parent_devnum = usbdev->parent->devnum;
 	/*
 	/*
@@ -541,15 +545,16 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
 				bus->bandwidth_allocated, max,
 				bus->bandwidth_allocated, max,
 				(100 * bus->bandwidth_allocated + max / 2)
 				(100 * bus->bandwidth_allocated + max / 2)
 					/ max,
 					/ max,
-			         bus->bandwidth_int_reqs,
-				 bus->bandwidth_isoc_reqs);
-	
+				bus->bandwidth_int_reqs,
+				bus->bandwidth_isoc_reqs);
+
 	}
 	}
-	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
-	
+	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256,
+				 usbdev);
+
 	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
 	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
 		data_end += sprintf(data_end, "(truncated)\n");
 		data_end += sprintf(data_end, "(truncated)\n");
-	
+
 	length = data_end - pages_start;
 	length = data_end - pages_start;
 	/* if we can start copying some data to the user */
 	/* if we can start copying some data to the user */
 	if (length > *skip_bytes) {
 	if (length > *skip_bytes) {
@@ -567,17 +572,18 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
 		*skip_bytes = 0;
 		*skip_bytes = 0;
 	} else
 	} else
 		*skip_bytes -= length;
 		*skip_bytes -= length;
-	
+
 	free_pages((unsigned long)pages_start, 1);
 	free_pages((unsigned long)pages_start, 1);
-	
+
 	/* Now look at all of this device's children. */
 	/* Now look at all of this device's children. */
 	for (chix = 0; chix < usbdev->maxchild; chix++) {
 	for (chix = 0; chix < usbdev->maxchild; chix++) {
 		struct usb_device *childdev = usbdev->children[chix];
 		struct usb_device *childdev = usbdev->children[chix];
 
 
 		if (childdev) {
 		if (childdev) {
 			usb_lock_device(childdev);
 			usb_lock_device(childdev);
-			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
-					bus, level + 1, chix, ++cnt);
+			ret = usb_device_dump(buffer, nbytes, skip_bytes,
+					      file_offset, childdev, bus,
+					      level + 1, chix, ++cnt);
 			usb_unlock_device(childdev);
 			usb_unlock_device(childdev);
 			if (ret == -EFAULT)
 			if (ret == -EFAULT)
 				return total_written;
 				return total_written;
@@ -587,7 +593,8 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
 	return total_written;
 	return total_written;
 }
 }
 
 
-static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t usb_device_read(struct file *file, char __user *buf,
+			       size_t nbytes, loff_t *ppos)
 {
 {
 	struct usb_bus *bus;
 	struct usb_bus *bus;
 	ssize_t ret, total_written = 0;
 	ssize_t ret, total_written = 0;
@@ -607,7 +614,8 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
 		if (!bus->root_hub)
 		if (!bus->root_hub)
 			continue;
 			continue;
 		usb_lock_device(bus->root_hub);
 		usb_lock_device(bus->root_hub);
-		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
+				      bus->root_hub, bus, 0, 0, 0);
 		usb_unlock_device(bus->root_hub);
 		usb_unlock_device(bus->root_hub);
 		if (ret < 0) {
 		if (ret < 0) {
 			mutex_unlock(&usb_bus_list_lock);
 			mutex_unlock(&usb_bus_list_lock);
@@ -620,7 +628,8 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
 }
 }
 
 
 /* Kernel lock for "lastev" protection */
 /* Kernel lock for "lastev" protection */
-static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int usb_device_poll(struct file *file,
+				    struct poll_table_struct *wait)
 {
 {
 	struct usb_device_status *st = file->private_data;
 	struct usb_device_status *st = file->private_data;
 	unsigned int mask = 0;
 	unsigned int mask = 0;
@@ -629,7 +638,8 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
 	if (!st) {
 	if (!st) {
 		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
 		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
 
 
-		/* we may have dropped BKL - need to check for having lost the race */
+		/* we may have dropped BKL -
+		 * need to check for having lost the race */
 		if (file->private_data) {
 		if (file->private_data) {
 			kfree(st);
 			kfree(st);
 			st = file->private_data;
 			st = file->private_data;
@@ -652,7 +662,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
 	}
 	}
 lost_race:
 lost_race:
 	if (file->f_mode & FMODE_READ)
 	if (file->f_mode & FMODE_READ)
-                poll_wait(file, &deviceconndiscwq, wait);
+		poll_wait(file, &deviceconndiscwq, wait);
 	if (st->lastev != conndiscevcnt)
 	if (st->lastev != conndiscevcnt)
 		mask |= POLLIN;
 		mask |= POLLIN;
 	st->lastev = conndiscevcnt;
 	st->lastev = conndiscevcnt;
@@ -662,18 +672,18 @@ lost_race:
 
 
 static int usb_device_open(struct inode *inode, struct file *file)
 static int usb_device_open(struct inode *inode, struct file *file)
 {
 {
-        file->private_data = NULL;
-        return 0;
+	file->private_data = NULL;
+	return 0;
 }
 }
 
 
 static int usb_device_release(struct inode *inode, struct file *file)
 static int usb_device_release(struct inode *inode, struct file *file)
 {
 {
 	kfree(file->private_data);
 	kfree(file->private_data);
 	file->private_data = NULL;
 	file->private_data = NULL;
-        return 0;
+	return 0;
 }
 }
 
 
-static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
+static loff_t usb_device_lseek(struct file *file, loff_t offset, int orig)
 {
 {
 	loff_t ret;
 	loff_t ret;
 
 

+ 209 - 150
drivers/usb/core/devio.c

@@ -75,14 +75,14 @@ struct async {
 	u32 secid;
 	u32 secid;
 };
 };
 
 
-static int usbfs_snoop = 0;
-module_param (usbfs_snoop, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
+static int usbfs_snoop;
+module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
 
 
 #define snoop(dev, format, arg...)				\
 #define snoop(dev, format, arg...)				\
 	do {							\
 	do {							\
 		if (usbfs_snoop)				\
 		if (usbfs_snoop)				\
-			dev_info( dev , format , ## arg);	\
+			dev_info(dev , format , ## arg);	\
 	} while (0)
 	} while (0)
 
 
 #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
 #define USB_DEVICE_DEV		MKDEV(USB_DEVICE_MAJOR, 0)
@@ -90,7 +90,7 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
 
 
 #define	MAX_USBFS_BUFFER_SIZE	16384
 #define	MAX_USBFS_BUFFER_SIZE	16384
 
 
-static inline int connected (struct dev_state *ps)
+static inline int connected(struct dev_state *ps)
 {
 {
 	return (!list_empty(&ps->list) &&
 	return (!list_empty(&ps->list) &&
 			ps->dev->state != USB_STATE_NOTATTACHED);
 			ps->dev->state != USB_STATE_NOTATTACHED);
@@ -120,7 +120,8 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
 	return ret;
 	return ret;
 }
 }
 
 
-static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes,
+			   loff_t *ppos)
 {
 {
 	struct dev_state *ps = file->private_data;
 	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	struct usb_device *dev = ps->dev;
@@ -140,7 +141,8 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
 	}
 	}
 
 
 	if (pos < sizeof(struct usb_device_descriptor)) {
 	if (pos < sizeof(struct usb_device_descriptor)) {
-		struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */
+		/* 18 bytes - fits on the stack */
+		struct usb_device_descriptor temp_desc;
 
 
 		memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor));
 		memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor));
 		le16_to_cpus(&temp_desc.bcdUSB);
 		le16_to_cpus(&temp_desc.bcdUSB);
@@ -210,17 +212,17 @@ err:
 
 
 static struct async *alloc_async(unsigned int numisoframes)
 static struct async *alloc_async(unsigned int numisoframes)
 {
 {
-        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kzalloc(assize, GFP_KERNEL);
+	struct async *as;
 
 
-        if (!as)
-                return NULL;
+	as = kzalloc(sizeof(struct async), GFP_KERNEL);
+	if (!as)
+		return NULL;
 	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
 	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
 	if (!as->urb) {
 	if (!as->urb) {
 		kfree(as);
 		kfree(as);
 		return NULL;
 		return NULL;
 	}
 	}
-        return as;
+	return as;
 }
 }
 
 
 static void free_async(struct async *as)
 static void free_async(struct async *as)
@@ -234,52 +236,54 @@ static void free_async(struct async *as)
 
 
 static inline void async_newpending(struct async *as)
 static inline void async_newpending(struct async *as)
 {
 {
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_add_tail(&as->asynclist, &ps->async_pending);
-        spin_unlock_irqrestore(&ps->lock, flags);
+	struct dev_state *ps = as->ps;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ps->lock, flags);
+	list_add_tail(&as->asynclist, &ps->async_pending);
+	spin_unlock_irqrestore(&ps->lock, flags);
 }
 }
 
 
 static inline void async_removepending(struct async *as)
 static inline void async_removepending(struct async *as)
 {
 {
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_del_init(&as->asynclist);
-        spin_unlock_irqrestore(&ps->lock, flags);
+	struct dev_state *ps = as->ps;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ps->lock, flags);
+	list_del_init(&as->asynclist);
+	spin_unlock_irqrestore(&ps->lock, flags);
 }
 }
 
 
 static inline struct async *async_getcompleted(struct dev_state *ps)
 static inline struct async *async_getcompleted(struct dev_state *ps)
 {
 {
-        unsigned long flags;
-        struct async *as = NULL;
-
-        spin_lock_irqsave(&ps->lock, flags);
-        if (!list_empty(&ps->async_completed)) {
-                as = list_entry(ps->async_completed.next, struct async, asynclist);
-                list_del_init(&as->asynclist);
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return as;
+	unsigned long flags;
+	struct async *as = NULL;
+
+	spin_lock_irqsave(&ps->lock, flags);
+	if (!list_empty(&ps->async_completed)) {
+		as = list_entry(ps->async_completed.next, struct async,
+				asynclist);
+		list_del_init(&as->asynclist);
+	}
+	spin_unlock_irqrestore(&ps->lock, flags);
+	return as;
 }
 }
 
 
-static inline struct async *async_getpending(struct dev_state *ps, void __user *userurb)
+static inline struct async *async_getpending(struct dev_state *ps,
+					     void __user *userurb)
 {
 {
-        unsigned long flags;
-        struct async *as;
+	unsigned long flags;
+	struct async *as;
 
 
-        spin_lock_irqsave(&ps->lock, flags);
+	spin_lock_irqsave(&ps->lock, flags);
 	list_for_each_entry(as, &ps->async_pending, asynclist)
 	list_for_each_entry(as, &ps->async_pending, asynclist)
 		if (as->userurb == userurb) {
 		if (as->userurb == userurb) {
 			list_del_init(&as->asynclist);
 			list_del_init(&as->asynclist);
 			spin_unlock_irqrestore(&ps->lock, flags);
 			spin_unlock_irqrestore(&ps->lock, flags);
 			return as;
 			return as;
 		}
 		}
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return NULL;
+	spin_unlock_irqrestore(&ps->lock, flags);
+	return NULL;
 }
 }
 
 
 static void snoop_urb(struct urb *urb, void __user *userurb)
 static void snoop_urb(struct urb *urb, void __user *userurb)
@@ -298,19 +302,19 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
 	dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
 	dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
 	dev_info(&urb->dev->dev, "data: ");
 	dev_info(&urb->dev->dev, "data: ");
 	for (j = 0; j < urb->transfer_buffer_length; ++j)
 	for (j = 0; j < urb->transfer_buffer_length; ++j)
-		printk ("%02x ", data[j]);
+		printk("%02x ", data[j]);
 	printk("\n");
 	printk("\n");
 }
 }
 
 
 static void async_completed(struct urb *urb)
 static void async_completed(struct urb *urb)
 {
 {
-        struct async *as = urb->context;
-        struct dev_state *ps = as->ps;
+	struct async *as = urb->context;
+	struct dev_state *ps = as->ps;
 	struct siginfo sinfo;
 	struct siginfo sinfo;
 
 
-        spin_lock(&ps->lock);
-        list_move_tail(&as->asynclist, &ps->async_completed);
-        spin_unlock(&ps->lock);
+	spin_lock(&ps->lock);
+	list_move_tail(&as->asynclist, &ps->async_completed);
+	spin_unlock(&ps->lock);
 	as->status = urb->status;
 	as->status = urb->status;
 	if (as->signr) {
 	if (as->signr) {
 		sinfo.si_signo = as->signr;
 		sinfo.si_signo = as->signr;
@@ -325,7 +329,7 @@ static void async_completed(struct urb *urb)
 	wake_up(&ps->wait);
 	wake_up(&ps->wait);
 }
 }
 
 
-static void destroy_async (struct dev_state *ps, struct list_head *list)
+static void destroy_async(struct dev_state *ps, struct list_head *list)
 {
 {
 	struct async *as;
 	struct async *as;
 	unsigned long flags;
 	unsigned long flags;
@@ -348,7 +352,8 @@ static void destroy_async (struct dev_state *ps, struct list_head *list)
 	}
 	}
 }
 }
 
 
-static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum)
+static void destroy_async_on_interface(struct dev_state *ps,
+				       unsigned int ifnum)
 {
 {
 	struct list_head *p, *q, hitlist;
 	struct list_head *p, *q, hitlist;
 	unsigned long flags;
 	unsigned long flags;
@@ -364,7 +369,7 @@ static void destroy_async_on_interface (struct dev_state *ps, unsigned int ifnum
 
 
 static inline void destroy_all_async(struct dev_state *ps)
 static inline void destroy_all_async(struct dev_state *ps)
 {
 {
-	        destroy_async(ps, &ps->async_pending);
+	destroy_async(ps, &ps->async_pending);
 }
 }
 
 
 /*
 /*
@@ -373,15 +378,15 @@ static inline void destroy_all_async(struct dev_state *ps)
  * they're also undone when devices disconnect.
  * they're also undone when devices disconnect.
  */
  */
 
 
-static int driver_probe (struct usb_interface *intf,
-			 const struct usb_device_id *id)
+static int driver_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
 {
 {
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
 static void driver_disconnect(struct usb_interface *intf)
 static void driver_disconnect(struct usb_interface *intf)
 {
 {
-	struct dev_state *ps = usb_get_intfdata (intf);
+	struct dev_state *ps = usb_get_intfdata(intf);
 	unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber;
 	unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber;
 
 
 	if (!ps)
 	if (!ps)
@@ -396,16 +401,31 @@ static void driver_disconnect(struct usb_interface *intf)
 	else
 	else
 		warn("interface number %u out of range", ifnum);
 		warn("interface number %u out of range", ifnum);
 
 
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 
 
 	/* force async requests to complete */
 	/* force async requests to complete */
 	destroy_async_on_interface(ps, ifnum);
 	destroy_async_on_interface(ps, ifnum);
 }
 }
 
 
+/* The following routines are merely placeholders.  There is no way
+ * to inform a user task about suspend or resumes.
+ */
+static int driver_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+	return 0;
+}
+
+static int driver_resume(struct usb_interface *intf)
+{
+	return 0;
+}
+
 struct usb_driver usbfs_driver = {
 struct usb_driver usbfs_driver = {
 	.name =		"usbfs",
 	.name =		"usbfs",
 	.probe =	driver_probe,
 	.probe =	driver_probe,
 	.disconnect =	driver_disconnect,
 	.disconnect =	driver_disconnect,
+	.suspend =	driver_suspend,
+	.resume =	driver_resume,
 };
 };
 
 
 static int claimintf(struct dev_state *ps, unsigned int ifnum)
 static int claimintf(struct dev_state *ps, unsigned int ifnum)
@@ -459,15 +479,16 @@ static int checkintf(struct dev_state *ps, unsigned int ifnum)
 	if (test_bit(ifnum, &ps->ifclaimed))
 	if (test_bit(ifnum, &ps->ifclaimed))
 		return 0;
 		return 0;
 	/* if not yet claimed, claim it for the driver */
 	/* if not yet claimed, claim it for the driver */
-	dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim interface %u before use\n",
-	       task_pid_nr(current), current->comm, ifnum);
+	dev_warn(&ps->dev->dev, "usbfs: process %d (%s) did not claim "
+		 "interface %u before use\n", task_pid_nr(current),
+		 current->comm, ifnum);
 	return claimintf(ps, ifnum);
 	return claimintf(ps, ifnum);
 }
 }
 
 
 static int findintfep(struct usb_device *dev, unsigned int ep)
 static int findintfep(struct usb_device *dev, unsigned int ep)
 {
 {
 	unsigned int i, j, e;
 	unsigned int i, j, e;
-        struct usb_interface *intf;
+	struct usb_interface *intf;
 	struct usb_host_interface *alts;
 	struct usb_host_interface *alts;
 	struct usb_endpoint_descriptor *endpt;
 	struct usb_endpoint_descriptor *endpt;
 
 
@@ -478,7 +499,7 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
 	for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 	for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 		intf = dev->actconfig->interface[i];
 		intf = dev->actconfig->interface[i];
 		for (j = 0; j < intf->num_altsetting; j++) {
 		for (j = 0; j < intf->num_altsetting; j++) {
-                        alts = &intf->altsetting[j];
+			alts = &intf->altsetting[j];
 			for (e = 0; e < alts->desc.bNumEndpoints; e++) {
 			for (e = 0; e < alts->desc.bNumEndpoints; e++) {
 				endpt = &alts->endpoint[e].desc;
 				endpt = &alts->endpoint[e].desc;
 				if (endpt->bEndpointAddress == ep)
 				if (endpt->bEndpointAddress == ep)
@@ -486,10 +507,11 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
 			}
 			}
 		}
 		}
 	}
 	}
-	return -ENOENT; 
+	return -ENOENT;
 }
 }
 
 
-static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
+static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
+			   unsigned int index)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
@@ -502,7 +524,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
 	index &= 0xff;
 	index &= 0xff;
 	switch (requesttype & USB_RECIP_MASK) {
 	switch (requesttype & USB_RECIP_MASK) {
 	case USB_RECIP_ENDPOINT:
 	case USB_RECIP_ENDPOINT:
-		if ((ret = findintfep(ps->dev, index)) >= 0)
+		ret = findintfep(ps->dev, index);
+		if (ret >= 0)
 			ret = checkintf(ps, ret);
 			ret = checkintf(ps, ret);
 		break;
 		break;
 
 
@@ -546,7 +569,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
 	mutex_lock(&usbfs_mutex);
 	mutex_lock(&usbfs_mutex);
 
 
 	ret = -ENOMEM;
 	ret = -ENOMEM;
-	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+	ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL);
+	if (!ps)
 		goto out;
 		goto out;
 
 
 	ret = -ENOENT;
 	ret = -ENOENT;
@@ -627,15 +651,18 @@ static int proc_control(struct dev_state *ps, void __user *arg)
 
 
 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 		return -EFAULT;
 		return -EFAULT;
-	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
+	ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+	if (ret)
 		return ret;
 		return ret;
 	if (ctrl.wLength > PAGE_SIZE)
 	if (ctrl.wLength > PAGE_SIZE)
 		return -EINVAL;
 		return -EINVAL;
-	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+	tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!tbuf)
 		return -ENOMEM;
 		return -ENOMEM;
 	tmo = ctrl.timeout;
 	tmo = ctrl.timeout;
 	if (ctrl.bRequestType & 0x80) {
 	if (ctrl.bRequestType & 0x80) {
-		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
+		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
+					       ctrl.wLength)) {
 			free_page((unsigned long)tbuf);
 			free_page((unsigned long)tbuf);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
@@ -646,14 +673,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
 				ctrl.wIndex, ctrl.wLength);
 				ctrl.wIndex, ctrl.wLength);
 
 
 		usb_unlock_device(dev);
 		usb_unlock_device(dev);
-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest,
+				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
 		usb_lock_device(dev);
 		if ((i > 0) && ctrl.wLength) {
 		if ((i > 0) && ctrl.wLength) {
 			if (usbfs_snoop) {
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
 				dev_info(&dev->dev, "control read: data ");
 				for (j = 0; j < i; ++j)
 				for (j = 0; j < i; ++j)
-					printk("%02x ", (unsigned char)(tbuf)[j]);
+					printk("%02x ", (u8)(tbuf)[j]);
 				printk("\n");
 				printk("\n");
 			}
 			}
 			if (copy_to_user(ctrl.data, tbuf, i)) {
 			if (copy_to_user(ctrl.data, tbuf, i)) {
@@ -680,12 +708,13 @@ static int proc_control(struct dev_state *ps, void __user *arg)
 			printk("\n");
 			printk("\n");
 		}
 		}
 		usb_unlock_device(dev);
 		usb_unlock_device(dev);
-		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
+				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
+				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
 		usb_lock_device(dev);
 	}
 	}
 	free_page((unsigned long)tbuf);
 	free_page((unsigned long)tbuf);
-	if (i<0 && i != -EPIPE) {
+	if (i < 0 && i != -EPIPE) {
 		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
 		dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
 			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
 			   "failed cmd %s rqt %u rq %u len %u ret %d\n",
 			   current->comm, ctrl.bRequestType, ctrl.bRequest,
 			   current->comm, ctrl.bRequestType, ctrl.bRequest,
@@ -705,9 +734,11 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 
 
 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
 	if (copy_from_user(&bulk, arg, sizeof(bulk)))
 		return -EFAULT;
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+	ret = findintfep(ps->dev, bulk.ep);
+	if (ret < 0)
 		return ret;
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 		return ret;
 	if (bulk.ep & USB_DIR_IN)
 	if (bulk.ep & USB_DIR_IN)
 		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
 		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
@@ -735,7 +766,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 			if (usbfs_snoop) {
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "bulk read: data ");
 				dev_info(&dev->dev, "bulk read: data ");
 				for (j = 0; j < len2; ++j)
 				for (j = 0; j < len2; ++j)
-					printk("%02x ", (unsigned char)(tbuf)[j]);
+					printk("%02x ", (u8)(tbuf)[j]);
 				printk("\n");
 				printk("\n");
 			}
 			}
 			if (copy_to_user(bulk.data, tbuf, len2)) {
 			if (copy_to_user(bulk.data, tbuf, len2)) {
@@ -775,9 +806,11 @@ static int proc_resetep(struct dev_state *ps, void __user *arg)
 
 
 	if (get_user(ep, (unsigned int __user *)arg))
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
+	ret = findintfep(ps->dev, ep);
+	if (ret < 0)
 		return ret;
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 		return ret;
 	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
 	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
 	return 0;
 	return 0;
@@ -791,18 +824,19 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg)
 
 
 	if (get_user(ep, (unsigned int __user *)arg))
 	if (get_user(ep, (unsigned int __user *)arg))
 		return -EFAULT;
 		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
+	ret = findintfep(ps->dev, ep);
+	if (ret < 0)
 		return ret;
 		return ret;
-	if ((ret = checkintf(ps, ret)))
+	ret = checkintf(ps, ret);
+	if (ret)
 		return ret;
 		return ret;
 	if (ep & USB_DIR_IN)
 	if (ep & USB_DIR_IN)
-                pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
-        else
-                pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
+		pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
+	else
+		pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
 
 
 	return usb_clear_halt(ps->dev, pipe);
 	return usb_clear_halt(ps->dev, pipe);
 }
 }
-		
 
 
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 static int proc_getdriver(struct dev_state *ps, void __user *arg)
 {
 {
@@ -856,23 +890,23 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
 {
 {
 	int u;
 	int u;
 	int status = 0;
 	int status = 0;
- 	struct usb_host_config *actconfig;
+	struct usb_host_config *actconfig;
 
 
 	if (get_user(u, (int __user *)arg))
 	if (get_user(u, (int __user *)arg))
 		return -EFAULT;
 		return -EFAULT;
 
 
- 	actconfig = ps->dev->actconfig;
- 
- 	/* Don't touch the device if any interfaces are claimed.
- 	 * It could interfere with other drivers' operations, and if
+	actconfig = ps->dev->actconfig;
+
+	/* Don't touch the device if any interfaces are claimed.
+	 * It could interfere with other drivers' operations, and if
 	 * an interface is claimed by usbfs it could easily deadlock.
 	 * an interface is claimed by usbfs it could easily deadlock.
 	 */
 	 */
- 	if (actconfig) {
- 		int i;
- 
- 		for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {
- 			if (usb_interface_claimed(actconfig->interface[i])) {
-				dev_warn (&ps->dev->dev,
+	if (actconfig) {
+		int i;
+
+		for (i = 0; i < actconfig->desc.bNumInterfaces; ++i) {
+			if (usb_interface_claimed(actconfig->interface[i])) {
+				dev_warn(&ps->dev->dev,
 					"usbfs: interface %d claimed by %s "
 					"usbfs: interface %d claimed by %s "
 					"while '%s' sets config #%d\n",
 					"while '%s' sets config #%d\n",
 					actconfig->interface[i]
 					actconfig->interface[i]
@@ -881,11 +915,11 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
 					actconfig->interface[i]
 					actconfig->interface[i]
 						->dev.driver->name,
 						->dev.driver->name,
 					current->comm, u);
 					current->comm, u);
- 				status = -EBUSY;
+				status = -EBUSY;
 				break;
 				break;
 			}
 			}
- 		}
- 	}
+		}
+	}
 
 
 	/* SET_CONFIGURATION is often abused as a "cheap" driver reset,
 	/* SET_CONFIGURATION is often abused as a "cheap" driver reset,
 	 * so avoid usb_set_configuration()'s kick to sysfs
 	 * so avoid usb_set_configuration()'s kick to sysfs
@@ -901,8 +935,8 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
 }
 }
 
 
 static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
-			     struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
-			     void __user *arg)
+			struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
+			void __user *arg)
 {
 {
 	struct usbdevfs_iso_packet_desc *isopkt = NULL;
 	struct usbdevfs_iso_packet_desc *isopkt = NULL;
 	struct usb_host_endpoint *ep;
 	struct usb_host_endpoint *ep;
@@ -917,12 +951,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		return -EINVAL;
 		return -EINVAL;
 	if (!uurb->buffer)
 	if (!uurb->buffer)
 		return -EINVAL;
 		return -EINVAL;
-	if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || uurb->signr > SIGRTMAX))
+	if (uurb->signr != 0 && (uurb->signr < SIGRTMIN ||
+				 uurb->signr > SIGRTMAX))
 		return -EINVAL;
 		return -EINVAL;
-	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ifnum = findintfep(ps->dev, uurb->endpoint)) < 0)
+	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
+	    (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+		ifnum = findintfep(ps->dev, uurb->endpoint);
+		if (ifnum < 0)
 			return ifnum;
 			return ifnum;
-		if ((ret = checkintf(ps, ifnum)))
+		ret = checkintf(ps, ifnum);
+		if (ret)
 			return ret;
 			return ret;
 	}
 	}
 	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
 	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
@@ -938,10 +976,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	case USBDEVFS_URB_TYPE_CONTROL:
 	case USBDEVFS_URB_TYPE_CONTROL:
 		if (!usb_endpoint_xfer_control(&ep->desc))
 		if (!usb_endpoint_xfer_control(&ep->desc))
 			return -EINVAL;
 			return -EINVAL;
-		/* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
-		if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
+		/* min 8 byte setup packet,
+		 * max 8 byte setup plus an arbitrary data stage */
+		if (uurb->buffer_length < 8 ||
+		    uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
 			return -EINVAL;
 			return -EINVAL;
-		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
+		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+		if (!dr)
 			return -ENOMEM;
 			return -ENOMEM;
 		if (copy_from_user(dr, uurb->buffer, 8)) {
 		if (copy_from_user(dr, uurb->buffer, 8)) {
 			kfree(dr);
 			kfree(dr);
@@ -951,7 +992,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			kfree(dr);
 			kfree(dr);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
-		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
+		ret = check_ctrlrecip(ps, dr->bRequestType,
+				      le16_to_cpup(&dr->wIndex));
+		if (ret) {
 			kfree(dr);
 			kfree(dr);
 			return ret;
 			return ret;
 		}
 		}
@@ -997,11 +1040,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 
 
 	case USBDEVFS_URB_TYPE_ISO:
 	case USBDEVFS_URB_TYPE_ISO:
 		/* arbitrary limit */
 		/* arbitrary limit */
-		if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
+		if (uurb->number_of_packets < 1 ||
+		    uurb->number_of_packets > 128)
 			return -EINVAL;
 			return -EINVAL;
 		if (!usb_endpoint_xfer_isoc(&ep->desc))
 		if (!usb_endpoint_xfer_isoc(&ep->desc))
 			return -EINVAL;
 			return -EINVAL;
-		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
+		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
+				   uurb->number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
 			return -ENOMEM;
 		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
 		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
@@ -1009,7 +1054,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 			return -EFAULT;
 			return -EFAULT;
 		}
 		}
 		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
-			/* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */
+			/* arbitrary limit,
+			 * sufficient for USB 2.0 high-bandwidth iso */
 			if (isopkt[u].length > 8192) {
 			if (isopkt[u].length > 8192) {
 				kfree(isopkt);
 				kfree(isopkt);
 				return -EINVAL;
 				return -EINVAL;
@@ -1039,25 +1085,27 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	if (!(as = alloc_async(uurb->number_of_packets))) {
+	as = alloc_async(uurb->number_of_packets);
+	if (!as) {
 		kfree(isopkt);
 		kfree(isopkt);
 		kfree(dr);
 		kfree(dr);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-	if (!(as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL))) {
+	as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
+	if (!as->urb->transfer_buffer) {
 		kfree(isopkt);
 		kfree(isopkt);
 		kfree(dr);
 		kfree(dr);
 		free_async(as);
 		free_async(as);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
-        as->urb->dev = ps->dev;
-        as->urb->pipe = (uurb->type << 30) |
+	as->urb->dev = ps->dev;
+	as->urb->pipe = (uurb->type << 30) |
 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
 			__create_pipe(ps->dev, uurb->endpoint & 0xf) |
 			(uurb->endpoint & USB_DIR_IN);
 			(uurb->endpoint & USB_DIR_IN);
-        as->urb->transfer_flags = uurb->flags |
+	as->urb->transfer_flags = uurb->flags |
 			(is_in ? URB_DIR_IN : URB_DIR_OUT);
 			(is_in ? URB_DIR_IN : URB_DIR_OUT);
 	as->urb->transfer_buffer_length = uurb->buffer_length;
 	as->urb->transfer_buffer_length = uurb->buffer_length;
-	as->urb->setup_packet = (unsigned char*)dr;
+	as->urb->setup_packet = (unsigned char *)dr;
 	as->urb->start_frame = uurb->start_frame;
 	as->urb->start_frame = uurb->start_frame;
 	as->urb->number_of_packets = uurb->number_of_packets;
 	as->urb->number_of_packets = uurb->number_of_packets;
 	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
 	if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
@@ -1065,8 +1113,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
 		as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
 	else
 	else
 		as->urb->interval = ep->desc.bInterval;
 		as->urb->interval = ep->desc.bInterval;
-        as->urb->context = as;
-        as->urb->complete = async_completed;
+	as->urb->context = as;
+	as->urb->complete = async_completed;
 	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 		as->urb->iso_frame_desc[u].offset = totlen;
 		as->urb->iso_frame_desc[u].offset = totlen;
 		as->urb->iso_frame_desc[u].length = isopkt[u].length;
 		as->urb->iso_frame_desc[u].length = isopkt[u].length;
@@ -1074,7 +1122,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 	}
 	}
 	kfree(isopkt);
 	kfree(isopkt);
 	as->ps = ps;
 	as->ps = ps;
-        as->userurb = arg;
+	as->userurb = arg;
 	if (uurb->endpoint & USB_DIR_IN)
 	if (uurb->endpoint & USB_DIR_IN)
 		as->userbuffer = uurb->buffer;
 		as->userbuffer = uurb->buffer;
 	else
 	else
@@ -1093,14 +1141,15 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
 		}
 		}
 	}
 	}
 	snoop_urb(as->urb, as->userurb);
 	snoop_urb(as->urb, as->userurb);
-        async_newpending(as);
-        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
-		dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret);
-                async_removepending(as);
-                free_async(as);
-                return ret;
-        }
-        return 0;
+	async_newpending(as);
+	if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+		dev_printk(KERN_DEBUG, &ps->dev->dev,
+			   "usbfs: usb_submit_urb returned %d\n", ret);
+		async_removepending(as);
+		free_async(as);
+		return ret;
+	}
+	return 0;
 }
 }
 
 
 static int proc_submiturb(struct dev_state *ps, void __user *arg)
 static int proc_submiturb(struct dev_state *ps, void __user *arg)
@@ -1110,7 +1159,9 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
 	if (copy_from_user(&uurb, arg, sizeof(uurb)))
 	if (copy_from_user(&uurb, arg, sizeof(uurb)))
 		return -EFAULT;
 		return -EFAULT;
 
 
-	return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg);
+	return proc_do_submiturb(ps, &uurb,
+			(((struct usbdevfs_urb __user *)arg)->iso_frame_desc),
+			arg);
 }
 }
 
 
 static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
 static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
@@ -1132,7 +1183,8 @@ static int processcompl(struct async *as, void __user * __user *arg)
 	unsigned int i;
 	unsigned int i;
 
 
 	if (as->userbuffer)
 	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+				 urb->transfer_buffer_length))
 			return -EFAULT;
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
 		return -EFAULT;
@@ -1159,16 +1211,17 @@ static int processcompl(struct async *as, void __user * __user *arg)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct async* reap_as(struct dev_state *ps)
+static struct async *reap_as(struct dev_state *ps)
 {
 {
-        DECLARE_WAITQUEUE(wait, current);
+	DECLARE_WAITQUEUE(wait, current);
 	struct async *as = NULL;
 	struct async *as = NULL;
 	struct usb_device *dev = ps->dev;
 	struct usb_device *dev = ps->dev;
 
 
 	add_wait_queue(&ps->wait, &wait);
 	add_wait_queue(&ps->wait, &wait);
 	for (;;) {
 	for (;;) {
 		__set_current_state(TASK_INTERRUPTIBLE);
 		__set_current_state(TASK_INTERRUPTIBLE);
-		if ((as = async_getcompleted(ps)))
+		as = async_getcompleted(ps);
+		if (as)
 			break;
 			break;
 		if (signal_pending(current))
 		if (signal_pending(current))
 			break;
 			break;
@@ -1232,10 +1285,12 @@ static int proc_submiturb_compat(struct dev_state *ps, void __user *arg)
 {
 {
 	struct usbdevfs_urb uurb;
 	struct usbdevfs_urb uurb;
 
 
-	if (get_urb32(&uurb,(struct usbdevfs_urb32 __user *)arg))
+	if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg))
 		return -EFAULT;
 		return -EFAULT;
 
 
-	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc, arg);
+	return proc_do_submiturb(ps, &uurb,
+			((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc,
+			arg);
 }
 }
 
 
 static int processcompl_compat(struct async *as, void __user * __user *arg)
 static int processcompl_compat(struct async *as, void __user * __user *arg)
@@ -1246,7 +1301,8 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
 	unsigned int i;
 	unsigned int i;
 
 
 	if (as->userbuffer)
 	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer,
+				 urb->transfer_buffer_length))
 			return -EFAULT;
 			return -EFAULT;
 	if (put_user(as->status, &userurb->status))
 	if (put_user(as->status, &userurb->status))
 		return -EFAULT;
 		return -EFAULT;
@@ -1337,16 +1393,16 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 	struct usb_driver       *driver = NULL;
 	struct usb_driver       *driver = NULL;
 
 
 	/* alloc buffer */
 	/* alloc buffer */
-	if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
-		if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
+	if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) {
+		if ((buf = kmalloc(size, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 			return -ENOMEM;
 		if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
 		if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
-			if (copy_from_user (buf, ctl->data, size)) {
+			if (copy_from_user(buf, ctl->data, size)) {
 				kfree(buf);
 				kfree(buf);
 				return -EFAULT;
 				return -EFAULT;
 			}
 			}
 		} else {
 		} else {
-			memset (buf, 0, size);
+			memset(buf, 0, size);
 		}
 		}
 	}
 	}
 
 
@@ -1357,15 +1413,15 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 
 
 	if (ps->dev->state != USB_STATE_CONFIGURED)
 	if (ps->dev->state != USB_STATE_CONFIGURED)
 		retval = -EHOSTUNREACH;
 		retval = -EHOSTUNREACH;
-	else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
-               retval = -EINVAL;
+	else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno)))
+		retval = -EINVAL;
 	else switch (ctl->ioctl_code) {
 	else switch (ctl->ioctl_code) {
 
 
 	/* disconnect kernel driver from interface */
 	/* disconnect kernel driver from interface */
 	case USBDEVFS_DISCONNECT:
 	case USBDEVFS_DISCONNECT:
 		if (intf->dev.driver) {
 		if (intf->dev.driver) {
 			driver = to_usb_driver(intf->dev.driver);
 			driver = to_usb_driver(intf->dev.driver);
-			dev_dbg (&intf->dev, "disconnect by usbfs\n");
+			dev_dbg(&intf->dev, "disconnect by usbfs\n");
 			usb_driver_release_interface(driver, intf);
 			usb_driver_release_interface(driver, intf);
 		} else
 		} else
 			retval = -ENODATA;
 			retval = -ENODATA;
@@ -1373,9 +1429,10 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 
 
 	/* let kernel drivers try to (re)bind to the interface */
 	/* let kernel drivers try to (re)bind to the interface */
 	case USBDEVFS_CONNECT:
 	case USBDEVFS_CONNECT:
-		usb_unlock_device(ps->dev);
-		retval = bus_rescan_devices(intf->dev.bus);
-		usb_lock_device(ps->dev);
+		if (!intf->dev.driver)
+			retval = device_attach(&intf->dev);
+		else
+			retval = -EBUSY;
 		break;
 		break;
 
 
 	/* talk directly to the interface's driver */
 	/* talk directly to the interface's driver */
@@ -1385,7 +1442,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 		if (driver == NULL || driver->ioctl == NULL) {
 		if (driver == NULL || driver->ioctl == NULL) {
 			retval = -ENOTTY;
 			retval = -ENOTTY;
 		} else {
 		} else {
-			retval = driver->ioctl (intf, ctl->ioctl_code, buf);
+			retval = driver->ioctl(intf, ctl->ioctl_code, buf);
 			if (retval == -ENOIOCTLCMD)
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 				retval = -ENOTTY;
 		}
 		}
@@ -1393,9 +1450,9 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
 
 
 	/* cleanup and return */
 	/* cleanup and return */
 	if (retval >= 0
 	if (retval >= 0
-			&& (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
+			&& (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0
 			&& size > 0
 			&& size > 0
-			&& copy_to_user (ctl->data, buf, size) != 0)
+			&& copy_to_user(ctl->data, buf, size) != 0)
 		retval = -EFAULT;
 		retval = -EFAULT;
 
 
 	kfree(buf);
 	kfree(buf);
@@ -1406,7 +1463,7 @@ static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
 {
 {
 	struct usbdevfs_ioctl	ctrl;
 	struct usbdevfs_ioctl	ctrl;
 
 
-	if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+	if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
 		return -EFAULT;
 		return -EFAULT;
 	return proc_ioctl(ps, &ctrl);
 	return proc_ioctl(ps, &ctrl);
 }
 }
@@ -1434,7 +1491,8 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
  * are assuming that somehow the configuration has been prevented from
  * are assuming that somehow the configuration has been prevented from
  * changing.  But there's no mechanism to ensure that...
  * changing.  But there's no mechanism to ensure that...
  */
  */
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int usbdev_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
 {
 {
 	struct dev_state *ps = file->private_data;
 	struct dev_state *ps = file->private_data;
 	struct usb_device *dev = ps->dev;
 	struct usb_device *dev = ps->dev;
@@ -1577,7 +1635,8 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 }
 }
 
 
 /* No kernel lock - fine */
 /* No kernel lock - fine */
-static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int usbdev_poll(struct file *file,
+				struct poll_table_struct *wait)
 {
 {
 	struct dev_state *ps = file->private_data;
 	struct dev_state *ps = file->private_data;
 	unsigned int mask = 0;
 	unsigned int mask = 0;
@@ -1648,7 +1707,7 @@ int __init usb_devio_init(void)
 	int retval;
 	int retval;
 
 
 	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
 	retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
-			"usb_device");
+					"usb_device");
 	if (retval) {
 	if (retval) {
 		err("unable to register minors for usb_device");
 		err("unable to register minors for usb_device");
 		goto out;
 		goto out;

+ 23 - 21
drivers/usb/core/driver.c

@@ -202,10 +202,10 @@ static int usb_probe_interface(struct device *dev)
 	intf = to_usb_interface(dev);
 	intf = to_usb_interface(dev);
 	udev = interface_to_usbdev(intf);
 	udev = interface_to_usbdev(intf);
 
 
- 	if (udev->authorized == 0) {
- 		dev_err(&intf->dev, "Device is not authorized for usage\n");
- 		return -ENODEV;
- 	}
+	if (udev->authorized == 0) {
+		dev_err(&intf->dev, "Device is not authorized for usage\n");
+		return -ENODEV;
+	}
 
 
 	id = usb_match_id(intf, driver->id_table);
 	id = usb_match_id(intf, driver->id_table);
 	if (!id)
 	if (!id)
@@ -299,7 +299,7 @@ static int usb_unbind_interface(struct device *dev)
  * lock.
  * lock.
  */
  */
 int usb_driver_claim_interface(struct usb_driver *driver,
 int usb_driver_claim_interface(struct usb_driver *driver,
-				struct usb_interface *iface, void* priv)
+				struct usb_interface *iface, void *priv)
 {
 {
 	struct device *dev = &iface->dev;
 	struct device *dev = &iface->dev;
 	struct usb_device *udev = interface_to_usbdev(iface);
 	struct usb_device *udev = interface_to_usbdev(iface);
@@ -325,7 +325,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
 
 
 	return retval;
 	return retval;
 }
 }
-EXPORT_SYMBOL(usb_driver_claim_interface);
+EXPORT_SYMBOL_GPL(usb_driver_claim_interface);
 
 
 /**
 /**
  * usb_driver_release_interface - unbind a driver from an interface
  * usb_driver_release_interface - unbind a driver from an interface
@@ -370,7 +370,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
 	iface->needs_remote_wakeup = 0;
 	iface->needs_remote_wakeup = 0;
 	usb_pm_unlock(udev);
 	usb_pm_unlock(udev);
 }
 }
-EXPORT_SYMBOL(usb_driver_release_interface);
+EXPORT_SYMBOL_GPL(usb_driver_release_interface);
 
 
 /* returns 0 if no match, 1 if match */
 /* returns 0 if no match, 1 if match */
 int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
 int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
@@ -398,7 +398,7 @@ int usb_match_device(struct usb_device *dev, const struct usb_device_id *id)
 		return 0;
 		return 0;
 
 
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-	    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+	    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
 		return 0;
 		return 0;
 
 
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
 	if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
@@ -534,15 +534,15 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 	   id->driver_info is the way to create an entry that
 	   id->driver_info is the way to create an entry that
 	   indicates that the driver want to examine every
 	   indicates that the driver want to examine every
 	   device and interface. */
 	   device and interface. */
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-	       id->driver_info; id++) {
+	for (; id->idVendor || id->idProduct || id->bDeviceClass ||
+	       id->bInterfaceClass || id->driver_info; id++) {
 		if (usb_match_one_id(interface, id))
 		if (usb_match_one_id(interface, id))
 			return id;
 			return id;
 	}
 	}
 
 
 	return NULL;
 	return NULL;
 }
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
+EXPORT_SYMBOL_GPL(usb_match_id);
 
 
 static int usb_device_match(struct device *dev, struct device_driver *drv)
 static int usb_device_match(struct device *dev, struct device_driver *drv)
 {
 {
@@ -586,7 +586,7 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct usb_device *usb_dev;
 	struct usb_device *usb_dev;
 
 
 	/* driver is often null here; dev_dbg() would oops */
 	/* driver is often null here; dev_dbg() would oops */
-	pr_debug ("usb %s: uevent\n", dev->bus_id);
+	pr_debug("usb %s: uevent\n", dev->bus_id);
 
 
 	if (is_usb_device(dev))
 	if (is_usb_device(dev))
 		usb_dev = to_usb_device(dev);
 		usb_dev = to_usb_device(dev);
@@ -596,11 +596,11 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
 	}
 	}
 
 
 	if (usb_dev->devnum < 0) {
 	if (usb_dev->devnum < 0) {
-		pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+		pr_debug("usb %s: already deleted?\n", dev->bus_id);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 	if (!usb_dev->bus) {
 	if (!usb_dev->bus) {
-		pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+		pr_debug("usb %s: bus removed?\n", dev->bus_id);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -745,7 +745,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
 
 
 	return retval;
 	return retval;
 }
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
+EXPORT_SYMBOL_GPL(usb_register_driver);
 
 
 /**
 /**
  * usb_deregister - unregister a USB interface driver
  * usb_deregister - unregister a USB interface driver
@@ -769,7 +769,7 @@ void usb_deregister(struct usb_driver *driver)
 
 
 	usbfs_update_special();
 	usbfs_update_special();
 }
 }
-EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+EXPORT_SYMBOL_GPL(usb_deregister);
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 
 
@@ -854,8 +854,10 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
 			dev_err(&intf->dev, "%s error %d\n",
 			dev_err(&intf->dev, "%s error %d\n",
 					"suspend", status);
 					"suspend", status);
 	} else {
 	} else {
-		// FIXME else if there's no suspend method, disconnect...
-		// Not possible if auto_pm is set...
+		/*
+		 * FIXME else if there's no suspend method, disconnect...
+		 * Not possible if auto_pm is set...
+		 */
 		dev_warn(&intf->dev, "no suspend for driver %s?\n",
 		dev_warn(&intf->dev, "no suspend for driver %s?\n",
 				driver->name);
 				driver->name);
 		mark_quiesced(intf);
 		mark_quiesced(intf);
@@ -894,7 +896,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
 				dev_err(&intf->dev, "%s error %d\n",
 				dev_err(&intf->dev, "%s error %d\n",
 						"reset_resume", status);
 						"reset_resume", status);
 		} else {
 		} else {
-			// status = -EOPNOTSUPP;
+			/* status = -EOPNOTSUPP; */
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"reset_resume", driver->name);
 					"reset_resume", driver->name);
 		}
 		}
@@ -905,7 +907,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
 				dev_err(&intf->dev, "%s error %d\n",
 				dev_err(&intf->dev, "%s error %d\n",
 						"resume", status);
 						"resume", status);
 		} else {
 		} else {
-			// status = -EOPNOTSUPP;
+			/* status = -EOPNOTSUPP; */
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"resume", driver->name);
 					"resume", driver->name);
 		}
 		}
@@ -1175,7 +1177,7 @@ static int usb_resume_both(struct usb_device *udev)
 			 * so if a root hub's controller is suspended
 			 * so if a root hub's controller is suspended
 			 * then we're stuck. */
 			 * then we're stuck. */
 			status = usb_resume_device(udev);
 			status = usb_resume_device(udev);
- 		}
+		}
 	} else {
 	} else {
 
 
 		/* Needed for setting udev->dev.power.power_state.event,
 		/* Needed for setting udev->dev.power.power_state.event,

+ 2 - 2
drivers/usb/core/file.c

@@ -204,7 +204,7 @@ int usb_register_dev(struct usb_interface *intf,
 exit:
 exit:
 	return retval;
 	return retval;
 }
 }
-EXPORT_SYMBOL(usb_register_dev);
+EXPORT_SYMBOL_GPL(usb_register_dev);
 
 
 /**
 /**
  * usb_deregister_dev - deregister a USB device's dynamic minor.
  * usb_deregister_dev - deregister a USB device's dynamic minor.
@@ -245,4 +245,4 @@ void usb_deregister_dev(struct usb_interface *intf,
 	intf->minor = -1;
 	intf->minor = -1;
 	destroy_usb_class();
 	destroy_usb_class();
 }
 }
-EXPORT_SYMBOL(usb_deregister_dev);
+EXPORT_SYMBOL_GPL(usb_deregister_dev);

+ 78 - 67
drivers/usb/core/hcd-pci.c

@@ -1,6 +1,6 @@
 /*
 /*
  * (C) Copyright David Brownell 2000-2002
  * (C) Copyright David Brownell 2000-2002
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -55,7 +55,7 @@
  *
  *
  * Store this function in the HCD's struct pci_driver as probe().
  * Store this function in the HCD's struct pci_driver as probe().
  */
  */
-int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 {
 	struct hc_driver	*driver;
 	struct hc_driver	*driver;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
@@ -64,66 +64,71 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 	if (usb_disabled())
 	if (usb_disabled())
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (!id || !(driver = (struct hc_driver *) id->driver_data))
+	if (!id)
+		return -EINVAL;
+	driver = (struct hc_driver *)id->driver_data;
+	if (!driver)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (pci_enable_device (dev) < 0)
+	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 		return -ENODEV;
 	dev->current_state = PCI_D0;
 	dev->current_state = PCI_D0;
 	dev->dev.power.power_state = PMSG_ON;
 	dev->dev.power.power_state = PMSG_ON;
-	
-        if (!dev->irq) {
-        	dev_err (&dev->dev,
+
+	if (!dev->irq) {
+		dev_err(&dev->dev,
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			pci_name(dev));
 			pci_name(dev));
-   	        retval = -ENODEV;
+		retval = -ENODEV;
 		goto err1;
 		goto err1;
-        }
+	}
 
 
-	hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
+	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
 	if (!hcd) {
 	if (!hcd) {
 		retval = -ENOMEM;
 		retval = -ENOMEM;
 		goto err1;
 		goto err1;
 	}
 	}
 
 
-	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
-		hcd->rsrc_start = pci_resource_start (dev, 0);
-		hcd->rsrc_len = pci_resource_len (dev, 0);
-		if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,
+	if (driver->flags & HCD_MEMORY) {
+		/* EHCI, OHCI */
+		hcd->rsrc_start = pci_resource_start(dev, 0);
+		hcd->rsrc_len = pci_resource_len(dev, 0);
+		if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
 				driver->description)) {
-			dev_dbg (&dev->dev, "controller already in use\n");
+			dev_dbg(&dev->dev, "controller already in use\n");
 			retval = -EBUSY;
 			retval = -EBUSY;
 			goto err2;
 			goto err2;
 		}
 		}
-		hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
+		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
 		if (hcd->regs == NULL) {
 		if (hcd->regs == NULL) {
-			dev_dbg (&dev->dev, "error mapping memory\n");
+			dev_dbg(&dev->dev, "error mapping memory\n");
 			retval = -EFAULT;
 			retval = -EFAULT;
 			goto err3;
 			goto err3;
 		}
 		}
 
 
-	} else { 				// UHCI
+	} else {
+		/* UHCI */
 		int	region;
 		int	region;
 
 
 		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
 		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
-			if (!(pci_resource_flags (dev, region) &
+			if (!(pci_resource_flags(dev, region) &
 					IORESOURCE_IO))
 					IORESOURCE_IO))
 				continue;
 				continue;
 
 
-			hcd->rsrc_start = pci_resource_start (dev, region);
-			hcd->rsrc_len = pci_resource_len (dev, region);
-			if (request_region (hcd->rsrc_start, hcd->rsrc_len,
+			hcd->rsrc_start = pci_resource_start(dev, region);
+			hcd->rsrc_len = pci_resource_len(dev, region);
+			if (request_region(hcd->rsrc_start, hcd->rsrc_len,
 					driver->description))
 					driver->description))
 				break;
 				break;
 		}
 		}
 		if (region == PCI_ROM_RESOURCE) {
 		if (region == PCI_ROM_RESOURCE) {
-			dev_dbg (&dev->dev, "no i/o regions available\n");
+			dev_dbg(&dev->dev, "no i/o regions available\n");
 			retval = -EBUSY;
 			retval = -EBUSY;
 			goto err1;
 			goto err1;
 		}
 		}
 	}
 	}
 
 
-	pci_set_master (dev);
+	pci_set_master(dev);
 
 
 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
 	if (retval != 0)
@@ -132,19 +137,19 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 
 
  err4:
  err4:
 	if (driver->flags & HCD_MEMORY) {
 	if (driver->flags & HCD_MEMORY) {
-		iounmap (hcd->regs);
+		iounmap(hcd->regs);
  err3:
  err3:
-		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else
 	} else
-		release_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_region(hcd->rsrc_start, hcd->rsrc_len);
  err2:
  err2:
-	usb_put_hcd (hcd);
+	usb_put_hcd(hcd);
  err1:
  err1:
-	pci_disable_device (dev);
-	dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
+	pci_disable_device(dev);
+	dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
 	return retval;
 	return retval;
-} 
-EXPORT_SYMBOL (usb_hcd_pci_probe);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_pci_probe);
 
 
 
 
 /* may be called without controller electrically present */
 /* may be called without controller electrically present */
@@ -161,7 +166,7 @@ EXPORT_SYMBOL (usb_hcd_pci_probe);
  *
  *
  * Store this function in the HCD's struct pci_driver as remove().
  * Store this function in the HCD's struct pci_driver as remove().
  */
  */
-void usb_hcd_pci_remove (struct pci_dev *dev)
+void usb_hcd_pci_remove(struct pci_dev *dev)
 {
 {
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 
 
@@ -169,17 +174,17 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
 	if (!hcd)
 	if (!hcd)
 		return;
 		return;
 
 
-	usb_remove_hcd (hcd);
+	usb_remove_hcd(hcd);
 	if (hcd->driver->flags & HCD_MEMORY) {
 	if (hcd->driver->flags & HCD_MEMORY) {
-		iounmap (hcd->regs);
-		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+		iounmap(hcd->regs);
+		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else {
 	} else {
-		release_region (hcd->rsrc_start, hcd->rsrc_len);
+		release_region(hcd->rsrc_start, hcd->rsrc_len);
 	}
 	}
-	usb_put_hcd (hcd);
+	usb_put_hcd(hcd);
 	pci_disable_device(dev);
 	pci_disable_device(dev);
 }
 }
-EXPORT_SYMBOL (usb_hcd_pci_remove);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
 
 
 
 
 #ifdef	CONFIG_PM
 #ifdef	CONFIG_PM
@@ -191,7 +196,7 @@ EXPORT_SYMBOL (usb_hcd_pci_remove);
  *
  *
  * Store this function in the HCD's struct pci_driver as suspend().
  * Store this function in the HCD's struct pci_driver as suspend().
  */
  */
-int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
+int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
 {
 {
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 	int			retval = 0;
 	int			retval = 0;
@@ -246,12 +251,18 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
 
 
 		/* no DMA or IRQs except when HC is active */
 		/* no DMA or IRQs except when HC is active */
 		if (dev->current_state == PCI_D0) {
 		if (dev->current_state == PCI_D0) {
-			pci_save_state (dev);
-			pci_disable_device (dev);
+			pci_save_state(dev);
+			pci_disable_device(dev);
+		}
+
+		if (message.event == PM_EVENT_FREEZE ||
+				message.event == PM_EVENT_PRETHAW) {
+			dev_dbg(hcd->self.controller, "--> no state change\n");
+			goto done;
 		}
 		}
 
 
 		if (!has_pci_pm) {
 		if (!has_pci_pm) {
-			dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
+			dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n");
 			goto done;
 			goto done;
 		}
 		}
 
 
@@ -260,30 +271,30 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
 		 * PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
 		 * PCI_D3 (but not PCI_D1 or PCI_D2) is allowed to reset
 		 * some device state (e.g. as part of clock reinit).
 		 * some device state (e.g. as part of clock reinit).
 		 */
 		 */
-		retval = pci_set_power_state (dev, PCI_D3hot);
+		retval = pci_set_power_state(dev, PCI_D3hot);
 		suspend_report_result(pci_set_power_state, retval);
 		suspend_report_result(pci_set_power_state, retval);
 		if (retval == 0) {
 		if (retval == 0) {
 			int wake = device_can_wakeup(&hcd->self.root_hub->dev);
 			int wake = device_can_wakeup(&hcd->self.root_hub->dev);
 
 
 			wake = wake && device_may_wakeup(hcd->self.controller);
 			wake = wake && device_may_wakeup(hcd->self.controller);
 
 
-			dev_dbg (hcd->self.controller, "--> PCI D3%s\n",
+			dev_dbg(hcd->self.controller, "--> PCI D3%s\n",
 					wake ? "/wakeup" : "");
 					wake ? "/wakeup" : "");
 
 
 			/* Ignore these return values.  We rely on pci code to
 			/* Ignore these return values.  We rely on pci code to
 			 * reject requests the hardware can't implement, rather
 			 * reject requests the hardware can't implement, rather
 			 * than coding the same thing.
 			 * than coding the same thing.
 			 */
 			 */
-			(void) pci_enable_wake (dev, PCI_D3hot, wake);
-			(void) pci_enable_wake (dev, PCI_D3cold, wake);
+			(void) pci_enable_wake(dev, PCI_D3hot, wake);
+			(void) pci_enable_wake(dev, PCI_D3cold, wake);
 		} else {
 		} else {
-			dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+			dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
 					retval);
 					retval);
-			(void) usb_hcd_pci_resume (dev);
+			(void) usb_hcd_pci_resume(dev);
 		}
 		}
 
 
 	} else if (hcd->state != HC_STATE_HALT) {
 	} else if (hcd->state != HC_STATE_HALT) {
-		dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
+		dev_dbg(hcd->self.controller, "hcd state %d; not suspended\n",
 			hcd->state);
 			hcd->state);
 		WARN_ON(1);
 		WARN_ON(1);
 		retval = -EINVAL;
 		retval = -EINVAL;
@@ -298,7 +309,7 @@ done:
 		if (machine_is(powermac)) {
 		if (machine_is(powermac)) {
 			struct device_node	*of_node;
 			struct device_node	*of_node;
 
 
-			of_node = pci_device_to_OF_node (dev);
+			of_node = pci_device_to_OF_node(dev);
 			if (of_node)
 			if (of_node)
 				pmac_call_feature(PMAC_FTR_USB_ENABLE,
 				pmac_call_feature(PMAC_FTR_USB_ENABLE,
 							of_node, 0, 0);
 							of_node, 0, 0);
@@ -308,7 +319,7 @@ done:
 
 
 	return retval;
 	return retval;
 }
 }
-EXPORT_SYMBOL (usb_hcd_pci_suspend);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
 
 
 /**
 /**
  * usb_hcd_pci_resume - power management resume of a PCI-based HCD
  * usb_hcd_pci_resume - power management resume of a PCI-based HCD
@@ -316,14 +327,14 @@ EXPORT_SYMBOL (usb_hcd_pci_suspend);
  *
  *
  * Store this function in the HCD's struct pci_driver as resume().
  * Store this function in the HCD's struct pci_driver as resume().
  */
  */
-int usb_hcd_pci_resume (struct pci_dev *dev)
+int usb_hcd_pci_resume(struct pci_dev *dev)
 {
 {
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 	int			retval;
 	int			retval;
 
 
 	hcd = pci_get_drvdata(dev);
 	hcd = pci_get_drvdata(dev);
 	if (hcd->state != HC_STATE_SUSPENDED) {
 	if (hcd->state != HC_STATE_SUSPENDED) {
-		dev_dbg (hcd->self.controller, 
+		dev_dbg(hcd->self.controller,
 				"can't resume, not suspended!\n");
 				"can't resume, not suspended!\n");
 		return 0;
 		return 0;
 	}
 	}
@@ -333,9 +344,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 	if (machine_is(powermac)) {
 	if (machine_is(powermac)) {
 		struct device_node *of_node;
 		struct device_node *of_node;
 
 
-		of_node = pci_device_to_OF_node (dev);
+		of_node = pci_device_to_OF_node(dev);
 		if (of_node)
 		if (of_node)
-			pmac_call_feature (PMAC_FTR_USB_ENABLE,
+			pmac_call_feature(PMAC_FTR_USB_ENABLE,
 						of_node, 0, 1);
 						of_node, 0, 1);
 	}
 	}
 #endif
 #endif
@@ -374,8 +385,8 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 		}
 		}
 #endif
 #endif
 		/* yes, ignore these results too... */
 		/* yes, ignore these results too... */
-		(void) pci_enable_wake (dev, dev->current_state, 0);
-		(void) pci_enable_wake (dev, PCI_D3cold, 0);
+		(void) pci_enable_wake(dev, dev->current_state, 0);
+		(void) pci_enable_wake(dev, PCI_D3cold, 0);
 	} else {
 	} else {
 		/* Same basic cases: clean (powered/not), dirty */
 		/* Same basic cases: clean (powered/not), dirty */
 		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
 		dev_dbg(hcd->self.controller, "PCI legacy resume\n");
@@ -386,14 +397,14 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 	 * but that won't re-enable bus mastering.  Yet pci_disable_device()
 	 * but that won't re-enable bus mastering.  Yet pci_disable_device()
 	 * explicitly disables bus mastering...
 	 * explicitly disables bus mastering...
 	 */
 	 */
-	retval = pci_enable_device (dev);
+	retval = pci_enable_device(dev);
 	if (retval < 0) {
 	if (retval < 0) {
-		dev_err (hcd->self.controller,
+		dev_err(hcd->self.controller,
 			"can't re-enable after resume, %d!\n", retval);
 			"can't re-enable after resume, %d!\n", retval);
 		return retval;
 		return retval;
 	}
 	}
-	pci_set_master (dev);
-	pci_restore_state (dev);
+	pci_set_master(dev);
+	pci_restore_state(dev);
 
 
 	dev->dev.power.power_state = PMSG_ON;
 	dev->dev.power.power_state = PMSG_ON;
 
 
@@ -402,15 +413,15 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 	if (hcd->driver->resume) {
 	if (hcd->driver->resume) {
 		retval = hcd->driver->resume(hcd);
 		retval = hcd->driver->resume(hcd);
 		if (retval) {
 		if (retval) {
-			dev_err (hcd->self.controller,
+			dev_err(hcd->self.controller,
 				"PCI post-resume error %d!\n", retval);
 				"PCI post-resume error %d!\n", retval);
-			usb_hc_died (hcd);
+			usb_hc_died(hcd);
 		}
 		}
 	}
 	}
 
 
 	return retval;
 	return retval;
 }
 }
-EXPORT_SYMBOL (usb_hcd_pci_resume);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
 
 
 #endif	/* CONFIG_PM */
 #endif	/* CONFIG_PM */
 
 
@@ -418,7 +429,7 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
  * usb_hcd_pci_shutdown - shutdown host controller
  * usb_hcd_pci_shutdown - shutdown host controller
  * @dev: USB Host Controller being shutdown
  * @dev: USB Host Controller being shutdown
  */
  */
-void usb_hcd_pci_shutdown (struct pci_dev *dev)
+void usb_hcd_pci_shutdown(struct pci_dev *dev)
 {
 {
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 
 
@@ -429,5 +440,5 @@ void usb_hcd_pci_shutdown (struct pci_dev *dev)
 	if (hcd->driver->shutdown)
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 		hcd->driver->shutdown(hcd);
 }
 }
-EXPORT_SYMBOL (usb_hcd_pci_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
 

+ 176 - 40
drivers/usb/core/hcd.c

@@ -35,6 +35,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 
 
@@ -131,8 +132,8 @@ static const u8 usb2_rh_dev_descriptor [18] = {
 	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
 	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
 
-	0x00, 0x00, /*  __le16 idVendor; */
- 	0x00, 0x00, /*  __le16 idProduct; */
+	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 
 	0x03,       /*  __u8  iManufacturer; */
 	0x03,       /*  __u8  iManufacturer; */
@@ -154,8 +155,8 @@ static const u8 usb11_rh_dev_descriptor [18] = {
 	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
 	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 	0x40,       /*  __u8  bMaxPacketSize0; 64 Bytes */
 
 
-	0x00, 0x00, /*  __le16 idVendor; */
- 	0x00, 0x00, /*  __le16 idProduct; */
+	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
+	0x01, 0x00, /*  __le16 idProduct; device 0x0001 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 
 	0x03,       /*  __u8  iManufacturer; */
 	0x03,       /*  __u8  iManufacturer; */
@@ -807,13 +808,13 @@ static int usb_register_bus(struct usb_bus *bus)
 	}
 	}
 	set_bit (busnum, busmap.busmap);
 	set_bit (busnum, busmap.busmap);
 	bus->busnum = busnum;
 	bus->busnum = busnum;
-	bus->class_dev = class_device_create(usb_host_class, NULL, MKDEV(0,0),
-					     bus->controller, "usb_host%d",
-					     busnum);
-	result = PTR_ERR(bus->class_dev);
-	if (IS_ERR(bus->class_dev))
+
+	bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
+				 "usb_host%d", busnum);
+	result = PTR_ERR(bus->dev);
+	if (IS_ERR(bus->dev))
 		goto error_create_class_dev;
 		goto error_create_class_dev;
-	class_set_devdata(bus->class_dev, bus);
+	dev_set_drvdata(bus->dev, bus);
 
 
 	/* Add it to the local list of buses */
 	/* Add it to the local list of buses */
 	list_add (&bus->bus_list, &usb_bus_list);
 	list_add (&bus->bus_list, &usb_bus_list);
@@ -857,7 +858,7 @@ static void usb_deregister_bus (struct usb_bus *bus)
 
 
 	clear_bit (bus->busnum, busmap.busmap);
 	clear_bit (bus->busnum, busmap.busmap);
 
 
-	class_device_unregister(bus->class_dev);
+	device_unregister(bus->dev);
 }
 }
 
 
 /**
 /**
@@ -970,7 +971,7 @@ long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)
 		return -1;
 		return -1;
 	}
 	}
 }
 }
-EXPORT_SYMBOL (usb_calc_bus_time);
+EXPORT_SYMBOL_GPL(usb_calc_bus_time);
 
 
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -1112,48 +1113,177 @@ void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb)
 }
 }
 EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
 EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
 
 
-static void map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+/*
+ * Some usb host controllers can only perform dma using a small SRAM area.
+ * The usb core itself is however optimized for host controllers that can dma
+ * using regular system memory - like pci devices doing bus mastering.
+ *
+ * To support host controllers with limited dma capabilites we provide dma
+ * bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag.
+ * For this to work properly the host controller code must first use the
+ * function dma_declare_coherent_memory() to point out which memory area
+ * that should be used for dma allocations.
+ *
+ * The HCD_LOCAL_MEM flag then tells the usb code to allocate all data for
+ * dma using dma_alloc_coherent() which in turn allocates from the memory
+ * area pointed out with dma_declare_coherent_memory().
+ *
+ * So, to summarize...
+ *
+ * - We need "local" memory, canonical example being
+ *   a small SRAM on a discrete controller being the
+ *   only memory that the controller can read ...
+ *   (a) "normal" kernel memory is no good, and
+ *   (b) there's not enough to share
+ *
+ * - The only *portable* hook for such stuff in the
+ *   DMA framework is dma_declare_coherent_memory()
+ *
+ * - So we use that, even though the primary requirement
+ *   is that the memory be "local" (hence addressible
+ *   by that device), not "coherent".
+ *
+ */
+
+static int hcd_alloc_coherent(struct usb_bus *bus,
+			      gfp_t mem_flags, dma_addr_t *dma_handle,
+			      void **vaddr_handle, size_t size,
+			      enum dma_data_direction dir)
+{
+	unsigned char *vaddr;
+
+	vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr),
+				 mem_flags, dma_handle);
+	if (!vaddr)
+		return -ENOMEM;
+
+	/*
+	 * Store the virtual address of the buffer at the end
+	 * of the allocated dma buffer. The size of the buffer
+	 * may be uneven so use unaligned functions instead
+	 * of just rounding up. It makes sense to optimize for
+	 * memory footprint over access speed since the amount
+	 * of memory available for dma may be limited.
+	 */
+	put_unaligned((unsigned long)*vaddr_handle,
+		      (unsigned long *)(vaddr + size));
+
+	if (dir == DMA_TO_DEVICE)
+		memcpy(vaddr, *vaddr_handle, size);
+
+	*vaddr_handle = vaddr;
+	return 0;
+}
+
+static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
+			      void **vaddr_handle, size_t size,
+			      enum dma_data_direction dir)
+{
+	unsigned char *vaddr = *vaddr_handle;
+
+	vaddr = (void *)get_unaligned((unsigned long *)(vaddr + size));
+
+	if (dir == DMA_FROM_DEVICE)
+		memcpy(vaddr, *vaddr_handle, size);
+
+	hcd_buffer_free(bus, size + sizeof(vaddr), *vaddr_handle, *dma_handle);
+
+	*vaddr_handle = vaddr;
+	*dma_handle = 0;
+}
+
+static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+			   gfp_t mem_flags)
 {
 {
+	enum dma_data_direction dir;
+	int ret = 0;
+
 	/* Map the URB's buffers for DMA access.
 	/* Map the URB's buffers for DMA access.
 	 * Lower level HCD code should use *_dma exclusively,
 	 * Lower level HCD code should use *_dma exclusively,
 	 * unless it uses pio or talks to another transport.
 	 * unless it uses pio or talks to another transport.
 	 */
 	 */
-	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
-		if (usb_endpoint_xfer_control(&urb->ep->desc)
-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-			urb->setup_dma = dma_map_single (
+	if (is_root_hub(urb->dev))
+		return 0;
+
+	if (usb_endpoint_xfer_control(&urb->ep->desc)
+	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+		if (hcd->self.uses_dma)
+			urb->setup_dma = dma_map_single(
 					hcd->self.controller,
 					hcd->self.controller,
 					urb->setup_packet,
 					urb->setup_packet,
-					sizeof (struct usb_ctrlrequest),
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
 					DMA_TO_DEVICE);
-		if (urb->transfer_buffer_length != 0
-			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+	}
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (ret == 0 && urb->transfer_buffer_length != 0
+	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			urb->transfer_dma = dma_map_single (
 			urb->transfer_dma = dma_map_single (
 					hcd->self.controller,
 					hcd->self.controller,
 					urb->transfer_buffer,
 					urb->transfer_buffer,
 					urb->transfer_buffer_length,
 					urb->transfer_buffer_length,
-					usb_urb_dir_in(urb)
-					    ? DMA_FROM_DEVICE
-					    : DMA_TO_DEVICE);
+					dir);
+		else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+			ret = hcd_alloc_coherent(
+					urb->dev->bus, mem_flags,
+					&urb->transfer_dma,
+					&urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					dir);
+
+			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
+			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+				hcd_free_coherent(urb->dev->bus,
+					&urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+		}
 	}
 	}
+	return ret;
 }
 }
 
 
 static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
 {
-	if (hcd->self.uses_dma && !is_root_hub(urb->dev)) {
-		if (usb_endpoint_xfer_control(&urb->ep->desc)
-			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+	enum dma_data_direction dir;
+
+	if (is_root_hub(urb->dev))
+		return;
+
+	if (usb_endpoint_xfer_control(&urb->ep->desc)
+	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			dma_unmap_single(hcd->self.controller, urb->setup_dma,
 			dma_unmap_single(hcd->self.controller, urb->setup_dma,
 					sizeof(struct usb_ctrlrequest),
 					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
 					DMA_TO_DEVICE);
-		if (urb->transfer_buffer_length != 0
-			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+					(void **)&urb->setup_packet,
+					sizeof(struct usb_ctrlrequest),
+					DMA_TO_DEVICE);
+	}
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (urb->transfer_buffer_length != 0
+	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+		if (hcd->self.uses_dma)
 			dma_unmap_single(hcd->self.controller,
 			dma_unmap_single(hcd->self.controller,
 					urb->transfer_dma,
 					urb->transfer_dma,
 					urb->transfer_buffer_length,
 					urb->transfer_buffer_length,
-					usb_urb_dir_in(urb)
-					    ? DMA_FROM_DEVICE
-					    : DMA_TO_DEVICE);
+					dir);
+		else if (hcd->driver->flags & HCD_LOCAL_MEM)
+			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+					&urb->transfer_buffer,
+					urb->transfer_buffer_length,
+					dir);
 	}
 	}
 }
 }
 
 
@@ -1185,7 +1315,12 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 	 * URBs must be submitted in process context with interrupts
 	 * URBs must be submitted in process context with interrupts
 	 * enabled.
 	 * enabled.
 	 */
 	 */
-	map_urb_for_dma(hcd, urb);
+	status = map_urb_for_dma(hcd, urb, mem_flags);
+	if (unlikely(status)) {
+		usbmon_urb_submit_error(&hcd->self, urb, status);
+		goto error;
+	}
+
 	if (is_root_hub(urb->dev))
 	if (is_root_hub(urb->dev))
 		status = rh_urb_enqueue(hcd, urb);
 		status = rh_urb_enqueue(hcd, urb);
 	else
 	else
@@ -1194,6 +1329,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 	if (unlikely(status)) {
 	if (unlikely(status)) {
 		usbmon_urb_submit_error(&hcd->self, urb, status);
 		usbmon_urb_submit_error(&hcd->self, urb, status);
 		unmap_urb_for_dma(hcd, urb);
 		unmap_urb_for_dma(hcd, urb);
+ error:
 		urb->hcpriv = NULL;
 		urb->hcpriv = NULL;
 		INIT_LIST_HEAD(&urb->urb_list);
 		INIT_LIST_HEAD(&urb->urb_list);
 		atomic_dec(&urb->use_count);
 		atomic_dec(&urb->use_count);
@@ -1291,7 +1427,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
 		wake_up (&usb_kill_urb_queue);
 		wake_up (&usb_kill_urb_queue);
 	usb_put_urb (urb);
 	usb_put_urb (urb);
 }
 }
-EXPORT_SYMBOL (usb_hcd_giveback_urb);
+EXPORT_SYMBOL_GPL(usb_hcd_giveback_urb);
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
@@ -1531,7 +1667,7 @@ int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
 		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
 		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
 	return status;
 	return status;
 }
 }
-EXPORT_SYMBOL (usb_bus_start_enum);
+EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 
 
 #endif
 #endif
 
 
@@ -1638,7 +1774,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 			"USB Host Controller";
 			"USB Host Controller";
 	return hcd;
 	return hcd;
 }
 }
-EXPORT_SYMBOL (usb_create_hcd);
+EXPORT_SYMBOL_GPL(usb_create_hcd);
 
 
 static void hcd_release (struct kref *kref)
 static void hcd_release (struct kref *kref)
 {
 {
@@ -1653,14 +1789,14 @@ struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
 		kref_get (&hcd->kref);
 		kref_get (&hcd->kref);
 	return hcd;
 	return hcd;
 }
 }
-EXPORT_SYMBOL (usb_get_hcd);
+EXPORT_SYMBOL_GPL(usb_get_hcd);
 
 
 void usb_put_hcd (struct usb_hcd *hcd)
 void usb_put_hcd (struct usb_hcd *hcd)
 {
 {
 	if (hcd)
 	if (hcd)
 		kref_put (&hcd->kref, hcd_release);
 		kref_put (&hcd->kref, hcd_release);
 }
 }
-EXPORT_SYMBOL (usb_put_hcd);
+EXPORT_SYMBOL_GPL(usb_put_hcd);
 
 
 /**
 /**
  * usb_add_hcd - finish generic HCD structure initialization and register
  * usb_add_hcd - finish generic HCD structure initialization and register
@@ -1786,7 +1922,7 @@ err_register_bus:
 	hcd_buffer_destroy(hcd);
 	hcd_buffer_destroy(hcd);
 	return retval;
 	return retval;
 } 
 } 
-EXPORT_SYMBOL (usb_add_hcd);
+EXPORT_SYMBOL_GPL(usb_add_hcd);
 
 
 /**
 /**
  * usb_remove_hcd - shutdown processing for generic HCDs
  * usb_remove_hcd - shutdown processing for generic HCDs
@@ -1828,7 +1964,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	usb_deregister_bus(&hcd->self);
 	usb_deregister_bus(&hcd->self);
 	hcd_buffer_destroy(hcd);
 	hcd_buffer_destroy(hcd);
 }
 }
-EXPORT_SYMBOL (usb_remove_hcd);
+EXPORT_SYMBOL_GPL(usb_remove_hcd);
 
 
 void
 void
 usb_hcd_platform_shutdown(struct platform_device* dev)
 usb_hcd_platform_shutdown(struct platform_device* dev)
@@ -1838,7 +1974,7 @@ usb_hcd_platform_shutdown(struct platform_device* dev)
 	if (hcd->driver->shutdown)
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 		hcd->driver->shutdown(hcd);
 }
 }
-EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 48 - 44
drivers/usb/core/hcd.h

@@ -125,7 +125,7 @@ struct usb_hcd {
 
 
 	/* more shared queuing code would be good; it should support
 	/* more shared queuing code would be good; it should support
 	 * smarter scheduling, handle transaction translators, etc;
 	 * smarter scheduling, handle transaction translators, etc;
-	 * input size of periodic table to an interrupt scheduler. 
+	 * input size of periodic table to an interrupt scheduler.
 	 * (ohci 32, uhci 1024, ehci 256/512/1024).
 	 * (ohci 32, uhci 1024, ehci 256/512/1024).
 	 */
 	 */
 
 
@@ -133,16 +133,16 @@ struct usb_hcd {
 	 * this structure.
 	 * this structure.
 	 */
 	 */
 	unsigned long hcd_priv[0]
 	unsigned long hcd_priv[0]
-			__attribute__ ((aligned (sizeof(unsigned long))));
+			__attribute__ ((aligned(sizeof(unsigned long))));
 };
 };
 
 
 /* 2.4 does this a bit differently ... */
 /* 2.4 does this a bit differently ... */
-static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
+static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd)
 {
 {
 	return &hcd->self;
 	return &hcd->self;
 }
 }
 
 
-static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
+static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus)
 {
 {
 	return container_of(bus, struct usb_hcd, self);
 	return container_of(bus, struct usb_hcd, self);
 }
 }
@@ -165,6 +165,7 @@ struct hc_driver {
 
 
 	int	flags;
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
+#define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 
 
@@ -201,15 +202,18 @@ struct hc_driver {
 			struct usb_host_endpoint *ep);
 			struct usb_host_endpoint *ep);
 
 
 	/* root hub support */
 	/* root hub support */
-	int		(*hub_status_data) (struct usb_hcd *hcd, char *buf);
-	int		(*hub_control) (struct usb_hcd *hcd,
+	int	(*hub_status_data) (struct usb_hcd *hcd, char *buf);
+	int	(*hub_control) (struct usb_hcd *hcd,
 				u16 typeReq, u16 wValue, u16 wIndex,
 				u16 typeReq, u16 wValue, u16 wIndex,
 				char *buf, u16 wLength);
 				char *buf, u16 wLength);
-	int		(*bus_suspend)(struct usb_hcd *);
-	int		(*bus_resume)(struct usb_hcd *);
-	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
-	void		(*hub_irq_enable)(struct usb_hcd *);
+	int	(*bus_suspend)(struct usb_hcd *);
+	int	(*bus_resume)(struct usb_hcd *);
+	int	(*start_port_reset)(struct usb_hcd *, unsigned port_num);
+	void	(*hub_irq_enable)(struct usb_hcd *);
 		/* Needed only if port-change IRQs are level-triggered */
 		/* Needed only if port-change IRQs are level-triggered */
+
+		/* force handover of high-speed port to full-speed companion */
+	void	(*relinquish_port)(struct usb_hcd *, int);
 };
 };
 
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -217,56 +221,56 @@ extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
 		int status);
 extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
 extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
 
 
-extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
-extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
+extern int usb_hcd_unlink_urb(struct urb *urb, int status);
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
 		int status);
 extern void usb_hcd_flush_endpoint(struct usb_device *udev,
 extern void usb_hcd_flush_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 		struct usb_host_endpoint *ep);
-extern int usb_hcd_get_frame_number (struct usb_device *udev);
+extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
 
-extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
 		struct device *dev, char *bus_name);
 		struct device *dev, char *bus_name);
-extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
-extern void usb_put_hcd (struct usb_hcd *hcd);
+extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
+extern void usb_put_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
 extern int usb_add_hcd(struct usb_hcd *hcd,
 		unsigned int irqnum, unsigned long irqflags);
 		unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
 
 struct platform_device;
 struct platform_device;
-extern void usb_hcd_platform_shutdown(struct platform_device* dev);
+extern void usb_hcd_platform_shutdown(struct platform_device *dev);
 
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI
 struct pci_dev;
 struct pci_dev;
 struct pci_device_id;
 struct pci_device_id;
-extern int usb_hcd_pci_probe (struct pci_dev *dev,
+extern int usb_hcd_pci_probe(struct pci_dev *dev,
 				const struct pci_device_id *id);
 				const struct pci_device_id *id);
-extern void usb_hcd_pci_remove (struct pci_dev *dev);
+extern void usb_hcd_pci_remove(struct pci_dev *dev);
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
-extern int usb_hcd_pci_resume (struct pci_dev *dev);
+extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t state);
+extern int usb_hcd_pci_resume(struct pci_dev *dev);
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */
 
 
-extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
 
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_PCI */
 
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
-int hcd_buffer_create (struct usb_hcd *hcd);
-void hcd_buffer_destroy (struct usb_hcd *hcd);
+int hcd_buffer_create(struct usb_hcd *hcd);
+void hcd_buffer_destroy(struct usb_hcd *hcd);
 
 
-void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
+void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
 	gfp_t mem_flags, dma_addr_t *dma);
 	gfp_t mem_flags, dma_addr_t *dma);
-void hcd_buffer_free (struct usb_bus *bus, size_t size,
+void hcd_buffer_free(struct usb_bus *bus, size_t size,
 	void *addr, dma_addr_t dma);
 	void *addr, dma_addr_t dma);
 
 
 /* generic bus glue, needed for host controllers that don't use PCI */
 /* generic bus glue, needed for host controllers that don't use PCI */
-extern irqreturn_t usb_hcd_irq (int irq, void *__hcd);
+extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
 
 
-extern void usb_hc_died (struct usb_hcd *hcd);
+extern void usb_hc_died(struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
 extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
 
 
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
@@ -319,9 +323,9 @@ extern void usb_destroy_configuration(struct usb_device *dev);
  * Generic bandwidth allocation constants/support
  * Generic bandwidth allocation constants/support
  */
  */
 #define FRAME_TIME_USECS	1000L
 #define FRAME_TIME_USECS	1000L
-#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
+#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
 		/* Trying not to use worst-case bit-stuffing
 		/* Trying not to use worst-case bit-stuffing
-                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+		 * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
 		/* bytecount = data payload byte count */
 		/* bytecount = data payload byte count */
 
 
 #define NS_TO_US(ns)	((ns + 500L) / 1000L)
 #define NS_TO_US(ns)	((ns + 500L) / 1000L)
@@ -333,9 +337,9 @@ extern void usb_destroy_configuration(struct usb_device *dev);
  */
  */
 #define BW_HOST_DELAY	1000L		/* nanoseconds */
 #define BW_HOST_DELAY	1000L		/* nanoseconds */
 #define BW_HUB_LS_SETUP	333L		/* nanoseconds */
 #define BW_HUB_LS_SETUP	333L		/* nanoseconds */
-                        /* 4 full-speed bit times (est.) */
+			/* 4 full-speed bit times (est.) */
 
 
-#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
+#define FRAME_TIME_BITS			12000L	/* frame = 1 millisecond */
 #define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
 #define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
 #define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
 #define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
 
 
@@ -345,16 +349,16 @@ extern void usb_destroy_configuration(struct usb_device *dev);
  * to preallocate bandwidth)
  * to preallocate bandwidth)
  */
  */
 #define USB2_HOST_DELAY	5	/* nsec, guess */
 #define USB2_HOST_DELAY	5	/* nsec, guess */
-#define HS_NSECS(bytes) ( ((55 * 8 * 2083) \
+#define HS_NSECS(bytes) (((55 * 8 * 2083) \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ USB2_HOST_DELAY)
 	+ USB2_HOST_DELAY)
-#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
+#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ (2083UL * (3 + BitTime(bytes))))/1000 \
 	+ USB2_HOST_DELAY)
 	+ USB2_HOST_DELAY)
 #define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
 #define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes))
 #define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
 #define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes))
 
 
-extern long usb_calc_bus_time (int speed, int is_input,
+extern long usb_calc_bus_time(int speed, int is_input,
 			int isoc, int bytecount);
 			int isoc, int bytecount);
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -370,16 +374,16 @@ extern struct list_head usb_bus_list;
 extern struct mutex usb_bus_list_lock;
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 extern wait_queue_head_t usb_kill_urb_queue;
 
 
-extern void usb_enable_root_hub_irq (struct usb_bus *bus);
+extern void usb_enable_root_hub_irq(struct usb_bus *bus);
 
 
-extern int usb_find_interface_driver (struct usb_device *dev,
+extern int usb_find_interface_driver(struct usb_device *dev,
 	struct usb_interface *interface);
 	struct usb_interface *interface);
 
 
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
-extern void usb_root_hub_lost_power (struct usb_device *rhdev);
+extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
+extern void usb_root_hub_lost_power(struct usb_device *rhdev);
 extern int hcd_bus_suspend(struct usb_device *rhdev);
 extern int hcd_bus_suspend(struct usb_device *rhdev);
 extern int hcd_bus_resume(struct usb_device *rhdev);
 extern int hcd_bus_resume(struct usb_device *rhdev);
 #else
 #else
@@ -399,13 +403,13 @@ static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
  * these are expected to be called from the USB core/hub thread
  * these are expected to be called from the USB core/hub thread
  * with the kernel lock held
  * with the kernel lock held
  */
  */
-extern void usbfs_update_special (void);
+extern void usbfs_update_special(void);
 extern int usbfs_init(void);
 extern int usbfs_init(void);
 extern void usbfs_cleanup(void);
 extern void usbfs_cleanup(void);
 
 
 #else /* CONFIG_USB_DEVICEFS */
 #else /* CONFIG_USB_DEVICEFS */
 
 
-static inline void usbfs_update_special (void) {}
+static inline void usbfs_update_special(void) {}
 static inline int usbfs_init(void) { return 0; }
 static inline int usbfs_init(void) { return 0; }
 static inline void usbfs_cleanup(void) { }
 static inline void usbfs_cleanup(void) { }
 
 
@@ -460,7 +464,7 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
 /* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
-// bleech -- resurfaced in 2.4.11 or 2.4.12
+/* bleech -- resurfaced in 2.4.11 or 2.4.12 */
 #define bitmap 	DeviceRemovable
 #define bitmap 	DeviceRemovable
 
 
 
 
@@ -468,8 +472,8 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
 
 
 /* random stuff */
 /* random stuff */
 
 
-#define	RUN_CONTEXT (in_irq () ? "in_irq" \
-		: (in_interrupt () ? "in_interrupt" : "can sleep"))
+#define	RUN_CONTEXT (in_irq() ? "in_irq" \
+		: (in_interrupt() ? "in_interrupt" : "can sleep"))
 
 
 
 
 /* This rwsem is for use only by the hub driver and ehci-hcd.
 /* This rwsem is for use only by the hub driver and ehci-hcd.

+ 49 - 39
drivers/usb/core/hub.c

@@ -37,6 +37,13 @@
 #define	USB_PERSIST	0
 #define	USB_PERSIST	0
 #endif
 #endif
 
 
+/* if we are in debug mode, always announce new devices */
+#ifdef DEBUG
+#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
+#define CONFIG_USB_ANNOUNCE_NEW_DEVICES
+#endif
+#endif
+
 struct usb_hub {
 struct usb_hub {
 	struct device		*intfdev;	/* the "interface" device */
 	struct device		*intfdev;	/* the "interface" device */
 	struct usb_device	*hdev;
 	struct usb_device	*hdev;
@@ -487,6 +494,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
 	schedule_work (&tt->kevent);
 	schedule_work (&tt->kevent);
 	spin_unlock_irqrestore (&tt->lock, flags);
 	spin_unlock_irqrestore (&tt->lock, flags);
 }
 }
+EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
 
 
 static void hub_power_on(struct usb_hub *hub)
 static void hub_power_on(struct usb_hub *hub)
 {
 {
@@ -1027,8 +1035,10 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 		if (udev->children[i])
 		if (udev->children[i])
 			recursively_mark_NOTATTACHED(udev->children[i]);
 			recursively_mark_NOTATTACHED(udev->children[i]);
 	}
 	}
-	if (udev->state == USB_STATE_SUSPENDED)
+	if (udev->state == USB_STATE_SUSPENDED) {
 		udev->discon_suspended = 1;
 		udev->discon_suspended = 1;
+		udev->active_duration -= jiffies;
+	}
 	udev->state = USB_STATE_NOTATTACHED;
 	udev->state = USB_STATE_NOTATTACHED;
 }
 }
 
 
@@ -1077,6 +1087,12 @@ void usb_set_device_state(struct usb_device *udev,
 			else
 			else
 				device_init_wakeup(&udev->dev, 0);
 				device_init_wakeup(&udev->dev, 0);
 		}
 		}
+		if (udev->state == USB_STATE_SUSPENDED &&
+			new_state != USB_STATE_SUSPENDED)
+			udev->active_duration -= jiffies;
+		else if (new_state == USB_STATE_SUSPENDED &&
+				udev->state != USB_STATE_SUSPENDED)
+			udev->active_duration += jiffies;
 		udev->state = new_state;
 		udev->state = new_state;
 	} else
 	} else
 		recursively_mark_NOTATTACHED(udev);
 		recursively_mark_NOTATTACHED(udev);
@@ -1207,7 +1223,7 @@ void usb_disconnect(struct usb_device **pdev)
 	put_device(&udev->dev);
 	put_device(&udev->dev);
 }
 }
 
 
-#ifdef DEBUG
+#ifdef CONFIG_USB_ANNOUNCE_NEW_DEVICES
 static void show_string(struct usb_device *udev, char *id, char *string)
 static void show_string(struct usb_device *udev, char *id, char *string)
 {
 {
 	if (!string)
 	if (!string)
@@ -1215,12 +1231,24 @@ static void show_string(struct usb_device *udev, char *id, char *string)
 	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
 	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
 }
 }
 
 
+static void announce_device(struct usb_device *udev)
+{
+	dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n",
+		le16_to_cpu(udev->descriptor.idVendor),
+		le16_to_cpu(udev->descriptor.idProduct));
+	dev_info(&udev->dev, "New USB device strings: Mfr=%d, Product=%d, "
+		"SerialNumber=%d\n",
+		udev->descriptor.iManufacturer,
+		udev->descriptor.iProduct,
+		udev->descriptor.iSerialNumber);
+	show_string(udev, "Product", udev->product);
+	show_string(udev, "Manufacturer", udev->manufacturer);
+	show_string(udev, "SerialNumber", udev->serial);
+}
 #else
 #else
-static inline void show_string(struct usb_device *udev, char *id, char *string)
-{}
+static inline void announce_device(struct usb_device *udev) { }
 #endif
 #endif
 
 
-
 #ifdef	CONFIG_USB_OTG
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
 #include "otg_whitelist.h"
 #endif
 #endif
@@ -1390,14 +1418,7 @@ int usb_new_device(struct usb_device *udev)
 	}
 	}
 
 
 	/* Tell the world! */
 	/* Tell the world! */
-	dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
-		"SerialNumber=%d\n",
-		udev->descriptor.iManufacturer,
-		udev->descriptor.iProduct,
-		udev->descriptor.iSerialNumber);
-	show_string(udev, "Product", udev->product);
-	show_string(udev, "Manufacturer", udev->manufacturer);
-	show_string(udev, "SerialNumber", udev->serial);
+	announce_device(udev);
 	return err;
 	return err;
 
 
 fail:
 fail:
@@ -2482,6 +2503,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 {
 {
 	struct usb_device *hdev = hub->hdev;
 	struct usb_device *hdev = hub->hdev;
 	struct device *hub_dev = hub->intfdev;
 	struct device *hub_dev = hub->intfdev;
+	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
 	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 	int status, i;
 	int status, i;
  
  
@@ -2645,6 +2667,8 @@ loop:
  
  
 done:
 done:
 	hub_port_disable(hub, port1, 1);
 	hub_port_disable(hub, port1, 1);
+	if (hcd->driver->relinquish_port && !hub->hdev->parent)
+		hcd->driver->relinquish_port(hcd, port1);
 }
 }
 
 
 static void hub_events(void)
 static void hub_events(void)
@@ -2946,7 +2970,7 @@ static int config_descriptors_changed(struct usb_device *udev)
 		if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
 		if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
 			len = le16_to_cpu(udev->config[index].desc.wTotalLength);
 			len = le16_to_cpu(udev->config[index].desc.wTotalLength);
 	}
 	}
-	buf = kmalloc (len, GFP_KERNEL);
+	buf = kmalloc(len, GFP_NOIO);
 	if (buf == NULL) {
 	if (buf == NULL) {
 		dev_err(&udev->dev, "no mem to re-read configs after reset\n");
 		dev_err(&udev->dev, "no mem to re-read configs after reset\n");
 		/* assume the worst */
 		/* assume the worst */
@@ -3093,7 +3117,7 @@ re_enumerate:
 	hub_port_logical_disconnect(parent_hub, port1);
 	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 	return -ENODEV;
 }
 }
-EXPORT_SYMBOL(usb_reset_device);
+EXPORT_SYMBOL_GPL(usb_reset_device);
 
 
 /**
 /**
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
@@ -3110,16 +3134,12 @@ EXPORT_SYMBOL(usb_reset_device);
  * this from a driver probe() routine after downloading new firmware.
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
  * For calls that might not occur during probe(), drivers should lock
  * the device using usb_lock_device_for_reset().
  * the device using usb_lock_device_for_reset().
- *
- * The interface locks are acquired during the pre_reset stage and released
- * during the post_reset stage.  However if iface is not NULL and is
- * currently being probed, we assume that the caller already owns its
- * lock.
  */
  */
 int usb_reset_composite_device(struct usb_device *udev,
 int usb_reset_composite_device(struct usb_device *udev,
 		struct usb_interface *iface)
 		struct usb_interface *iface)
 {
 {
 	int ret;
 	int ret;
+	int i;
 	struct usb_host_config *config = udev->actconfig;
 	struct usb_host_config *config = udev->actconfig;
 
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
 	if (udev->state == USB_STATE_NOTATTACHED ||
@@ -3136,16 +3156,11 @@ int usb_reset_composite_device(struct usb_device *udev,
 		iface = NULL;
 		iface = NULL;
 
 
 	if (config) {
 	if (config) {
-		int i;
-		struct usb_interface *cintf;
-		struct usb_driver *drv;
-
 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
-			cintf = config->interface[i];
-			if (cintf != iface)
-				down(&cintf->dev.sem);
-			if (device_is_registered(&cintf->dev) &&
-					cintf->dev.driver) {
+			struct usb_interface *cintf = config->interface[i];
+			struct usb_driver *drv;
+
+			if (cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->pre_reset)
 				if (drv->pre_reset)
 					(drv->pre_reset)(cintf);
 					(drv->pre_reset)(cintf);
@@ -3157,25 +3172,20 @@ int usb_reset_composite_device(struct usb_device *udev,
 	ret = usb_reset_device(udev);
 	ret = usb_reset_device(udev);
 
 
 	if (config) {
 	if (config) {
-		int i;
-		struct usb_interface *cintf;
-		struct usb_driver *drv;
-
 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
-			cintf = config->interface[i];
-			if (device_is_registered(&cintf->dev) &&
-					cintf->dev.driver) {
+			struct usb_interface *cintf = config->interface[i];
+			struct usb_driver *drv;
+
+			if (cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->post_reset)
 				if (drv->post_reset)
 					(drv->post_reset)(cintf);
 					(drv->post_reset)(cintf);
 	/* FIXME: Unbind if post_reset returns an error or isn't defined */
 	/* FIXME: Unbind if post_reset returns an error or isn't defined */
 			}
 			}
-			if (cintf != iface)
-				up(&cintf->dev.sem);
 		}
 		}
 	}
 	}
 
 
 	usb_autosuspend_device(udev);
 	usb_autosuspend_device(udev);
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(usb_reset_composite_device);
+EXPORT_SYMBOL_GPL(usb_reset_composite_device);

+ 9 - 9
drivers/usb/core/hub.h

@@ -55,16 +55,16 @@
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_INDICATOR         22
 #define USB_PORT_FEAT_INDICATOR         22
 
 
-/* 
+/*
  * Hub Status and Hub Change results
  * Hub Status and Hub Change results
  * See USB 2.0 spec Table 11-19 and Table 11-20
  * See USB 2.0 spec Table 11-19 and Table 11-20
  */
  */
 struct usb_port_status {
 struct usb_port_status {
 	__le16 wPortStatus;
 	__le16 wPortStatus;
-	__le16 wPortChange;	
+	__le16 wPortChange;
 } __attribute__ ((packed));
 } __attribute__ ((packed));
 
 
-/* 
+/*
  * wPortStatus bit field
  * wPortStatus bit field
  * See USB 2.0 spec Table 11-21
  * See USB 2.0 spec Table 11-21
  */
  */
@@ -81,7 +81,7 @@ struct usb_port_status {
 #define USB_PORT_STAT_INDICATOR         0x1000
 #define USB_PORT_STAT_INDICATOR         0x1000
 /* bits 13 to 15 are reserved */
 /* bits 13 to 15 are reserved */
 
 
-/* 
+/*
  * wPortChange bit field
  * wPortChange bit field
  * See USB 2.0 spec Table 11-22
  * See USB 2.0 spec Table 11-22
  * Bits 0 to 4 shown, bits 5 to 15 are reserved
  * Bits 0 to 4 shown, bits 5 to 15 are reserved
@@ -93,7 +93,7 @@ struct usb_port_status {
 #define USB_PORT_STAT_C_RESET		0x0010
 #define USB_PORT_STAT_C_RESET		0x0010
 
 
 /*
 /*
- * wHubCharacteristics (masks) 
+ * wHubCharacteristics (masks)
  * See USB 2.0 spec Table 11-13, offset 3
  * See USB 2.0 spec Table 11-13, offset 3
  */
  */
 #define HUB_CHAR_LPSM		0x0003 /* D1 .. D0 */
 #define HUB_CHAR_LPSM		0x0003 /* D1 .. D0 */
@@ -119,8 +119,8 @@ struct usb_hub_status {
 #define HUB_CHANGE_OVERCURRENT	0x0002
 #define HUB_CHANGE_OVERCURRENT	0x0002
 
 
 
 
-/* 
- * Hub descriptor 
+/*
+ * Hub descriptor
  * See USB 2.0 spec Table 11-13
  * See USB 2.0 spec Table 11-13
  */
  */
 
 
@@ -134,7 +134,7 @@ struct usb_hub_descriptor {
 	__le16 wHubCharacteristics;
 	__le16 wHubCharacteristics;
 	__u8  bPwrOn2PwrGood;
 	__u8  bPwrOn2PwrGood;
 	__u8  bHubContrCurrent;
 	__u8  bHubContrCurrent;
-	    	/* add 1 bit for hub status change; round to bytes */
+		/* add 1 bit for hub status change; round to bytes */
 	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
 	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
 	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
 	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
 } __attribute__ ((packed));
 } __attribute__ ((packed));
@@ -190,6 +190,6 @@ struct usb_tt_clear {
 	u16			devinfo;
 	u16			devinfo;
 };
 };
 
 
-extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
+extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
 
 
 #endif /* __LINUX_HUB_H */
 #endif /* __LINUX_HUB_H */

+ 36 - 6
drivers/usb/core/inode.c

@@ -38,10 +38,15 @@
 #include <linux/usbdevice_fs.h>
 #include <linux/usbdevice_fs.h>
 #include <linux/parser.h>
 #include <linux/parser.h>
 #include <linux/notifier.h>
 #include <linux/notifier.h>
+#include <linux/seq_file.h>
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include "usb.h"
 #include "usb.h"
 #include "hcd.h"
 #include "hcd.h"
 
 
+#define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO)
+#define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO)
+#define USBFS_DEFAULT_LISTMODE S_IRUGO
+
 static struct super_operations usbfs_ops;
 static struct super_operations usbfs_ops;
 static const struct file_operations default_file_operations;
 static const struct file_operations default_file_operations;
 static struct vfsmount *usbfs_mount;
 static struct vfsmount *usbfs_mount;
@@ -57,9 +62,33 @@ static uid_t listuid;	/* = 0 */
 static gid_t devgid;	/* = 0 */
 static gid_t devgid;	/* = 0 */
 static gid_t busgid;	/* = 0 */
 static gid_t busgid;	/* = 0 */
 static gid_t listgid;	/* = 0 */
 static gid_t listgid;	/* = 0 */
-static umode_t devmode = S_IWUSR | S_IRUGO;
-static umode_t busmode = S_IXUGO | S_IRUGO;
-static umode_t listmode = S_IRUGO;
+static umode_t devmode = USBFS_DEFAULT_DEVMODE;
+static umode_t busmode = USBFS_DEFAULT_BUSMODE;
+static umode_t listmode = USBFS_DEFAULT_LISTMODE;
+
+static int usbfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+	if (devuid != 0)
+		seq_printf(seq, ",devuid=%u", devuid);
+	if (devgid != 0)
+		seq_printf(seq, ",devgid=%u", devgid);
+	if (devmode != USBFS_DEFAULT_DEVMODE)
+		seq_printf(seq, ",devmode=%o", devmode);
+	if (busuid != 0)
+		seq_printf(seq, ",busuid=%u", busuid);
+	if (busgid != 0)
+		seq_printf(seq, ",busgid=%u", busgid);
+	if (busmode != USBFS_DEFAULT_BUSMODE)
+		seq_printf(seq, ",busmode=%o", busmode);
+	if (listuid != 0)
+		seq_printf(seq, ",listuid=%u", listuid);
+	if (listgid != 0)
+		seq_printf(seq, ",listgid=%u", listgid);
+	if (listmode != USBFS_DEFAULT_LISTMODE)
+		seq_printf(seq, ",listmode=%o", listmode);
+
+	return 0;
+}
 
 
 enum {
 enum {
 	Opt_devuid, Opt_devgid, Opt_devmode,
 	Opt_devuid, Opt_devgid, Opt_devmode,
@@ -93,9 +122,9 @@ static int parse_options(struct super_block *s, char *data)
 	devgid = 0;
 	devgid = 0;
 	busgid = 0;
 	busgid = 0;
 	listgid = 0;
 	listgid = 0;
-	devmode = S_IWUSR | S_IRUGO;
-	busmode = S_IXUGO | S_IRUGO;
-	listmode = S_IRUGO;
+	devmode = USBFS_DEFAULT_DEVMODE;
+	busmode = USBFS_DEFAULT_BUSMODE;
+	listmode = USBFS_DEFAULT_LISTMODE;
 
 
 	while ((p = strsep(&data, ",")) != NULL) {
 	while ((p = strsep(&data, ",")) != NULL) {
 		substring_t args[MAX_OPT_ARGS];
 		substring_t args[MAX_OPT_ARGS];
@@ -418,6 +447,7 @@ static struct super_operations usbfs_ops = {
 	.statfs =	simple_statfs,
 	.statfs =	simple_statfs,
 	.drop_inode =	generic_delete_inode,
 	.drop_inode =	generic_delete_inode,
 	.remount_fs =	remount,
 	.remount_fs =	remount,
+	.show_options = usbfs_show_options,
 };
 };
 
 
 static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
 static int usbfs_fill_super(struct super_block *sb, void *data, int silent)

+ 215 - 215
drivers/usb/core/message.c

@@ -39,7 +39,7 @@ static void usb_api_blocking_completion(struct urb *urb)
  * own interruptible routines.
  * own interruptible routines.
  */
  */
 static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
-{ 
+{
 	struct api_context ctx;
 	struct api_context ctx;
 	unsigned long expire;
 	unsigned long expire;
 	int retval;
 	int retval;
@@ -74,9 +74,9 @@ out:
 }
 }
 
 
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
+/* returns status (negative) or length (positive) */
 static int usb_internal_control_msg(struct usb_device *usb_dev,
 static int usb_internal_control_msg(struct usb_device *usb_dev,
-				    unsigned int pipe, 
+				    unsigned int pipe,
 				    struct usb_ctrlrequest *cmd,
 				    struct usb_ctrlrequest *cmd,
 				    void *data, int len, int timeout)
 				    void *data, int len, int timeout)
 {
 {
@@ -87,7 +87,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
 	urb = usb_alloc_urb(0, GFP_NOIO);
 	urb = usb_alloc_urb(0, GFP_NOIO);
 	if (!urb)
 	if (!urb)
 		return -ENOMEM;
 		return -ENOMEM;
-  
+
 	usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
 	usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
 			     len, usb_api_blocking_completion, NULL);
 			     len, usb_api_blocking_completion, NULL);
 
 
@@ -99,47 +99,51 @@ static int usb_internal_control_msg(struct usb_device *usb_dev,
 }
 }
 
 
 /**
 /**
- *	usb_control_msg - Builds a control urb, sends it off and waits for completion
- *	@dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@request: USB message request value
- *	@requesttype: USB message request type value
- *	@value: USB message value
- *	@index: USB message index value
- *	@data: pointer to the data to send
- *	@size: length in bytes of the data to send
- *	@timeout: time in msecs to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
- *
- *	This function sends a simple control message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns the number of bytes transferred, otherwise a negative error number.
- *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to send
- *	a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
+ * usb_control_msg - Builds a control urb, sends it off and waits for completion
+ * @dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @request: USB message request value
+ * @requesttype: USB message request type value
+ * @value: USB message value
+ * @index: USB message index value
+ * @data: pointer to the data to send
+ * @size: length in bytes of the data to send
+ * @timeout: time in msecs to wait for the message to complete before timing
+ *	out (if 0 the wait is forever)
+ *
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple control message to a specified endpoint and
+ * waits for the message to complete, or timeout.
+ *
+ * If successful, it returns the number of bytes transferred, otherwise a
+ * negative error number.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb().
+ * If a thread in your driver uses this call, make sure your disconnect()
+ * method can wait for it to complete.  Since you don't have a handle on the
+ * URB used, you can't cancel the request.
  */
  */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
+		    __u8 requesttype, __u16 value, __u16 index, void *data,
+		    __u16 size, int timeout)
 {
 {
-	struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+	struct usb_ctrlrequest *dr;
 	int ret;
 	int ret;
-	
+
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
 	if (!dr)
 	if (!dr)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	dr->bRequestType= requesttype;
+	dr->bRequestType = requesttype;
 	dr->bRequest = request;
 	dr->bRequest = request;
 	dr->wValue = cpu_to_le16p(&value);
 	dr->wValue = cpu_to_le16p(&value);
 	dr->wIndex = cpu_to_le16p(&index);
 	dr->wIndex = cpu_to_le16p(&index);
 	dr->wLength = cpu_to_le16p(&size);
 	dr->wLength = cpu_to_le16p(&size);
 
 
-	//dbg("usb_control_msg");	
+	/* dbg("usb_control_msg"); */
 
 
 	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
 	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
 
 
@@ -147,7 +151,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 
 
 	return ret;
 	return ret;
 }
 }
-
+EXPORT_SYMBOL_GPL(usb_control_msg);
 
 
 /**
 /**
  * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
  * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
@@ -155,9 +159,11 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
  * @pipe: endpoint "pipe" to send the message to
  * @pipe: endpoint "pipe" to send the message to
  * @data: pointer to the data to send
  * @data: pointer to the data to send
  * @len: length in bytes of the data to send
  * @len: length in bytes of the data to send
- * @actual_length: pointer to a location to put the actual length transferred in bytes
+ * @actual_length: pointer to a location to put the actual length transferred
+ *	in bytes
  * @timeout: time in msecs to wait for the message to complete before
  * @timeout: time in msecs to wait for the message to complete before
  *	timing out (if 0 the wait is forever)
  *	timing out (if 0 the wait is forever)
+ *
  * Context: !in_interrupt ()
  * Context: !in_interrupt ()
  *
  *
  * This function sends a simple interrupt message to a specified endpoint and
  * This function sends a simple interrupt message to a specified endpoint and
@@ -181,38 +187,38 @@ int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
 EXPORT_SYMBOL_GPL(usb_interrupt_msg);
 EXPORT_SYMBOL_GPL(usb_interrupt_msg);
 
 
 /**
 /**
- *	usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- *	@usb_dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@data: pointer to the data to send
- *	@len: length in bytes of the data to send
- *	@actual_length: pointer to a location to put the actual length transferred in bytes
- *	@timeout: time in msecs to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
- *
- *	This function sends a simple bulk message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns 0, otherwise a negative error number.
- *	The number of actual bytes transferred will be stored in the 
- *	actual_length paramater.
- *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to
- *	send a message from within interrupt context, use usb_submit_urb()
- *      If a thread in your driver uses this call, make sure your disconnect()
- *      method can wait for it to complete.  Since you don't have a handle on
- *      the URB used, you can't cancel the request.
- *
- *	Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
- *	ioctl, users are forced to abuse this routine by using it to submit
- *	URBs for interrupt endpoints.  We will take the liberty of creating
- *	an interrupt URB (with the default interval) if the target is an
- *	interrupt endpoint.
+ * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred
+ *	in bytes
+ * @timeout: time in msecs to wait for the message to complete before
+ *	timing out (if 0 the wait is forever)
+ *
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple bulk message to a specified endpoint
+ * and waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.  The number
+ * of actual bytes transferred will be stored in the actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb() If a thread in your
+ * driver uses this call, make sure your disconnect() method can wait for it to
+ * complete.  Since you don't have a handle on the URB used, you can't cancel
+ * the request.
+ *
+ * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
+ * users are forced to abuse this routine by using it to submit URBs for
+ * interrupt endpoints.  We will take the liberty of creating an interrupt URB
+ * (with the default interval) if the target is an interrupt endpoint.
  */
  */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
-			void *data, int len, int *actual_length, int timeout)
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+		 void *data, int len, int *actual_length, int timeout)
 {
 {
 	struct urb *urb;
 	struct urb *urb;
 	struct usb_host_endpoint *ep;
 	struct usb_host_endpoint *ep;
@@ -238,29 +244,30 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 
 
 	return usb_start_wait_urb(urb, timeout, actual_length);
 	return usb_start_wait_urb(urb, timeout, actual_length);
 }
 }
+EXPORT_SYMBOL_GPL(usb_bulk_msg);
 
 
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
 
 
-static void sg_clean (struct usb_sg_request *io)
+static void sg_clean(struct usb_sg_request *io)
 {
 {
 	if (io->urbs) {
 	if (io->urbs) {
 		while (io->entries--)
 		while (io->entries--)
-			usb_free_urb (io->urbs [io->entries]);
-		kfree (io->urbs);
+			usb_free_urb(io->urbs [io->entries]);
+		kfree(io->urbs);
 		io->urbs = NULL;
 		io->urbs = NULL;
 	}
 	}
 	if (io->dev->dev.dma_mask != NULL)
 	if (io->dev->dev.dma_mask != NULL)
-		usb_buffer_unmap_sg (io->dev, usb_pipein(io->pipe),
-				io->sg, io->nents);
+		usb_buffer_unmap_sg(io->dev, usb_pipein(io->pipe),
+				    io->sg, io->nents);
 	io->dev = NULL;
 	io->dev = NULL;
 }
 }
 
 
-static void sg_complete (struct urb *urb)
+static void sg_complete(struct urb *urb)
 {
 {
-	struct usb_sg_request	*io = urb->context;
+	struct usb_sg_request *io = urb->context;
 	int status = urb->status;
 	int status = urb->status;
 
 
-	spin_lock (&io->lock);
+	spin_lock(&io->lock);
 
 
 	/* In 2.5 we require hcds' endpoint queues not to progress after fault
 	/* In 2.5 we require hcds' endpoint queues not to progress after fault
 	 * reports, until the completion callback (this!) returns.  That lets
 	 * reports, until the completion callback (this!) returns.  That lets
@@ -276,13 +283,13 @@ static void sg_complete (struct urb *urb)
 			&& (io->status != -ECONNRESET
 			&& (io->status != -ECONNRESET
 				|| status != -ECONNRESET)
 				|| status != -ECONNRESET)
 			&& urb->actual_length) {
 			&& urb->actual_length) {
-		dev_err (io->dev->bus->controller,
+		dev_err(io->dev->bus->controller,
 			"dev %s ep%d%s scatterlist error %d/%d\n",
 			"dev %s ep%d%s scatterlist error %d/%d\n",
 			io->dev->devpath,
 			io->dev->devpath,
 			usb_endpoint_num(&urb->ep->desc),
 			usb_endpoint_num(&urb->ep->desc),
 			usb_urb_dir_in(urb) ? "in" : "out",
 			usb_urb_dir_in(urb) ? "in" : "out",
 			status, io->status);
 			status, io->status);
-		// BUG ();
+		/* BUG (); */
 	}
 	}
 
 
 	if (io->status == 0 && status && status != -ECONNRESET) {
 	if (io->status == 0 && status && status != -ECONNRESET) {
@@ -294,22 +301,22 @@ static void sg_complete (struct urb *urb)
 		 * unlink pending urbs so they won't rx/tx bad data.
 		 * unlink pending urbs so they won't rx/tx bad data.
 		 * careful: unlink can sometimes be synchronous...
 		 * careful: unlink can sometimes be synchronous...
 		 */
 		 */
-		spin_unlock (&io->lock);
+		spin_unlock(&io->lock);
 		for (i = 0, found = 0; i < io->entries; i++) {
 		for (i = 0, found = 0; i < io->entries; i++) {
 			if (!io->urbs [i] || !io->urbs [i]->dev)
 			if (!io->urbs [i] || !io->urbs [i]->dev)
 				continue;
 				continue;
 			if (found) {
 			if (found) {
-				retval = usb_unlink_urb (io->urbs [i]);
+				retval = usb_unlink_urb(io->urbs [i]);
 				if (retval != -EINPROGRESS &&
 				if (retval != -EINPROGRESS &&
 				    retval != -ENODEV &&
 				    retval != -ENODEV &&
 				    retval != -EBUSY)
 				    retval != -EBUSY)
-					dev_err (&io->dev->dev,
+					dev_err(&io->dev->dev,
 						"%s, unlink --> %d\n",
 						"%s, unlink --> %d\n",
 						__FUNCTION__, retval);
 						__FUNCTION__, retval);
 			} else if (urb == io->urbs [i])
 			} else if (urb == io->urbs [i])
 				found = 1;
 				found = 1;
 		}
 		}
-		spin_lock (&io->lock);
+		spin_lock(&io->lock);
 	}
 	}
 	urb->dev = NULL;
 	urb->dev = NULL;
 
 
@@ -317,9 +324,9 @@ static void sg_complete (struct urb *urb)
 	io->bytes += urb->actual_length;
 	io->bytes += urb->actual_length;
 	io->count--;
 	io->count--;
 	if (!io->count)
 	if (!io->count)
-		complete (&io->complete);
+		complete(&io->complete);
 
 
-	spin_unlock (&io->lock);
+	spin_unlock(&io->lock);
 }
 }
 
 
 
 
@@ -348,28 +355,21 @@ static void sg_complete (struct urb *urb)
  * The request may be canceled with usb_sg_cancel(), either before or after
  * The request may be canceled with usb_sg_cancel(), either before or after
  * usb_sg_wait() is called.
  * usb_sg_wait() is called.
  */
  */
-int usb_sg_init (
-	struct usb_sg_request	*io,
-	struct usb_device	*dev,
-	unsigned		pipe, 
-	unsigned		period,
-	struct scatterlist	*sg,
-	int			nents,
-	size_t			length,
-	gfp_t			mem_flags
-)
+int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
+		unsigned pipe, unsigned	period, struct scatterlist *sg,
+		int nents, size_t length, gfp_t mem_flags)
 {
 {
-	int			i;
-	int			urb_flags;
-	int			dma;
+	int i;
+	int urb_flags;
+	int dma;
 
 
 	if (!io || !dev || !sg
 	if (!io || !dev || !sg
-			|| usb_pipecontrol (pipe)
-			|| usb_pipeisoc (pipe)
+			|| usb_pipecontrol(pipe)
+			|| usb_pipeisoc(pipe)
 			|| nents <= 0)
 			|| nents <= 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	spin_lock_init (&io->lock);
+	spin_lock_init(&io->lock);
 	io->dev = dev;
 	io->dev = dev;
 	io->pipe = pipe;
 	io->pipe = pipe;
 	io->sg = sg;
 	io->sg = sg;
@@ -381,7 +381,7 @@ int usb_sg_init (
 	dma = (dev->dev.dma_mask != NULL);
 	dma = (dev->dev.dma_mask != NULL);
 	if (dma)
 	if (dma)
 		io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
 		io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
-				sg, nents);
+						sg, nents);
 	else
 	else
 		io->entries = nents;
 		io->entries = nents;
 
 
@@ -390,30 +390,30 @@ int usb_sg_init (
 		return io->entries;
 		return io->entries;
 
 
 	io->count = io->entries;
 	io->count = io->entries;
-	io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
+	io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags);
 	if (!io->urbs)
 	if (!io->urbs)
 		goto nomem;
 		goto nomem;
 
 
 	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
 	urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
-	if (usb_pipein (pipe))
+	if (usb_pipein(pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 		urb_flags |= URB_SHORT_NOT_OK;
 
 
 	for (i = 0; i < io->entries; i++) {
 	for (i = 0; i < io->entries; i++) {
-		unsigned		len;
+		unsigned len;
 
 
-		io->urbs [i] = usb_alloc_urb (0, mem_flags);
-		if (!io->urbs [i]) {
+		io->urbs[i] = usb_alloc_urb(0, mem_flags);
+		if (!io->urbs[i]) {
 			io->entries = i;
 			io->entries = i;
 			goto nomem;
 			goto nomem;
 		}
 		}
 
 
-		io->urbs [i]->dev = NULL;
-		io->urbs [i]->pipe = pipe;
-		io->urbs [i]->interval = period;
-		io->urbs [i]->transfer_flags = urb_flags;
+		io->urbs[i]->dev = NULL;
+		io->urbs[i]->pipe = pipe;
+		io->urbs[i]->interval = period;
+		io->urbs[i]->transfer_flags = urb_flags;
 
 
-		io->urbs [i]->complete = sg_complete;
-		io->urbs [i]->context = io;
+		io->urbs[i]->complete = sg_complete;
+		io->urbs[i]->context = io;
 
 
 		/*
 		/*
 		 * Some systems need to revert to PIO when DMA is temporarily
 		 * Some systems need to revert to PIO when DMA is temporarily
@@ -432,8 +432,8 @@ int usb_sg_init (
 		 * to prevent stale pointers and to help spot bugs.
 		 * to prevent stale pointers and to help spot bugs.
 		 */
 		 */
 		if (dma) {
 		if (dma) {
-			io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
-			len = sg_dma_len (sg + i);
+			io->urbs[i]->transfer_dma = sg_dma_address(sg + i);
+			len = sg_dma_len(sg + i);
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
 			io->urbs[i]->transfer_buffer = NULL;
 			io->urbs[i]->transfer_buffer = NULL;
 #else
 #else
@@ -441,31 +441,31 @@ int usb_sg_init (
 #endif
 #endif
 		} else {
 		} else {
 			/* hc may use _only_ transfer_buffer */
 			/* hc may use _only_ transfer_buffer */
-			io->urbs [i]->transfer_buffer = sg_virt(&sg[i]);
-			len = sg [i].length;
+			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
+			len = sg[i].length;
 		}
 		}
 
 
 		if (length) {
 		if (length) {
-			len = min_t (unsigned, len, length);
+			len = min_t(unsigned, len, length);
 			length -= len;
 			length -= len;
 			if (length == 0)
 			if (length == 0)
 				io->entries = i + 1;
 				io->entries = i + 1;
 		}
 		}
-		io->urbs [i]->transfer_buffer_length = len;
+		io->urbs[i]->transfer_buffer_length = len;
 	}
 	}
-	io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT;
+	io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
 
 
 	/* transaction state */
 	/* transaction state */
 	io->status = 0;
 	io->status = 0;
 	io->bytes = 0;
 	io->bytes = 0;
-	init_completion (&io->complete);
+	init_completion(&io->complete);
 	return 0;
 	return 0;
 
 
 nomem:
 nomem:
-	sg_clean (io);
+	sg_clean(io);
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
-
+EXPORT_SYMBOL_GPL(usb_sg_init);
 
 
 /**
 /**
  * usb_sg_wait - synchronously execute scatter/gather request
  * usb_sg_wait - synchronously execute scatter/gather request
@@ -506,31 +506,32 @@ nomem:
  * speed interrupt endpoints, which allow at most one packet per millisecond,
  * speed interrupt endpoints, which allow at most one packet per millisecond,
  * of at most 8 or 64 bytes (respectively).
  * of at most 8 or 64 bytes (respectively).
  */
  */
-void usb_sg_wait (struct usb_sg_request *io)
+void usb_sg_wait(struct usb_sg_request *io)
 {
 {
-	int		i, entries = io->entries;
+	int i;
+	int entries = io->entries;
 
 
 	/* queue the urbs.  */
 	/* queue the urbs.  */
-	spin_lock_irq (&io->lock);
+	spin_lock_irq(&io->lock);
 	i = 0;
 	i = 0;
 	while (i < entries && !io->status) {
 	while (i < entries && !io->status) {
-		int	retval;
+		int retval;
 
 
-		io->urbs [i]->dev = io->dev;
-		retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC);
+		io->urbs[i]->dev = io->dev;
+		retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC);
 
 
 		/* after we submit, let completions or cancelations fire;
 		/* after we submit, let completions or cancelations fire;
 		 * we handshake using io->status.
 		 * we handshake using io->status.
 		 */
 		 */
-		spin_unlock_irq (&io->lock);
+		spin_unlock_irq(&io->lock);
 		switch (retval) {
 		switch (retval) {
 			/* maybe we retrying will recover */
 			/* maybe we retrying will recover */
-		case -ENXIO:	// hc didn't queue this one
+		case -ENXIO:	/* hc didn't queue this one */
 		case -EAGAIN:
 		case -EAGAIN:
 		case -ENOMEM:
 		case -ENOMEM:
 			io->urbs[i]->dev = NULL;
 			io->urbs[i]->dev = NULL;
 			retval = 0;
 			retval = 0;
-			yield ();
+			yield();
 			break;
 			break;
 
 
 			/* no error? continue immediately.
 			/* no error? continue immediately.
@@ -541,34 +542,35 @@ void usb_sg_wait (struct usb_sg_request *io)
 			 */
 			 */
 		case 0:
 		case 0:
 			++i;
 			++i;
-			cpu_relax ();
+			cpu_relax();
 			break;
 			break;
 
 
 			/* fail any uncompleted urbs */
 			/* fail any uncompleted urbs */
 		default:
 		default:
-			io->urbs [i]->dev = NULL;
-			io->urbs [i]->status = retval;
-			dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
+			io->urbs[i]->dev = NULL;
+			io->urbs[i]->status = retval;
+			dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
 				__FUNCTION__, retval);
 				__FUNCTION__, retval);
-			usb_sg_cancel (io);
+			usb_sg_cancel(io);
 		}
 		}
-		spin_lock_irq (&io->lock);
+		spin_lock_irq(&io->lock);
 		if (retval && (io->status == 0 || io->status == -ECONNRESET))
 		if (retval && (io->status == 0 || io->status == -ECONNRESET))
 			io->status = retval;
 			io->status = retval;
 	}
 	}
 	io->count -= entries - i;
 	io->count -= entries - i;
 	if (io->count == 0)
 	if (io->count == 0)
-		complete (&io->complete);
-	spin_unlock_irq (&io->lock);
+		complete(&io->complete);
+	spin_unlock_irq(&io->lock);
 
 
 	/* OK, yes, this could be packaged as non-blocking.
 	/* OK, yes, this could be packaged as non-blocking.
 	 * So could the submit loop above ... but it's easier to
 	 * So could the submit loop above ... but it's easier to
 	 * solve neither problem than to solve both!
 	 * solve neither problem than to solve both!
 	 */
 	 */
-	wait_for_completion (&io->complete);
+	wait_for_completion(&io->complete);
 
 
-	sg_clean (io);
+	sg_clean(io);
 }
 }
+EXPORT_SYMBOL_GPL(usb_sg_wait);
 
 
 /**
 /**
  * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
  * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
@@ -578,32 +580,33 @@ void usb_sg_wait (struct usb_sg_request *io)
  * It can also prevents one initialized by usb_sg_init() from starting,
  * It can also prevents one initialized by usb_sg_init() from starting,
  * so that call just frees resources allocated to the request.
  * so that call just frees resources allocated to the request.
  */
  */
-void usb_sg_cancel (struct usb_sg_request *io)
+void usb_sg_cancel(struct usb_sg_request *io)
 {
 {
-	unsigned long	flags;
+	unsigned long flags;
 
 
-	spin_lock_irqsave (&io->lock, flags);
+	spin_lock_irqsave(&io->lock, flags);
 
 
 	/* shut everything down, if it didn't already */
 	/* shut everything down, if it didn't already */
 	if (!io->status) {
 	if (!io->status) {
-		int	i;
+		int i;
 
 
 		io->status = -ECONNRESET;
 		io->status = -ECONNRESET;
-		spin_unlock (&io->lock);
+		spin_unlock(&io->lock);
 		for (i = 0; i < io->entries; i++) {
 		for (i = 0; i < io->entries; i++) {
-			int	retval;
+			int retval;
 
 
 			if (!io->urbs [i]->dev)
 			if (!io->urbs [i]->dev)
 				continue;
 				continue;
-			retval = usb_unlink_urb (io->urbs [i]);
+			retval = usb_unlink_urb(io->urbs [i]);
 			if (retval != -EINPROGRESS && retval != -EBUSY)
 			if (retval != -EINPROGRESS && retval != -EBUSY)
-				dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
+				dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
 					__FUNCTION__, retval);
 					__FUNCTION__, retval);
 		}
 		}
-		spin_lock (&io->lock);
+		spin_lock(&io->lock);
 	}
 	}
-	spin_unlock_irqrestore (&io->lock, flags);
+	spin_unlock_irqrestore(&io->lock, flags);
 }
 }
+EXPORT_SYMBOL_GPL(usb_sg_cancel);
 
 
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
 
 
@@ -629,12 +632,13 @@ void usb_sg_cancel (struct usb_sg_request *io)
  * Returns the number of bytes received on success, or else the status code
  * Returns the number of bytes received on success, or else the status code
  * returned by the underlying usb_control_msg() call.
  * returned by the underlying usb_control_msg() call.
  */
  */
-int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+int usb_get_descriptor(struct usb_device *dev, unsigned char type,
+		       unsigned char index, void *buf, int size)
 {
 {
 	int i;
 	int i;
 	int result;
 	int result;
-	
-	memset(buf,0,size);	// Make sure we parse really received data
+
+	memset(buf, 0, size);	/* Make sure we parse really received data */
 
 
 	for (i = 0; i < 3; ++i) {
 	for (i = 0; i < 3; ++i) {
 		/* retry on length 0 or error; some devices are flakey */
 		/* retry on length 0 or error; some devices are flakey */
@@ -652,6 +656,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
 	}
 	}
 	return result;
 	return result;
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_descriptor);
 
 
 /**
 /**
  * usb_get_string - gets a string descriptor
  * usb_get_string - gets a string descriptor
@@ -708,7 +713,7 @@ static void usb_try_string_workarounds(unsigned char *buf, int *length)
 }
 }
 
 
 static int usb_string_sub(struct usb_device *dev, unsigned int langid,
 static int usb_string_sub(struct usb_device *dev, unsigned int langid,
-		unsigned int index, unsigned char *buf)
+			  unsigned int index, unsigned char *buf)
 {
 {
 	int rc;
 	int rc;
 
 
@@ -751,7 +756,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
  * @buf: where to put the string
  * @buf: where to put the string
  * @size: how big is "buf"?
  * @size: how big is "buf"?
  * Context: !in_interrupt ()
  * Context: !in_interrupt ()
- * 
+ *
  * This converts the UTF-16LE encoded strings returned by devices, from
  * This converts the UTF-16LE encoded strings returned by devices, from
  * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
  * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
  * that are more usable in most kernel contexts.  Note that all characters
  * that are more usable in most kernel contexts.  Note that all characters
@@ -787,23 +792,23 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 	if (!dev->have_langid) {
 	if (!dev->have_langid) {
 		err = usb_string_sub(dev, 0, 0, tbuf);
 		err = usb_string_sub(dev, 0, 0, tbuf);
 		if (err < 0) {
 		if (err < 0) {
-			dev_err (&dev->dev,
+			dev_err(&dev->dev,
 				"string descriptor 0 read error: %d\n",
 				"string descriptor 0 read error: %d\n",
 				err);
 				err);
 			goto errout;
 			goto errout;
 		} else if (err < 4) {
 		} else if (err < 4) {
-			dev_err (&dev->dev, "string descriptor 0 too short\n");
+			dev_err(&dev->dev, "string descriptor 0 too short\n");
 			err = -EINVAL;
 			err = -EINVAL;
 			goto errout;
 			goto errout;
 		} else {
 		} else {
 			dev->have_langid = 1;
 			dev->have_langid = 1;
-			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
-				/* always use the first langid listed */
-			dev_dbg (&dev->dev, "default language 0x%04x\n",
+			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+			/* always use the first langid listed */
+			dev_dbg(&dev->dev, "default language 0x%04x\n",
 				dev->string_langid);
 				dev->string_langid);
 		}
 		}
 	}
 	}
-	
+
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
 	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
 	if (err < 0)
 	if (err < 0)
 		goto errout;
 		goto errout;
@@ -821,12 +826,15 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 	err = idx;
 	err = idx;
 
 
 	if (tbuf[1] != USB_DT_STRING)
 	if (tbuf[1] != USB_DT_STRING)
-		dev_dbg(&dev->dev, "wrong descriptor type %02x for string %d (\"%s\")\n", tbuf[1], index, buf);
+		dev_dbg(&dev->dev,
+			"wrong descriptor type %02x for string %d (\"%s\")\n",
+			tbuf[1], index, buf);
 
 
  errout:
  errout:
 	kfree(tbuf);
 	kfree(tbuf);
 	return err;
 	return err;
 }
 }
+EXPORT_SYMBOL_GPL(usb_string);
 
 
 /**
 /**
  * usb_cache_string - read a string descriptor and cache it for later use
  * usb_cache_string - read a string descriptor and cache it for later use
@@ -842,9 +850,15 @@ char *usb_cache_string(struct usb_device *udev, int index)
 	char *smallbuf = NULL;
 	char *smallbuf = NULL;
 	int len;
 	int len;
 
 
-	if (index > 0 && (buf = kmalloc(256, GFP_KERNEL)) != NULL) {
-		if ((len = usb_string(udev, index, buf, 256)) > 0) {
-			if ((smallbuf = kmalloc(++len, GFP_KERNEL)) == NULL)
+	if (index <= 0)
+		return NULL;
+
+	buf = kmalloc(256, GFP_KERNEL);
+	if (buf) {
+		len = usb_string(udev, index, buf, 256);
+		if (len > 0) {
+			smallbuf = kmalloc(++len, GFP_KERNEL);
+			if (!smallbuf)
 				return buf;
 				return buf;
 			memcpy(smallbuf, buf, len);
 			memcpy(smallbuf, buf, len);
 		}
 		}
@@ -883,7 +897,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
 	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
-	if (ret >= 0) 
+	if (ret >= 0)
 		memcpy(&dev->descriptor, desc, size);
 		memcpy(&dev->descriptor, desc, size);
 	kfree(desc);
 	kfree(desc);
 	return ret;
 	return ret;
@@ -927,6 +941,7 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 	kfree(status);
 	kfree(status);
 	return ret;
 	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_status);
 
 
 /**
 /**
  * usb_clear_halt - tells device to clear endpoint halt/stall condition
  * usb_clear_halt - tells device to clear endpoint halt/stall condition
@@ -955,8 +970,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
 {
 {
 	int result;
 	int result;
 	int endp = usb_pipeendpoint(pipe);
 	int endp = usb_pipeendpoint(pipe);
-	
-	if (usb_pipein (pipe))
+
+	if (usb_pipein(pipe))
 		endp |= USB_DIR_IN;
 		endp |= USB_DIR_IN;
 
 
 	/* we don't care if it wasn't halted first. in fact some devices
 	/* we don't care if it wasn't halted first. in fact some devices
@@ -985,6 +1000,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(usb_clear_halt);
 
 
 /**
 /**
  * usb_disable_endpoint -- Disable an endpoint by address
  * usb_disable_endpoint -- Disable an endpoint by address
@@ -1038,7 +1054,7 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
 	}
 	}
 }
 }
 
 
-/*
+/**
  * usb_disable_device - Disable all the endpoints for a USB device
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
  * @dev: the device whose endpoints are being disabled
  * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
  * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
@@ -1053,7 +1069,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 	int i;
 	int i;
 
 
 	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
 	dev_dbg(&dev->dev, "%s nuking %s URBs\n", __FUNCTION__,
-			skip_ep0 ? "non-ep0" : "all");
+		skip_ep0 ? "non-ep0" : "all");
 	for (i = skip_ep0; i < 16; ++i) {
 	for (i = skip_ep0; i < 16; ++i) {
 		usb_disable_endpoint(dev, i);
 		usb_disable_endpoint(dev, i);
 		usb_disable_endpoint(dev, i + USB_DIR_IN);
 		usb_disable_endpoint(dev, i + USB_DIR_IN);
@@ -1071,17 +1087,17 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 			interface = dev->actconfig->interface[i];
 			interface = dev->actconfig->interface[i];
 			if (!device_is_registered(&interface->dev))
 			if (!device_is_registered(&interface->dev))
 				continue;
 				continue;
-			dev_dbg (&dev->dev, "unregistering interface %s\n",
+			dev_dbg(&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
 				interface->dev.bus_id);
 			usb_remove_sysfs_intf_files(interface);
 			usb_remove_sysfs_intf_files(interface);
-			device_del (&interface->dev);
+			device_del(&interface->dev);
 		}
 		}
 
 
 		/* Now that the interfaces are unbound, nobody should
 		/* Now that the interfaces are unbound, nobody should
 		 * try to access them.
 		 * try to access them.
 		 */
 		 */
 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
-			put_device (&dev->actconfig->interface[i]->dev);
+			put_device(&dev->actconfig->interface[i]->dev);
 			dev->actconfig->interface[i] = NULL;
 			dev->actconfig->interface[i] = NULL;
 		}
 		}
 		dev->actconfig = NULL;
 		dev->actconfig = NULL;
@@ -1090,8 +1106,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 	}
 	}
 }
 }
 
 
-
-/*
+/**
  * usb_enable_endpoint - Enable an endpoint for USB communications
  * usb_enable_endpoint - Enable an endpoint for USB communications
  * @dev: the device whose interface is being enabled
  * @dev: the device whose interface is being enabled
  * @ep: the endpoint
  * @ep: the endpoint
@@ -1116,7 +1131,7 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
 	ep->enabled = 1;
 	ep->enabled = 1;
 }
 }
 
 
-/*
+/**
  * usb_enable_interface - Enable all the endpoints for an interface
  * usb_enable_interface - Enable all the endpoints for an interface
  * @dev: the device whose interface is being enabled
  * @dev: the device whose interface is being enabled
  * @intf: pointer to the interface descriptor
  * @intf: pointer to the interface descriptor
@@ -1172,6 +1187,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 	struct usb_host_interface *alt;
 	struct usb_host_interface *alt;
 	int ret;
 	int ret;
 	int manual = 0;
 	int manual = 0;
+	unsigned int epaddr;
+	unsigned int pipe;
 
 
 	if (dev->state == USB_STATE_SUSPENDED)
 	if (dev->state == USB_STATE_SUSPENDED)
 		return -EHOSTUNREACH;
 		return -EHOSTUNREACH;
@@ -1226,11 +1243,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 		int i;
 		int i;
 
 
 		for (i = 0; i < alt->desc.bNumEndpoints; i++) {
 		for (i = 0; i < alt->desc.bNumEndpoints; i++) {
-			unsigned int epaddr =
-				alt->endpoint[i].desc.bEndpointAddress;
-			unsigned int pipe =
-	__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
-	| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
+			epaddr = alt->endpoint[i].desc.bEndpointAddress;
+			pipe = __create_pipe(dev,
+					USB_ENDPOINT_NUMBER_MASK & epaddr) |
+					(usb_endpoint_out(epaddr) ?
+					USB_DIR_OUT : USB_DIR_IN);
 
 
 			usb_clear_halt(dev, pipe);
 			usb_clear_halt(dev, pipe);
 		}
 		}
@@ -1253,6 +1270,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(usb_set_interface);
 
 
 /**
 /**
  * usb_reset_configuration - lightweight device reset
  * usb_reset_configuration - lightweight device reset
@@ -1328,6 +1346,7 @@ int usb_reset_configuration(struct usb_device *dev)
 	}
 	}
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(usb_reset_configuration);
 
 
 static void usb_release_interface(struct device *dev)
 static void usb_release_interface(struct device *dev)
 {
 {
@@ -1357,7 +1376,8 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	if (add_uevent_var(env,
 	if (add_uevent_var(env,
-		   "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+		   "MODALIAS=usb:"
+		   "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
 		   le16_to_cpu(usb_dev->descriptor.idVendor),
 		   le16_to_cpu(usb_dev->descriptor.idVendor),
 		   le16_to_cpu(usb_dev->descriptor.idProduct),
 		   le16_to_cpu(usb_dev->descriptor.idProduct),
 		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
 		   le16_to_cpu(usb_dev->descriptor.bcdDevice),
@@ -1387,8 +1407,8 @@ struct device_type usb_if_device_type = {
 };
 };
 
 
 static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
 static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
-						       struct usb_host_config *config,
-						       u8 inum)
+						struct usb_host_config *config,
+						u8 inum)
 {
 {
 	struct usb_interface_assoc_descriptor *retval = NULL;
 	struct usb_interface_assoc_descriptor *retval = NULL;
 	struct usb_interface_assoc_descriptor *intf_assoc;
 	struct usb_interface_assoc_descriptor *intf_assoc;
@@ -1415,7 +1435,6 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
 	return retval;
 	return retval;
 }
 }
 
 
-
 /*
 /*
  * usb_set_configuration - Makes a particular device setting be current
  * usb_set_configuration - Makes a particular device setting be current
  * @dev: the device whose configuration is being updated
  * @dev: the device whose configuration is being updated
@@ -1533,12 +1552,12 @@ free_interfaces:
 	 * getting rid of old interfaces means unbinding their drivers.
 	 * getting rid of old interfaces means unbinding their drivers.
 	 */
 	 */
 	if (dev->state != USB_STATE_ADDRESS)
 	if (dev->state != USB_STATE_ADDRESS)
-		usb_disable_device (dev, 1);	// Skip ep0
-
-	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+		usb_disable_device(dev, 1);	/* Skip ep0 */
 
 
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			      USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+			      NULL, 0, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0) {
 		/* All the old state is gone, so what else can we do?
 		/* All the old state is gone, so what else can we do?
 		 * The device is probably useless now anyway.
 		 * The device is probably useless now anyway.
 		 */
 		 */
@@ -1585,11 +1604,11 @@ free_interfaces:
 		intf->dev.bus = &usb_bus_type;
 		intf->dev.bus = &usb_bus_type;
 		intf->dev.type = &usb_if_device_type;
 		intf->dev.type = &usb_if_device_type;
 		intf->dev.dma_mask = dev->dev.dma_mask;
 		intf->dev.dma_mask = dev->dev.dma_mask;
-		device_initialize (&intf->dev);
+		device_initialize(&intf->dev);
 		mark_quiesced(intf);
 		mark_quiesced(intf);
-		sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-			 dev->bus->busnum, dev->devpath,
-			 configuration, alt->desc.bInterfaceNumber);
+		sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",
+			dev->bus->busnum, dev->devpath,
+			configuration, alt->desc.bInterfaceNumber);
 	}
 	}
 	kfree(new_interfaces);
 	kfree(new_interfaces);
 
 
@@ -1605,11 +1624,11 @@ free_interfaces:
 	for (i = 0; i < nintf; ++i) {
 	for (i = 0; i < nintf; ++i) {
 		struct usb_interface *intf = cp->interface[i];
 		struct usb_interface *intf = cp->interface[i];
 
 
-		dev_dbg (&dev->dev,
+		dev_dbg(&dev->dev,
 			"adding %s (config #%d, interface %d)\n",
 			"adding %s (config #%d, interface %d)\n",
 			intf->dev.bus_id, configuration,
 			intf->dev.bus_id, configuration,
 			intf->cur_altsetting->desc.bInterfaceNumber);
 			intf->cur_altsetting->desc.bInterfaceNumber);
-		ret = device_add (&intf->dev);
+		ret = device_add(&intf->dev);
 		if (ret != 0) {
 		if (ret != 0) {
 			dev_err(&dev->dev, "device_add(%s) --> %d\n",
 			dev_err(&dev->dev, "device_add(%s) --> %d\n",
 				intf->dev.bus_id, ret);
 				intf->dev.bus_id, ret);
@@ -1677,22 +1696,3 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
 EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-
-EXPORT_SYMBOL(usb_sg_init);
-EXPORT_SYMBOL(usb_sg_cancel);
-EXPORT_SYMBOL(usb_sg_wait);
-
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_string);
-
-// synchronous calls that also maintain usbcore state
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_reset_configuration);
-EXPORT_SYMBOL(usb_set_interface);
-

+ 1 - 1
drivers/usb/core/notify.c

@@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(usb_register_notify);
  * usb_unregister_notify - unregister a notifier callback
  * usb_unregister_notify - unregister a notifier callback
  * @nb: pointer to the notifier block for the callback events.
  * @nb: pointer to the notifier block for the callback events.
  *
  *
- * usb_register_notifier() must have been previously called for this function
+ * usb_register_notify() must have been previously called for this function
  * to work properly.
  * to work properly.
  */
  */
 void usb_unregister_notify(struct notifier_block *nb)
 void usb_unregister_notify(struct notifier_block *nb)

+ 3 - 3
drivers/usb/core/otg_whitelist.h

@@ -14,7 +14,7 @@
  * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
  * mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
  *
  *
  * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
  * YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
- */ 
+ */
 
 
 static struct usb_device_id whitelist_table [] = {
 static struct usb_device_id whitelist_table [] = {
 
 
@@ -55,7 +55,7 @@ static int is_targeted(struct usb_device *dev)
 		return 1;
 		return 1;
 
 
 	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
 	/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
-	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && 
+	if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
 	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
 	     le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
 		return 0;
 		return 0;
 
 
@@ -86,7 +86,7 @@ static int is_targeted(struct usb_device *dev)
 			continue;
 			continue;
 
 
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+		    (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
 			continue;
 			continue;
 
 
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
 		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&

+ 59 - 10
drivers/usb/core/sysfs.c

@@ -72,7 +72,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
 	return (value < 0) ? value : count;
 	return (value < 0) ? value : count;
 }
 }
 
 
-static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, 
+static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
 		show_bConfigurationValue, set_bConfigurationValue);
 		show_bConfigurationValue, set_bConfigurationValue);
 
 
 /* String fields */
 /* String fields */
@@ -248,6 +248,41 @@ static void remove_persist_attributes(struct device *dev)
 
 
 #ifdef	CONFIG_USB_SUSPEND
 #ifdef	CONFIG_USB_SUSPEND
 
 
+static ssize_t
+show_connected_duration(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+
+	return sprintf(buf, "%u\n",
+			jiffies_to_msecs(jiffies - udev->connect_time));
+}
+
+static DEVICE_ATTR(connected_duration, S_IRUGO, show_connected_duration, NULL);
+
+/*
+ * If the device is resumed, the last time the device was suspended has
+ * been pre-subtracted from active_duration.  We add the current time to
+ * get the duration that the device was actually active.
+ *
+ * If the device is suspended, the active_duration is up-to-date.
+ */
+static ssize_t
+show_active_duration(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct usb_device *udev = to_usb_device(dev);
+	int duration;
+
+	if (udev->state != USB_STATE_SUSPENDED)
+		duration = jiffies_to_msecs(jiffies + udev->active_duration);
+	else
+		duration = jiffies_to_msecs(udev->active_duration);
+	return sprintf(buf, "%u\n", duration);
+}
+
+static DEVICE_ATTR(active_duration, S_IRUGO, show_active_duration, NULL);
+
 static ssize_t
 static ssize_t
 show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
 show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
 {
 {
@@ -365,12 +400,26 @@ static int add_power_attributes(struct device *dev)
 			rc = sysfs_add_file_to_group(&dev->kobj,
 			rc = sysfs_add_file_to_group(&dev->kobj,
 					&dev_attr_level.attr,
 					&dev_attr_level.attr,
 					power_group);
 					power_group);
+		if (rc == 0)
+			rc = sysfs_add_file_to_group(&dev->kobj,
+					&dev_attr_connected_duration.attr,
+					power_group);
+		if (rc == 0)
+			rc = sysfs_add_file_to_group(&dev->kobj,
+					&dev_attr_active_duration.attr,
+					power_group);
 	}
 	}
 	return rc;
 	return rc;
 }
 }
 
 
 static void remove_power_attributes(struct device *dev)
 static void remove_power_attributes(struct device *dev)
 {
 {
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_active_duration.attr,
+			power_group);
+	sysfs_remove_file_from_group(&dev->kobj,
+			&dev_attr_connected_duration.attr,
+			power_group);
 	sysfs_remove_file_from_group(&dev->kobj,
 	sysfs_remove_file_from_group(&dev->kobj,
 			&dev_attr_level.attr,
 			&dev_attr_level.attr,
 			power_group);
 			power_group);
@@ -601,21 +650,21 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
 /* Interface Accociation Descriptor fields */
 /* Interface Accociation Descriptor fields */
 #define usb_intf_assoc_attr(field, format_string)			\
 #define usb_intf_assoc_attr(field, format_string)			\
 static ssize_t								\
 static ssize_t								\
-show_iad_##field (struct device *dev, struct device_attribute *attr,	\
+show_iad_##field(struct device *dev, struct device_attribute *attr,	\
 		char *buf)						\
 		char *buf)						\
 {									\
 {									\
-	struct usb_interface *intf = to_usb_interface (dev);		\
+	struct usb_interface *intf = to_usb_interface(dev);		\
 									\
 									\
-	return sprintf (buf, format_string,				\
-			intf->intf_assoc->field); 		\
+	return sprintf(buf, format_string,				\
+			intf->intf_assoc->field); 			\
 }									\
 }									\
 static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
 static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
 
 
-usb_intf_assoc_attr (bFirstInterface, "%02x\n")
-usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
-usb_intf_assoc_attr (bFunctionClass, "%02x\n")
-usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
-usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
+usb_intf_assoc_attr(bFirstInterface, "%02x\n")
+usb_intf_assoc_attr(bInterfaceCount, "%02d\n")
+usb_intf_assoc_attr(bFunctionClass, "%02x\n")
+usb_intf_assoc_attr(bFunctionSubClass, "%02x\n")
+usb_intf_assoc_attr(bFunctionProtocol, "%02x\n")
 
 
 /* Interface fields */
 /* Interface fields */
 #define usb_intf_attr(field, format_string)				\
 #define usb_intf_attr(field, format_string)				\

+ 19 - 18
drivers/usb/core/urb.c

@@ -42,6 +42,7 @@ void usb_init_urb(struct urb *urb)
 		INIT_LIST_HEAD(&urb->anchor_list);
 		INIT_LIST_HEAD(&urb->anchor_list);
 	}
 	}
 }
 }
+EXPORT_SYMBOL_GPL(usb_init_urb);
 
 
 /**
 /**
  * usb_alloc_urb - creates a new urb for a USB driver to use
  * usb_alloc_urb - creates a new urb for a USB driver to use
@@ -73,6 +74,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 	usb_init_urb(urb);
 	usb_init_urb(urb);
 	return urb;
 	return urb;
 }
 }
+EXPORT_SYMBOL_GPL(usb_alloc_urb);
 
 
 /**
 /**
  * usb_free_urb - frees the memory used by a urb when all users of it are finished
  * usb_free_urb - frees the memory used by a urb when all users of it are finished
@@ -89,6 +91,7 @@ void usb_free_urb(struct urb *urb)
 	if (urb)
 	if (urb)
 		kref_put(&urb->kref, urb_destroy);
 		kref_put(&urb->kref, urb_destroy);
 }
 }
+EXPORT_SYMBOL_GPL(usb_free_urb);
 
 
 /**
 /**
  * usb_get_urb - increments the reference count of the urb
  * usb_get_urb - increments the reference count of the urb
@@ -100,12 +103,13 @@ void usb_free_urb(struct urb *urb)
  *
  *
  * A pointer to the urb with the incremented reference counter is returned.
  * A pointer to the urb with the incremented reference counter is returned.
  */
  */
-struct urb * usb_get_urb(struct urb *urb)
+struct urb *usb_get_urb(struct urb *urb)
 {
 {
 	if (urb)
 	if (urb)
 		kref_get(&urb->kref);
 		kref_get(&urb->kref);
 	return urb;
 	return urb;
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_urb);
 
 
 /**
 /**
  * usb_anchor_urb - anchors an URB while it is processed
  * usb_anchor_urb - anchors an URB while it is processed
@@ -172,7 +176,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  * describing that request to the USB subsystem.  Request completion will
  * describing that request to the USB subsystem.  Request completion will
  * be indicated later, asynchronously, by calling the completion handler.
  * be indicated later, asynchronously, by calling the completion handler.
  * The three types of completion are success, error, and unlink
  * The three types of completion are success, error, and unlink
- * (a software-induced fault, also called "request cancellation").  
+ * (a software-induced fault, also called "request cancellation").
  *
  *
  * URBs may be submitted in interrupt context.
  * URBs may be submitted in interrupt context.
  *
  *
@@ -255,7 +259,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
  *       semaphores), or
  *       semaphores), or
  *   (c) current->state != TASK_RUNNING, this is the case only after
  *   (c) current->state != TASK_RUNNING, this is the case only after
  *       you've changed it.
  *       you've changed it.
- * 
+ *
  * GFP_NOIO is used in the block io path and error handling of storage
  * GFP_NOIO is used in the block io path and error handling of storage
  * devices.
  * devices.
  *
  *
@@ -284,7 +288,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 
 
 	if (!urb || urb->hcpriv || !urb->complete)
 	if (!urb || urb->hcpriv || !urb->complete)
 		return -EINVAL;
 		return -EINVAL;
-	if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
+	dev = urb->dev;
+	if ((!dev) || (dev->state < USB_STATE_DEFAULT))
 		return -ENODEV;
 		return -ENODEV;
 
 
 	/* For now, get the endpoint from the pipe.  Eventually drivers
 	/* For now, get the endpoint from the pipe.  Eventually drivers
@@ -347,11 +352,11 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 			max *= mult;
 			max *= mult;
 		}
 		}
 
 
-		if (urb->number_of_packets <= 0)		    
+		if (urb->number_of_packets <= 0)
 			return -EINVAL;
 			return -EINVAL;
 		for (n = 0; n < urb->number_of_packets; n++) {
 		for (n = 0; n < urb->number_of_packets; n++) {
 			len = urb->iso_frame_desc[n].length;
 			len = urb->iso_frame_desc[n].length;
-			if (len < 0 || len > max) 
+			if (len < 0 || len > max)
 				return -EMSGSIZE;
 				return -EMSGSIZE;
 			urb->iso_frame_desc[n].status = -EXDEV;
 			urb->iso_frame_desc[n].status = -EXDEV;
 			urb->iso_frame_desc[n].actual_length = 0;
 			urb->iso_frame_desc[n].actual_length = 0;
@@ -416,7 +421,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 		/* too big? */
 		/* too big? */
 		switch (dev->speed) {
 		switch (dev->speed) {
 		case USB_SPEED_HIGH:	/* units are microframes */
 		case USB_SPEED_HIGH:	/* units are microframes */
-			// NOTE usb handles 2^15
+			/* NOTE usb handles 2^15 */
 			if (urb->interval > (1024 * 8))
 			if (urb->interval > (1024 * 8))
 				urb->interval = 1024 * 8;
 				urb->interval = 1024 * 8;
 			max = 1024 * 8;
 			max = 1024 * 8;
@@ -426,12 +431,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 			if (xfertype == USB_ENDPOINT_XFER_INT) {
 			if (xfertype == USB_ENDPOINT_XFER_INT) {
 				if (urb->interval > 255)
 				if (urb->interval > 255)
 					return -EINVAL;
 					return -EINVAL;
-				// NOTE ohci only handles up to 32
+				/* NOTE ohci only handles up to 32 */
 				max = 128;
 				max = 128;
 			} else {
 			} else {
 				if (urb->interval > 1024)
 				if (urb->interval > 1024)
 					urb->interval = 1024;
 					urb->interval = 1024;
-				// NOTE usb and ohci handle up to 2^15
+				/* NOTE usb and ohci handle up to 2^15 */
 				max = 1024;
 				max = 1024;
 			}
 			}
 			break;
 			break;
@@ -444,6 +449,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 
 
 	return usb_hcd_submit_urb(urb, mem_flags);
 	return usb_hcd_submit_urb(urb, mem_flags);
 }
 }
+EXPORT_SYMBOL_GPL(usb_submit_urb);
 
 
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
 
 
@@ -514,6 +520,7 @@ int usb_unlink_urb(struct urb *urb)
 		return -EIDRM;
 		return -EIDRM;
 	return usb_hcd_unlink_urb(urb, -ECONNRESET);
 	return usb_hcd_unlink_urb(urb, -ECONNRESET);
 }
 }
+EXPORT_SYMBOL_GPL(usb_unlink_urb);
 
 
 /**
 /**
  * usb_kill_urb - cancel a transfer request and wait for it to finish
  * usb_kill_urb - cancel a transfer request and wait for it to finish
@@ -553,6 +560,7 @@ void usb_kill_urb(struct urb *urb)
 	--urb->reject;
 	--urb->reject;
 	mutex_unlock(&reject_mutex);
 	mutex_unlock(&reject_mutex);
 }
 }
+EXPORT_SYMBOL_GPL(usb_kill_urb);
 
 
 /**
 /**
  * usb_kill_anchored_urbs - cancel transfer requests en masse
  * usb_kill_anchored_urbs - cancel transfer requests en masse
@@ -567,7 +575,8 @@ void usb_kill_anchored_urbs(struct usb_anchor *anchor)
 
 
 	spin_lock_irq(&anchor->lock);
 	spin_lock_irq(&anchor->lock);
 	while (!list_empty(&anchor->urb_list)) {
 	while (!list_empty(&anchor->urb_list)) {
-		victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list);
+		victim = list_entry(anchor->urb_list.prev, struct urb,
+				    anchor_list);
 		/* we must make sure the URB isn't freed before we kill it*/
 		/* we must make sure the URB isn't freed before we kill it*/
 		usb_get_urb(victim);
 		usb_get_urb(victim);
 		spin_unlock_irq(&anchor->lock);
 		spin_unlock_irq(&anchor->lock);
@@ -595,11 +604,3 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
 				  msecs_to_jiffies(timeout));
 				  msecs_to_jiffies(timeout));
 }
 }
 EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
 EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
-
-EXPORT_SYMBOL(usb_init_urb);
-EXPORT_SYMBOL(usb_alloc_urb);
-EXPORT_SYMBOL(usb_free_urb);
-EXPORT_SYMBOL(usb_get_urb);
-EXPORT_SYMBOL(usb_submit_urb);
-EXPORT_SYMBOL(usb_unlink_urb);
-EXPORT_SYMBOL(usb_kill_urb);

+ 44 - 73
drivers/usb/core/usb.c

@@ -96,6 +96,7 @@ struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
 
 
 	return NULL;
 	return NULL;
 }
 }
+EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
 
 
 /**
 /**
  * usb_altnum_to_altsetting - get the altsetting structure with a given
  * usb_altnum_to_altsetting - get the altsetting structure with a given
@@ -115,8 +116,9 @@ struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
  * Don't call this function unless you are bound to the intf interface
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
  * or you have locked the device!
  */
  */
-struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,
-						    unsigned int altnum)
+struct usb_host_interface *usb_altnum_to_altsetting(
+					const struct usb_interface *intf,
+					unsigned int altnum)
 {
 {
 	int i;
 	int i;
 
 
@@ -126,13 +128,14 @@ struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
+EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting);
 
 
 struct find_interface_arg {
 struct find_interface_arg {
 	int minor;
 	int minor;
 	struct usb_interface *interface;
 	struct usb_interface *interface;
 };
 };
 
 
-static int __find_interface(struct device * dev, void * data)
+static int __find_interface(struct device *dev, void *data)
 {
 {
 	struct find_interface_arg *arg = data;
 	struct find_interface_arg *arg = data;
 	struct usb_interface *intf;
 	struct usb_interface *intf;
@@ -154,7 +157,7 @@ static int __find_interface(struct device * dev, void * data)
  * @drv: the driver whose current configuration is considered
  * @drv: the driver whose current configuration is considered
  * @minor: the minor number of the desired device
  * @minor: the minor number of the desired device
  *
  *
- * This walks the driver device list and returns a pointer to the interface 
+ * This walks the driver device list and returns a pointer to the interface
  * with the matching minor.  Note, this only works for devices that share the
  * with the matching minor.  Note, this only works for devices that share the
  * USB major number.
  * USB major number.
  */
  */
@@ -170,6 +173,7 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 					__find_interface);
 					__find_interface);
 	return argb.interface;
 	return argb.interface;
 }
 }
+EXPORT_SYMBOL_GPL(usb_find_interface);
 
 
 /**
 /**
  * usb_release_dev - free a usb device structure when all users of it are finished.
  * usb_release_dev - free a usb device structure when all users of it are finished.
@@ -230,7 +234,7 @@ static int ksuspend_usb_init(void)
 	 * singlethreaded.  Its job doesn't justify running on more
 	 * singlethreaded.  Its job doesn't justify running on more
 	 * than one CPU.
 	 * than one CPU.
 	 */
 	 */
-	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
+	ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
 	if (!ksuspend_usb_wq)
 	if (!ksuspend_usb_wq)
 		return -ENOMEM;
 		return -ENOMEM;
 	return 0;
 	return 0;
@@ -269,8 +273,8 @@ static unsigned usb_bus_is_wusb(struct usb_bus *bus)
  *
  *
  * This call may not be used in a non-sleeping context.
  * This call may not be used in a non-sleeping context.
  */
  */
-struct usb_device *
-usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
+struct usb_device *usb_alloc_dev(struct usb_device *parent,
+				 struct usb_bus *bus, unsigned port1)
 {
 {
 	struct usb_device *dev;
 	struct usb_device *dev;
 	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
 	struct usb_hcd *usb_hcd = container_of(bus, struct usb_hcd, self);
@@ -339,6 +343,8 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
 	mutex_init(&dev->pm_mutex);
 	mutex_init(&dev->pm_mutex);
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
 	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+	dev->connect_time = jiffies;
+	dev->active_duration = -jiffies;
 #endif
 #endif
 	if (root_hub)	/* Root hub always ok [and always wired] */
 	if (root_hub)	/* Root hub always ok [and always wired] */
 		dev->authorized = 1;
 		dev->authorized = 1;
@@ -367,6 +373,7 @@ struct usb_device *usb_get_dev(struct usb_device *dev)
 		get_device(&dev->dev);
 		get_device(&dev->dev);
 	return dev;
 	return dev;
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_dev);
 
 
 /**
 /**
  * usb_put_dev - release a use of the usb device structure
  * usb_put_dev - release a use of the usb device structure
@@ -380,6 +387,7 @@ void usb_put_dev(struct usb_device *dev)
 	if (dev)
 	if (dev)
 		put_device(&dev->dev);
 		put_device(&dev->dev);
 }
 }
+EXPORT_SYMBOL_GPL(usb_put_dev);
 
 
 /**
 /**
  * usb_get_intf - increments the reference count of the usb interface structure
  * usb_get_intf - increments the reference count of the usb interface structure
@@ -400,6 +408,7 @@ struct usb_interface *usb_get_intf(struct usb_interface *intf)
 		get_device(&intf->dev);
 		get_device(&intf->dev);
 	return intf;
 	return intf;
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_intf);
 
 
 /**
 /**
  * usb_put_intf - release a use of the usb interface structure
  * usb_put_intf - release a use of the usb interface structure
@@ -414,7 +423,7 @@ void usb_put_intf(struct usb_interface *intf)
 	if (intf)
 	if (intf)
 		put_device(&intf->dev);
 		put_device(&intf->dev);
 }
 }
-
+EXPORT_SYMBOL_GPL(usb_put_intf);
 
 
 /*			USB device locking
 /*			USB device locking
  *
  *
@@ -461,11 +470,11 @@ int usb_lock_device_for_reset(struct usb_device *udev,
 		return -EHOSTUNREACH;
 		return -EHOSTUNREACH;
 	if (iface) {
 	if (iface) {
 		switch (iface->condition) {
 		switch (iface->condition) {
-		  case USB_INTERFACE_BINDING:
+		case USB_INTERFACE_BINDING:
 			return 0;
 			return 0;
-		  case USB_INTERFACE_BOUND:
+		case USB_INTERFACE_BOUND:
 			break;
 			break;
-		  default:
+		default:
 			return -EINTR;
 			return -EINTR;
 		}
 		}
 	}
 	}
@@ -487,7 +496,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
 	}
 	}
 	return 1;
 	return 1;
 }
 }
-
+EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
 
 
 static struct usb_device *match_device(struct usb_device *dev,
 static struct usb_device *match_device(struct usb_device *dev,
 				       u16 vendor_id, u16 product_id)
 				       u16 vendor_id, u16 product_id)
@@ -540,10 +549,10 @@ struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
 	struct list_head *buslist;
 	struct list_head *buslist;
 	struct usb_bus *bus;
 	struct usb_bus *bus;
 	struct usb_device *dev = NULL;
 	struct usb_device *dev = NULL;
-	
+
 	mutex_lock(&usb_bus_list_lock);
 	mutex_lock(&usb_bus_list_lock);
 	for (buslist = usb_bus_list.next;
 	for (buslist = usb_bus_list.next;
-	     buslist != &usb_bus_list; 
+	     buslist != &usb_bus_list;
 	     buslist = buslist->next) {
 	     buslist = buslist->next) {
 		bus = container_of(buslist, struct usb_bus, bus_list);
 		bus = container_of(buslist, struct usb_bus, bus_list);
 		if (!bus->root_hub)
 		if (!bus->root_hub)
@@ -576,6 +585,7 @@ int usb_get_current_frame_number(struct usb_device *dev)
 {
 {
 	return usb_hcd_get_frame_number(dev);
 	return usb_hcd_get_frame_number(dev);
 }
 }
+EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
 
 
 /*-------------------------------------------------------------------*/
 /*-------------------------------------------------------------------*/
 /*
 /*
@@ -584,7 +594,7 @@ int usb_get_current_frame_number(struct usb_device *dev)
  */
  */
 
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
-	unsigned char type, void **ptr)
+			       unsigned char type, void **ptr)
 {
 {
 	struct usb_descriptor_header *header;
 	struct usb_descriptor_header *header;
 
 
@@ -595,7 +605,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
 			printk(KERN_ERR
 			printk(KERN_ERR
 				"%s: bogus descriptor, type %d length %d\n",
 				"%s: bogus descriptor, type %d length %d\n",
 				usbcore_name,
 				usbcore_name,
-				header->bDescriptorType, 
+				header->bDescriptorType,
 				header->bLength);
 				header->bLength);
 			return -1;
 			return -1;
 		}
 		}
@@ -610,6 +620,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
 	}
 	}
 	return -1;
 	return -1;
 }
 }
+EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
 
 
 /**
 /**
  * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
  * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
@@ -633,17 +644,14 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
  *
  *
  * When the buffer is no longer used, free it with usb_buffer_free().
  * When the buffer is no longer used, free it with usb_buffer_free().
  */
  */
-void *usb_buffer_alloc(
-	struct usb_device *dev,
-	size_t size,
-	gfp_t mem_flags,
-	dma_addr_t *dma
-)
+void *usb_buffer_alloc(struct usb_device *dev, size_t size, gfp_t mem_flags,
+		       dma_addr_t *dma)
 {
 {
 	if (!dev || !dev->bus)
 	if (!dev || !dev->bus)
 		return NULL;
 		return NULL;
 	return hcd_buffer_alloc(dev->bus, size, mem_flags, dma);
 	return hcd_buffer_alloc(dev->bus, size, mem_flags, dma);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_alloc);
 
 
 /**
 /**
  * usb_buffer_free - free memory allocated with usb_buffer_alloc()
  * usb_buffer_free - free memory allocated with usb_buffer_alloc()
@@ -656,12 +664,8 @@ void *usb_buffer_alloc(
  * been allocated using usb_buffer_alloc(), and the parameters must match
  * been allocated using usb_buffer_alloc(), and the parameters must match
  * those provided in that allocation request.
  * those provided in that allocation request.
  */
  */
-void usb_buffer_free(
-	struct usb_device *dev,
-	size_t size,
-	void *addr,
-	dma_addr_t dma
-)
+void usb_buffer_free(struct usb_device *dev, size_t size, void *addr,
+		     dma_addr_t dma)
 {
 {
 	if (!dev || !dev->bus)
 	if (!dev || !dev->bus)
 		return;
 		return;
@@ -669,6 +673,7 @@ void usb_buffer_free(
 		return;
 		return;
 	hcd_buffer_free(dev->bus, size, addr, dma);
 	hcd_buffer_free(dev->bus, size, addr, dma);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_free);
 
 
 /**
 /**
  * usb_buffer_map - create DMA mapping(s) for an urb
  * usb_buffer_map - create DMA mapping(s) for an urb
@@ -708,14 +713,15 @@ struct urb *usb_buffer_map(struct urb *urb)
 					urb->setup_packet,
 					urb->setup_packet,
 					sizeof(struct usb_ctrlrequest),
 					sizeof(struct usb_ctrlrequest),
 					DMA_TO_DEVICE);
 					DMA_TO_DEVICE);
-	// FIXME generic api broken like pci, can't report errors
-	// if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
+	/* FIXME generic api broken like pci, can't report errors */
+	/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
 	} else
 	} else
 		urb->transfer_dma = ~0;
 		urb->transfer_dma = ~0;
 	urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
 	urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
 				| URB_NO_SETUP_DMA_MAP);
 				| URB_NO_SETUP_DMA_MAP);
 	return urb;
 	return urb;
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_map);
 #endif  /*  0  */
 #endif  /*  0  */
 
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
@@ -753,6 +759,7 @@ void usb_buffer_dmasync(struct urb *urb)
 					DMA_TO_DEVICE);
 					DMA_TO_DEVICE);
 	}
 	}
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync);
 #endif
 #endif
 
 
 /**
 /**
@@ -788,6 +795,7 @@ void usb_buffer_unmap(struct urb *urb)
 	urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
 	urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
 				| URB_NO_SETUP_DMA_MAP);
 				| URB_NO_SETUP_DMA_MAP);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_unmap);
 #endif  /*  0  */
 #endif  /*  0  */
 
 
 /**
 /**
@@ -828,10 +836,11 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
 			|| !controller->dma_mask)
 			|| !controller->dma_mask)
 		return -1;
 		return -1;
 
 
-	// FIXME generic api broken like pci, can't report errors
+	/* FIXME generic api broken like pci, can't report errors */
 	return dma_map_sg(controller, sg, nents,
 	return dma_map_sg(controller, sg, nents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_map_sg);
 
 
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
 /* XXX DISABLED, no users currently.  If you wish to re-enable this
  * XXX please determine whether the sync is to transfer ownership of
  * XXX please determine whether the sync is to transfer ownership of
@@ -865,6 +874,7 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in,
 	dma_sync_sg(controller, sg, n_hw_ents,
 	dma_sync_sg(controller, sg, n_hw_ents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
 #endif
 #endif
 
 
 /**
 /**
@@ -891,6 +901,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in,
 	dma_unmap_sg(controller, sg, n_hw_ents,
 	dma_unmap_sg(controller, sg, n_hw_ents,
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 			is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 }
+EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg);
 
 
 /* format to disable USB on kernel command line is: nousb */
 /* format to disable USB on kernel command line is: nousb */
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
@@ -902,6 +913,7 @@ int usb_disabled(void)
 {
 {
 	return nousb;
 	return nousb;
 }
 }
+EXPORT_SYMBOL_GPL(usb_disabled);
 
 
 /*
 /*
  * Init
  * Init
@@ -918,7 +930,7 @@ static int __init usb_init(void)
 	if (retval)
 	if (retval)
 		goto out;
 		goto out;
 	retval = bus_register(&usb_bus_type);
 	retval = bus_register(&usb_bus_type);
-	if (retval) 
+	if (retval)
 		goto bus_register_failed;
 		goto bus_register_failed;
 	retval = usb_host_init();
 	retval = usb_host_init();
 	if (retval)
 	if (retval)
@@ -983,45 +995,4 @@ static void __exit usb_exit(void)
 
 
 subsys_initcall(usb_init);
 subsys_initcall(usb_init);
 module_exit(usb_exit);
 module_exit(usb_exit);
-
-/*
- * USB may be built into the kernel or be built as modules.
- * These symbols are exported for device (or host controller)
- * driver modules to use.
- */
-
-EXPORT_SYMBOL(usb_disabled);
-
-EXPORT_SYMBOL_GPL(usb_get_intf);
-EXPORT_SYMBOL_GPL(usb_put_intf);
-
-EXPORT_SYMBOL(usb_put_dev);
-EXPORT_SYMBOL(usb_get_dev);
-EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
-
-EXPORT_SYMBOL(usb_lock_device_for_reset);
-
-EXPORT_SYMBOL(usb_find_interface);
-EXPORT_SYMBOL(usb_ifnum_to_if);
-EXPORT_SYMBOL(usb_altnum_to_altsetting);
-
-EXPORT_SYMBOL(__usb_get_extra_descriptor);
-
-EXPORT_SYMBOL(usb_get_current_frame_number);
-
-EXPORT_SYMBOL(usb_buffer_alloc);
-EXPORT_SYMBOL(usb_buffer_free);
-
-#if 0
-EXPORT_SYMBOL(usb_buffer_map);
-EXPORT_SYMBOL(usb_buffer_dmasync);
-EXPORT_SYMBOL(usb_buffer_unmap);
-#endif
-
-EXPORT_SYMBOL(usb_buffer_map_sg);
-#if 0
-EXPORT_SYMBOL(usb_buffer_dmasync_sg);
-#endif
-EXPORT_SYMBOL(usb_buffer_unmap_sg);
-
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 11 - 10
drivers/usb/core/usb.h

@@ -1,22 +1,23 @@
 /* Functions local to drivers/usb/core/ */
 /* Functions local to drivers/usb/core/ */
 
 
-extern int usb_create_sysfs_dev_files (struct usb_device *dev);
-extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
-extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
-extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+extern int usb_create_sysfs_dev_files(struct usb_device *dev);
+extern void usb_remove_sysfs_dev_files(struct usb_device *dev);
+extern int usb_create_sysfs_intf_files(struct usb_interface *intf);
+extern void usb_remove_sysfs_intf_files(struct usb_interface *intf);
+extern int usb_create_ep_files(struct device *parent,
+				struct usb_host_endpoint *endpoint,
 				struct usb_device *udev);
 				struct usb_device *udev);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
 
 extern void usb_enable_endpoint(struct usb_device *dev,
 extern void usb_enable_endpoint(struct usb_device *dev,
 		struct usb_host_endpoint *ep);
 		struct usb_host_endpoint *ep);
-extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
-extern void usb_disable_interface (struct usb_device *dev,
+extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr);
+extern void usb_disable_interface(struct usb_device *dev,
 		struct usb_interface *intf);
 		struct usb_interface *intf);
 extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_release_interface_cache(struct kref *ref);
-extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
-extern int usb_deauthorize_device (struct usb_device *);
-extern int usb_authorize_device (struct usb_device *);
+extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
+extern int usb_deauthorize_device(struct usb_device *);
+extern int usb_authorize_device(struct usb_device *);
 extern void usb_detect_quirks(struct usb_device *udev);
 extern void usb_detect_quirks(struct usb_device *udev);
 
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
 extern int usb_get_device_descriptor(struct usb_device *dev,

+ 29 - 4
drivers/usb/gadget/Kconfig

@@ -12,10 +12,9 @@
 # With help from a special transceiver and a "Mini-AB" jack, systems with
 # With help from a special transceiver and a "Mini-AB" jack, systems with
 # both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
 # both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
 #
 #
-menu "USB Gadget Support"
 
 
-config USB_GADGET
-	tristate "Support for USB Gadgets"
+menuconfig USB_GADGET
+	tristate "USB Gadget Support"
 	help
 	help
 	   USB is a master/slave protocol, organized with one master
 	   USB is a master/slave protocol, organized with one master
 	   host (such as a PC) controlling up to 127 peripheral devices.
 	   host (such as a PC) controlling up to 127 peripheral devices.
@@ -42,6 +41,8 @@ config USB_GADGET
 	   For more information, see <http://www.linux-usb.org/gadget> and
 	   For more information, see <http://www.linux-usb.org/gadget> and
 	   the kernel DocBook documentation for this API.
 	   the kernel DocBook documentation for this API.
 
 
+if USB_GADGET
+
 config USB_GADGET_DEBUG
 config USB_GADGET_DEBUG
 	boolean "Debugging messages"
 	boolean "Debugging messages"
 	depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
 	depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
@@ -220,6 +221,16 @@ config USB_M66592
 	default USB_GADGET
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 	select USB_GADGET_SELECTED
 
 
+config SUPERH_BUILT_IN_M66592
+	boolean "Enable SuperH built-in USB like the M66592"
+	depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722
+	help
+	   SH7722 has USB like the M66592.
+
+	   The transfer rate is very slow when use "Ethernet Gadget".
+	   However, this problem is improved if change a value of
+	   NET_IP_ALIGN to 4.
+
 config USB_GADGET_GOKU
 config USB_GADGET_GOKU
 	boolean "Toshiba TC86C001 'Goku-S'"
 	boolean "Toshiba TC86C001 'Goku-S'"
 	depends on PCI
 	depends on PCI
@@ -538,6 +549,20 @@ config USB_MIDI_GADGET
 	  Say "y" to link the driver statically, or "m" to build a
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module called "g_midi".
 	  dynamically linked module called "g_midi".
 
 
+config USB_G_PRINTER
+	tristate "Printer Gadget"
+	help
+	  The Printer Gadget channels data between the USB host and a
+	  userspace program driving the print engine. The user space
+	  program reads and writes the device file /dev/g_printer to
+	  receive or send printer data. It can use ioctl calls to
+	  the device file to get or set printer status.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module called "g_printer".
+
+	  For more information, see Documentation/usb/gadget_printer.txt
+	  which includes sample code for accessing the device file.
 
 
 # put drivers that need isochronous transfer support (for audio
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
 # or video class gadget drivers), or specific hardware, here.
@@ -546,4 +571,4 @@ config USB_MIDI_GADGET
 
 
 endchoice
 endchoice
 
 
-endmenu
+endif # USB_GADGET

+ 3 - 0
drivers/usb/gadget/Makefile

@@ -28,6 +28,8 @@ g_midi-objs			:= gmidi.o usbstring.o config.o epautoconf.o
 gadgetfs-objs			:= inode.o
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
 					epautoconf.o
+g_printer-objs			:= printer.o usbstring.o config.o \
+					epautoconf.o
 
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
 	g_ether-objs		+= rndis.o
 	g_ether-objs		+= rndis.o
@@ -38,5 +40,6 @@ obj-$(CONFIG_USB_ETH)		+= g_ether.o
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_GADGETFS)	+= gadgetfs.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
+obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 
 

+ 2 - 1
drivers/usb/gadget/amd5536udc.c

@@ -1244,7 +1244,7 @@ udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)
 		/* stop OUT naking */
 		/* stop OUT naking */
 		if (!ep->in) {
 		if (!ep->in) {
 			if (!use_dma && udc_rxfifo_pending) {
 			if (!use_dma && udc_rxfifo_pending) {
-				DBG(dev, "udc_queue(): pending bytes in"
+				DBG(dev, "udc_queue(): pending bytes in "
 					"rxfifo after nyet\n");
 					"rxfifo after nyet\n");
 				/*
 				/*
 				 * read pending bytes afer nyet:
 				 * read pending bytes afer nyet:
@@ -2038,6 +2038,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
 	driver->unbind(&dev->gadget);
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	/* set SD */
 	/* set SD */

+ 65 - 22
drivers/usb/gadget/at91_udc.c

@@ -21,8 +21,7 @@
  * Boston, MA  02111-1307, USA.
  * Boston, MA  02111-1307, USA.
  */
  */
 
 
-#undef	DEBUG
-#undef	VERBOSE
+#undef	VERBOSE_DEBUG
 #undef	PACKET_TRACE
 #undef	PACKET_TRACE
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -46,8 +45,8 @@
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
+#include <asm/gpio.h>
 
 
-#include <asm/arch/gpio.h>
 #include <asm/arch/board.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/at91sam9261_matrix.h>
 #include <asm/arch/at91sam9261_matrix.h>
@@ -580,7 +579,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
  */
  */
 
 
 static struct usb_request *
 static struct usb_request *
-at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
+at91_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
 {
 {
 	struct at91_request *req;
 	struct at91_request *req;
 
 
@@ -881,6 +880,8 @@ static void clk_off(struct at91_udc *udc)
  */
  */
 static void pullup(struct at91_udc *udc, int is_on)
 static void pullup(struct at91_udc *udc, int is_on)
 {
 {
+	int	active = !udc->board.pullup_active_low;
+
 	if (!udc->enabled || !udc->vbus)
 	if (!udc->enabled || !udc->vbus)
 		is_on = 0;
 		is_on = 0;
 	DBG("%sactive\n", is_on ? "" : "in");
 	DBG("%sactive\n", is_on ? "" : "in");
@@ -890,7 +891,7 @@ static void pullup(struct at91_udc *udc, int is_on)
 		at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
 		if (cpu_is_at91rm9200())
 		if (cpu_is_at91rm9200())
-			at91_set_gpio_value(udc->board.pullup_pin, 1);
+			gpio_set_value(udc->board.pullup_pin, active);
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 
@@ -908,7 +909,7 @@ static void pullup(struct at91_udc *udc, int is_on)
 		at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		if (cpu_is_at91rm9200())
 		if (cpu_is_at91rm9200())
-			at91_set_gpio_value(udc->board.pullup_pin, 0);
+			gpio_set_value(udc->board.pullup_pin, !active);
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) {
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
 
 
@@ -1153,7 +1154,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 			| USB_REQ_GET_STATUS:
 			| USB_REQ_GET_STATUS:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
 		ep = &udc->ep[tmp];
-		if (tmp > NUM_ENDPOINTS || (tmp && !ep->desc))
+		if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
 			goto stall;
 			goto stall;
 
 
 		if (tmp) {
 		if (tmp) {
@@ -1176,7 +1177,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 			| USB_REQ_SET_FEATURE:
 			| USB_REQ_SET_FEATURE:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
 		ep = &udc->ep[tmp];
-		if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+		if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
 			goto stall;
 			goto stall;
 		if (!ep->desc || ep->is_iso)
 		if (!ep->desc || ep->is_iso)
 			goto stall;
 			goto stall;
@@ -1195,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
 			| USB_REQ_CLEAR_FEATURE:
 			| USB_REQ_CLEAR_FEATURE:
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
 		ep = &udc->ep[tmp];
 		ep = &udc->ep[tmp];
-		if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+		if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
 			goto stall;
 			goto stall;
 		if (tmp == 0)
 		if (tmp == 0)
 			goto succeed;
 			goto succeed;
@@ -1551,7 +1552,7 @@ static irqreturn_t at91_vbus_irq(int irq, void *_udc)
 
 
 	/* vbus needs at least brief debouncing */
 	/* vbus needs at least brief debouncing */
 	udelay(10);
 	udelay(10);
-	value = at91_get_gpio_value(udc->board.vbus_pin);
+	value = gpio_get_value(udc->board.vbus_pin);
 	if (value != udc->vbus)
 	if (value != udc->vbus)
 		at91_vbus_session(&udc->gadget, value);
 		at91_vbus_session(&udc->gadget, value);
 
 
@@ -1616,6 +1617,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	local_irq_enable();
 	local_irq_enable();
 
 
 	driver->unbind(&udc->gadget);
 	driver->unbind(&udc->gadget);
+	udc->gadget.dev.driver = NULL;
+	udc->gadget.dev.driver_data = NULL;
 	udc->driver = NULL;
 	udc->driver = NULL;
 
 
 	DBG("unbound from %s\n", driver->driver.name);
 	DBG("unbound from %s\n", driver->driver.name);
@@ -1645,12 +1648,12 @@ static int __init at91udc_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	if (pdev->num_resources != 2) {
 	if (pdev->num_resources != 2) {
-		DBG("invalid num_resources");
+		DBG("invalid num_resources\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 	if ((pdev->resource[0].flags != IORESOURCE_MEM)
 	if ((pdev->resource[0].flags != IORESOURCE_MEM)
 			|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
 			|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-		DBG("invalid resource type");
+		DBG("invalid resource type\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -1672,10 +1675,26 @@ static int __init at91udc_probe(struct platform_device *pdev)
 	udc->pdev = pdev;
 	udc->pdev = pdev;
 	udc->enabled = 0;
 	udc->enabled = 0;
 
 
+	/* rm9200 needs manual D+ pullup; off by default */
+	if (cpu_is_at91rm9200()) {
+		if (udc->board.pullup_pin <= 0) {
+			DBG("no D+ pullup?\n");
+			retval = -ENODEV;
+			goto fail0;
+		}
+		retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
+		if (retval) {
+			DBG("D+ pullup is busy\n");
+			goto fail0;
+		}
+		gpio_direction_output(udc->board.pullup_pin,
+				udc->board.pullup_active_low);
+	}
+
 	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
 	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
 	if (!udc->udp_baseaddr) {
 	if (!udc->udp_baseaddr) {
-		release_mem_region(res->start, res->end - res->start + 1);
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto fail0a;
 	}
 	}
 
 
 	udc_reinit(udc);
 	udc_reinit(udc);
@@ -1686,12 +1705,13 @@ static int __init at91udc_probe(struct platform_device *pdev)
 	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
 	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
 		DBG("clocks missing\n");
 		DBG("clocks missing\n");
 		retval = -ENODEV;
 		retval = -ENODEV;
-		goto fail0;
+		/* NOTE: we "know" here that refcounts on these are NOPs */
+		goto fail0b;
 	}
 	}
 
 
 	retval = device_register(&udc->gadget.dev);
 	retval = device_register(&udc->gadget.dev);
 	if (retval < 0)
 	if (retval < 0)
-		goto fail0;
+		goto fail0b;
 
 
 	/* don't do anything until we have both gadget driver and VBUS */
 	/* don't do anything until we have both gadget driver and VBUS */
 	clk_enable(udc->iclk);
 	clk_enable(udc->iclk);
@@ -1703,25 +1723,32 @@ static int __init at91udc_probe(struct platform_device *pdev)
 
 
 	/* request UDC and maybe VBUS irqs */
 	/* request UDC and maybe VBUS irqs */
 	udc->udp_irq = platform_get_irq(pdev, 0);
 	udc->udp_irq = platform_get_irq(pdev, 0);
-	if (request_irq(udc->udp_irq, at91_udc_irq,
-			IRQF_DISABLED, driver_name, udc)) {
+	retval = request_irq(udc->udp_irq, at91_udc_irq,
+			IRQF_DISABLED, driver_name, udc);
+	if (retval < 0) {
 		DBG("request irq %d failed\n", udc->udp_irq);
 		DBG("request irq %d failed\n", udc->udp_irq);
-		retval = -EBUSY;
 		goto fail1;
 		goto fail1;
 	}
 	}
 	if (udc->board.vbus_pin > 0) {
 	if (udc->board.vbus_pin > 0) {
+		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
+		if (retval < 0) {
+			DBG("request vbus pin failed\n");
+			goto fail2;
+		}
+		gpio_direction_input(udc->board.vbus_pin);
+
 		/*
 		/*
 		 * Get the initial state of VBUS - we cannot expect
 		 * Get the initial state of VBUS - we cannot expect
 		 * a pending interrupt.
 		 * a pending interrupt.
 		 */
 		 */
-		udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
+		udc->vbus = gpio_get_value(udc->board.vbus_pin);
 		if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
 		if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
 				IRQF_DISABLED, driver_name, udc)) {
 				IRQF_DISABLED, driver_name, udc)) {
 			DBG("request vbus irq %d failed\n",
 			DBG("request vbus irq %d failed\n",
 					udc->board.vbus_pin);
 					udc->board.vbus_pin);
 			free_irq(udc->udp_irq, udc);
 			free_irq(udc->udp_irq, udc);
 			retval = -EBUSY;
 			retval = -EBUSY;
-			goto fail1;
+			goto fail3;
 		}
 		}
 	} else {
 	} else {
 		DBG("no VBUS detection, assuming always-on\n");
 		DBG("no VBUS detection, assuming always-on\n");
@@ -1734,8 +1761,18 @@ static int __init at91udc_probe(struct platform_device *pdev)
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
 	return 0;
 	return 0;
 
 
+fail3:
+	if (udc->board.vbus_pin > 0)
+		gpio_free(udc->board.vbus_pin);
+fail2:
+	free_irq(udc->udp_irq, udc);
 fail1:
 fail1:
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
+fail0b:
+	iounmap(udc->udp_baseaddr);
+fail0a:
+	if (cpu_is_at91rm9200())
+		gpio_free(udc->board.pullup_pin);
 fail0:
 fail0:
 	release_mem_region(res->start, res->end - res->start + 1);
 	release_mem_region(res->start, res->end - res->start + 1);
 	DBG("%s probe failed, %d\n", driver_name, retval);
 	DBG("%s probe failed, %d\n", driver_name, retval);
@@ -1756,12 +1793,18 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 
 
 	device_init_wakeup(&pdev->dev, 0);
 	device_init_wakeup(&pdev->dev, 0);
 	remove_debug_file(udc);
 	remove_debug_file(udc);
-	if (udc->board.vbus_pin > 0)
+	if (udc->board.vbus_pin > 0) {
 		free_irq(udc->board.vbus_pin, udc);
 		free_irq(udc->board.vbus_pin, udc);
+		gpio_free(udc->board.vbus_pin);
+	}
 	free_irq(udc->udp_irq, udc);
 	free_irq(udc->udp_irq, udc);
 	device_unregister(&udc->gadget.dev);
 	device_unregister(&udc->gadget.dev);
 
 
 	iounmap(udc->udp_baseaddr);
 	iounmap(udc->udp_baseaddr);
+
+	if (cpu_is_at91rm9200())
+		gpio_free(udc->board.pullup_pin);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, res->end - res->start + 1);
 	release_mem_region(res->start, res->end - res->start + 1);
 
 

+ 6 - 11
drivers/usb/gadget/at91_udc.h

@@ -53,7 +53,7 @@
 #define     AT91_UDP_RXRSM	(1 <<  9)	/* USB Resume Interrupt Status */
 #define     AT91_UDP_RXRSM	(1 <<  9)	/* USB Resume Interrupt Status */
 #define     AT91_UDP_EXTRSM	(1 << 10)	/* External Resume Interrupt Status [AT91RM9200 only] */
 #define     AT91_UDP_EXTRSM	(1 << 10)	/* External Resume Interrupt Status [AT91RM9200 only] */
 #define     AT91_UDP_SOFINT	(1 << 11)	/* Start of Frame Interrupt Status */
 #define     AT91_UDP_SOFINT	(1 << 11)	/* Start of Frame Interrupt Status */
-#define     AT91_UDP_ENDBUSRES	(1 << 12)	/* End of Bus Reset Interrpt Status */
+#define     AT91_UDP_ENDBUSRES	(1 << 12)	/* End of Bus Reset Interrupt Status */
 #define     AT91_UDP_WAKEUP	(1 << 13)	/* USB Wakeup Interrupt Status [AT91RM9200 only] */
 #define     AT91_UDP_WAKEUP	(1 << 13)	/* USB Wakeup Interrupt Status [AT91RM9200 only] */
 
 
 #define AT91_UDP_ICR		0x20		/* Interrupt Clear Register */
 #define AT91_UDP_ICR		0x20		/* Interrupt Clear Register */
@@ -158,13 +158,7 @@ struct at91_request {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "udc: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
-
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
 #    define VDBG		DBG
 #    define VDBG		DBG
 #else
 #else
 #    define VDBG(stuff...)	do{}while(0)
 #    define VDBG(stuff...)	do{}while(0)
@@ -176,9 +170,10 @@ struct at91_request {
 #    define PACKET(stuff...)	do{}while(0)
 #    define PACKET(stuff...)	do{}while(0)
 #endif
 #endif
 
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
+#define DBG(stuff...)		pr_debug("udc: " stuff)
 
 
 #endif
 #endif
 
 

+ 4 - 7
drivers/usb/gadget/atmel_usba_udc.c

@@ -1384,8 +1384,7 @@ delegate:
 	return retval;
 	return retval;
 
 
 stall:
 stall:
-	printk(KERN_ERR
-		"udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
+	pr_err("udc: %s: Invalid setup request: %02x.%02x v%04x i%04x l%d, "
 		"halting endpoint...\n",
 		"halting endpoint...\n",
 		ep->ep.name, crq->bRequestType, crq->bRequest,
 		ep->ep.name, crq->bRequestType, crq->bRequest,
 		le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
 		le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
@@ -1456,8 +1455,7 @@ restart:
 				set_protocol_stall(udc, ep);
 				set_protocol_stall(udc, ep);
 			break;
 			break;
 		default:
 		default:
-			printk(KERN_ERR
-				"udc: %s: TXCOMP: Invalid endpoint state %d, "
+			pr_err("udc: %s: TXCOMP: Invalid endpoint state %d, "
 				"halting endpoint...\n",
 				"halting endpoint...\n",
 				ep->ep.name, ep->state);
 				ep->ep.name, ep->state);
 			set_protocol_stall(udc, ep);
 			set_protocol_stall(udc, ep);
@@ -1486,8 +1484,7 @@ restart:
 		default:
 		default:
 			usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
 			usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
 			usba_ep_writel(ep, CTL_DIS, USBA_RX_BK_RDY);
-			printk(KERN_ERR
-				"udc: %s: RXRDY: Invalid endpoint state %d, "
+			pr_err("udc: %s: RXRDY: Invalid endpoint state %d, "
 				"halting endpoint...\n",
 				"halting endpoint...\n",
 				ep->ep.name, ep->state);
 				ep->ep.name, ep->state);
 			set_protocol_stall(udc, ep);
 			set_protocol_stall(udc, ep);
@@ -1532,7 +1529,7 @@ restart:
 		pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
 		pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
 		DBG(DBG_HW, "Packet length: %u\n", pkt_len);
 		DBG(DBG_HW, "Packet length: %u\n", pkt_len);
 		if (pkt_len != sizeof(crq)) {
 		if (pkt_len != sizeof(crq)) {
-			printk(KERN_WARNING "udc: Invalid packet length %u "
+			pr_warning("udc: Invalid packet length %u "
 				"(expected %lu)\n", pkt_len, sizeof(crq));
 				"(expected %lu)\n", pkt_len, sizeof(crq));
 			set_protocol_stall(udc, ep);
 			set_protocol_stall(udc, ep);
 			return;
 			return;

+ 2 - 5
drivers/usb/gadget/atmel_usba_udc.h

@@ -216,7 +216,6 @@
 #define FIFO_IOMEM_ID	0
 #define FIFO_IOMEM_ID	0
 #define CTRL_IOMEM_ID	1
 #define CTRL_IOMEM_ID	1
 
 
-#ifdef DEBUG
 #define DBG_ERR		0x0001	/* report all error returns */
 #define DBG_ERR		0x0001	/* report all error returns */
 #define DBG_HW		0x0002	/* debug hardware initialization */
 #define DBG_HW		0x0002	/* debug hardware initialization */
 #define DBG_GADGET	0x0004	/* calls to/from gadget driver */
 #define DBG_GADGET	0x0004	/* calls to/from gadget driver */
@@ -230,14 +229,12 @@
 #define DBG_NONE	0x0000
 #define DBG_NONE	0x0000
 
 
 #define DEBUG_LEVEL	(DBG_ERR)
 #define DEBUG_LEVEL	(DBG_ERR)
+
 #define DBG(level, fmt, ...)					\
 #define DBG(level, fmt, ...)					\
 	do {							\
 	do {							\
 		if ((level) & DEBUG_LEVEL)			\
 		if ((level) & DEBUG_LEVEL)			\
-			printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__);	\
+			pr_debug("udc: " fmt, ## __VA_ARGS__);	\
 	} while (0)
 	} while (0)
-#else
-#define DBG(level, fmt...)
-#endif
 
 
 enum usba_ctrl_state {
 enum usba_ctrl_state {
 	WAIT_FOR_SETUP,
 	WAIT_FOR_SETUP,

+ 11 - 27
drivers/usb/gadget/dummy_hcd.c

@@ -61,6 +61,8 @@
 #define DRIVER_DESC	"USB Host+Gadget Emulator"
 #define DRIVER_DESC	"USB Host+Gadget Emulator"
 #define DRIVER_VERSION	"02 May 2005"
 #define DRIVER_VERSION	"02 May 2005"
 
 
+#define POWER_BUDGET	500	/* in mA; use 8 for low-power port testing */
+
 static const char	driver_name [] = "dummy_hcd";
 static const char	driver_name [] = "dummy_hcd";
 static const char	driver_desc [] = "USB Host+Gadget Emulator";
 static const char	driver_desc [] = "USB Host+Gadget Emulator";
 
 
@@ -772,18 +774,17 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
 	list_del_init (&dum->ep [0].ep.ep_list);
 	list_del_init (&dum->ep [0].ep.ep_list);
 	INIT_LIST_HEAD(&dum->fifo_req.queue);
 	INIT_LIST_HEAD(&dum->fifo_req.queue);
 
 
+	driver->driver.bus = NULL;
 	dum->driver = driver;
 	dum->driver = driver;
 	dum->gadget.dev.driver = &driver->driver;
 	dum->gadget.dev.driver = &driver->driver;
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 	dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
 			driver->driver.name);
 			driver->driver.name);
-	if ((retval = driver->bind (&dum->gadget)) != 0)
-		goto err_bind_gadget;
-
-	driver->driver.bus = dum->gadget.dev.parent->bus;
-	if ((retval = driver_register (&driver->driver)) != 0)
-		goto err_register;
-	if ((retval = device_bind_driver (&dum->gadget.dev)) != 0)
-		goto err_bind_driver;
+	retval = driver->bind(&dum->gadget);
+	if (retval) {
+		dum->driver = NULL;
+		dum->gadget.dev.driver = NULL;
+		return retval;
+	}
 
 
 	/* khubd will enumerate this in a while */
 	/* khubd will enumerate this in a while */
 	spin_lock_irq (&dum->lock);
 	spin_lock_irq (&dum->lock);
@@ -793,20 +794,6 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
 
 
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	usb_hcd_poll_rh_status (dummy_to_hcd (dum));
 	return 0;
 	return 0;
-
-err_bind_driver:
-	driver_unregister (&driver->driver);
-err_register:
-	if (driver->unbind)
-		driver->unbind (&dum->gadget);
-	spin_lock_irq (&dum->lock);
-	dum->pullup = 0;
-	set_link_state (dum);
-	spin_unlock_irq (&dum->lock);
-err_bind_gadget:
-	dum->driver = NULL;
-	dum->gadget.dev.driver = NULL;
-	return retval;
 }
 }
 EXPORT_SYMBOL (usb_gadget_register_driver);
 EXPORT_SYMBOL (usb_gadget_register_driver);
 
 
@@ -830,11 +817,9 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore (&dum->lock, flags);
 	spin_unlock_irqrestore (&dum->lock, flags);
 
 
 	driver->unbind (&dum->gadget);
 	driver->unbind (&dum->gadget);
+	dum->gadget.dev.driver = NULL;
 	dum->driver = NULL;
 	dum->driver = NULL;
 
 
-	device_release_driver (&dum->gadget.dev);
-	driver_unregister (&driver->driver);
-
 	spin_lock_irqsave (&dum->lock, flags);
 	spin_lock_irqsave (&dum->lock, flags);
 	dum->pullup = 0;
 	dum->pullup = 0;
 	set_link_state (dum);
 	set_link_state (dum);
@@ -1827,8 +1812,7 @@ static int dummy_start (struct usb_hcd *hcd)
 
 
 	INIT_LIST_HEAD (&dum->urbp_list);
 	INIT_LIST_HEAD (&dum->urbp_list);
 
 
-	/* only show a low-power port: just 8mA */
-	hcd->power_budget = 8;
+	hcd->power_budget = POWER_BUDGET;
 	hcd->state = HC_STATE_RUNNING;
 	hcd->state = HC_STATE_RUNNING;
 	hcd->uses_new_polling = 1;
 	hcd->uses_new_polling = 1;
 
 

+ 3 - 3
drivers/usb/gadget/ether.c

@@ -1067,19 +1067,19 @@ done:
 
 
 	/* on error, disable any endpoints  */
 	/* on error, disable any endpoints  */
 	if (result < 0) {
 	if (result < 0) {
-		if (!subset_active(dev))
+		if (!subset_active(dev) && dev->status_ep)
 			(void) usb_ep_disable (dev->status_ep);
 			(void) usb_ep_disable (dev->status_ep);
 		dev->status = NULL;
 		dev->status = NULL;
 		(void) usb_ep_disable (dev->in_ep);
 		(void) usb_ep_disable (dev->in_ep);
 		(void) usb_ep_disable (dev->out_ep);
 		(void) usb_ep_disable (dev->out_ep);
 		dev->in = NULL;
 		dev->in = NULL;
 		dev->out = NULL;
 		dev->out = NULL;
-	} else
+	}
 
 
 	/* activate non-CDC configs right away
 	/* activate non-CDC configs right away
 	 * this isn't strictly according to the RNDIS spec
 	 * this isn't strictly according to the RNDIS spec
 	 */
 	 */
-	if (!cdc_active (dev)) {
+	else if (!cdc_active (dev)) {
 		netif_carrier_on (dev->net);
 		netif_carrier_on (dev->net);
 		if (netif_running (dev->net)) {
 		if (netif_running (dev->net)) {
 			spin_unlock (&dev->lock);
 			spin_unlock (&dev->lock);

+ 5 - 9
drivers/usb/gadget/file_storage.c

@@ -275,19 +275,15 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-#ifdef DEBUG
 #define LDBG(lun,fmt,args...) \
 #define LDBG(lun,fmt,args...) \
 	dev_dbg(&(lun)->dev , fmt , ## args)
 	dev_dbg(&(lun)->dev , fmt , ## args)
 #define MDBG(fmt,args...) \
 #define MDBG(fmt,args...) \
-	printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
-#else
-#define LDBG(lun,fmt,args...) \
-	do { } while (0)
-#define MDBG(fmt,args...) \
-	do { } while (0)
+	pr_debug(DRIVER_NAME ": " fmt , ## args)
+
+#ifndef DEBUG
 #undef VERBOSE_DEBUG
 #undef VERBOSE_DEBUG
 #undef DUMP_MSGS
 #undef DUMP_MSGS
-#endif /* DEBUG */
+#endif /* !DEBUG */
 
 
 #ifdef VERBOSE_DEBUG
 #ifdef VERBOSE_DEBUG
 #define VLDBG	LDBG
 #define VLDBG	LDBG
@@ -304,7 +300,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 	dev_info(&(lun)->dev , fmt , ## args)
 	dev_info(&(lun)->dev , fmt , ## args)
 
 
 #define MINFO(fmt,args...) \
 #define MINFO(fmt,args...) \
-	printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
+	pr_info(DRIVER_NAME ": " fmt , ## args)
 
 
 #define DBG(d, fmt, args...) \
 #define DBG(d, fmt, args...) \
 	dev_dbg(&(d)->gadget->dev , fmt , ## args)
 	dev_dbg(&(d)->gadget->dev , fmt , ## args)

+ 2 - 2
drivers/usb/gadget/fsl_usb2_udc.c

@@ -776,7 +776,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 		VDBG("%s, bad params\n", __FUNCTION__);
 		VDBG("%s, bad params\n", __FUNCTION__);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	if (!_ep || (!ep->desc && ep_index(ep))) {
+	if (unlikely(!_ep || !ep->desc)) {
 		VDBG("%s, bad ep\n", __FUNCTION__);
 		VDBG("%s, bad ep\n", __FUNCTION__);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -1896,7 +1896,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
 
 
 	spin_lock_irqsave(&udc->lock, flags);
 	spin_lock_irqsave(&udc->lock, flags);
 
 
-	/* ------basic driver infomation ---- */
+	/* ------basic driver information ---- */
 	t = scnprintf(next, size,
 	t = scnprintf(next, size,
 			DRIVER_DESC "\n"
 			DRIVER_DESC "\n"
 			"%s version: %s\n"
 			"%s version: %s\n"

+ 3 - 3
drivers/usb/gadget/fsl_usb2_udc.h

@@ -551,9 +551,9 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length)
 #define VDBG(stuff...)	do{}while(0)
 #define VDBG(stuff...)	do{}while(0)
 #endif
 #endif
 
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 3 - 3
drivers/usb/gadget/gmidi.c

@@ -1158,7 +1158,7 @@ static int __devinit gmidi_bind(struct usb_gadget *gadget)
 	/* support optional vendor/distro customization */
 	/* support optional vendor/distro customization */
 	if (idVendor) {
 	if (idVendor) {
 		if (!idProduct) {
 		if (!idProduct) {
-			printk(KERN_ERR "idVendor needs idProduct!\n");
+			pr_err("idVendor needs idProduct!\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		device_desc.idVendor = cpu_to_le16(idVendor);
 		device_desc.idVendor = cpu_to_le16(idVendor);
@@ -1190,7 +1190,7 @@ static int __devinit gmidi_bind(struct usb_gadget *gadget)
 	in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
 	in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
 	if (!in_ep) {
 	if (!in_ep) {
 autoconf_fail:
 autoconf_fail:
-		printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+		pr_err("%s: can't autoconfigure on %s\n",
 			shortname, gadget->name);
 			shortname, gadget->name);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1212,7 +1212,7 @@ autoconf_fail:
 		 * it SHOULD NOT have problems with bulk-capable hardware.
 		 * it SHOULD NOT have problems with bulk-capable hardware.
 		 * so warn about unrecognized controllers, don't panic.
 		 * so warn about unrecognized controllers, don't panic.
 		 */
 		 */
-		printk(KERN_WARNING "%s: controller '%s' not recognized\n",
+		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
 			shortname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 	}

+ 1 - 0
drivers/usb/gadget/goku_udc.c

@@ -1422,6 +1422,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
 	driver->unbind(&dev->gadget);
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 
 
 	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
 	return 0;
 	return 0;

+ 1 - 1
drivers/usb/gadget/inode.c

@@ -1699,7 +1699,7 @@ gadgetfs_bind (struct usb_gadget *gadget)
 	if (!dev)
 	if (!dev)
 		return -ESRCH;
 		return -ESRCH;
 	if (0 != strcmp (CHIP, gadget->name)) {
 	if (0 != strcmp (CHIP, gadget->name)) {
-		printk (KERN_ERR "%s expected %s controller not %s\n",
+		pr_err("%s expected %s controller not %s\n",
 			shortname, CHIP, gadget->name);
 			shortname, CHIP, gadget->name);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}

+ 1 - 0
drivers/usb/gadget/lh7a40x_udc.c

@@ -474,6 +474,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	spin_unlock_irqrestore(&dev->lock, flags);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 
 	driver->unbind(&dev->gadget);
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	device_del(&dev->gadget.dev);
 	device_del(&dev->gadget.dev);
 
 
 	udc_disable(dev);
 	udc_disable(dev);

+ 79 - 25
drivers/usb/gadget/m66592-udc.c

@@ -36,9 +36,14 @@ MODULE_DESCRIPTION("M66592 USB gadget driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 MODULE_AUTHOR("Yoshihiro Shimoda");
 
 
-#define DRIVER_VERSION	"29 May 2007"
+#define DRIVER_VERSION	"18 Oct 2007"
 
 
 /* module parameters */
 /* module parameters */
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static unsigned short endian = M66592_LITTLE;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)");
+#else
 static unsigned short clock = M66592_XTAL24;
 static unsigned short clock = M66592_XTAL24;
 module_param(clock, ushort, 0644);
 module_param(clock, ushort, 0644);
 MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
 MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 "
@@ -56,6 +61,7 @@ static unsigned short irq_sense = M66592_INTL;
 module_param(irq_sense, ushort, 0644);
 module_param(irq_sense, ushort, 0644);
 MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
 MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
 		"(default=2)");
 		"(default=2)");
+#endif
 
 
 static const char udc_name[] = "m66592_udc";
 static const char udc_name[] = "m66592_udc";
 static const char *m66592_ep_name[] = {
 static const char *m66592_ep_name[] = {
@@ -141,7 +147,7 @@ static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
 		offset = get_pipectr_addr(pipenum);
 		offset = get_pipectr_addr(pipenum);
 		pid = m66592_read(m66592, offset) & M66592_PID;
 		pid = m66592_read(m66592, offset) & M66592_PID;
 	} else
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 
 
 	return pid;
 	return pid;
 }
 }
@@ -157,7 +163,7 @@ static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
 		offset = get_pipectr_addr(pipenum);
 		offset = get_pipectr_addr(pipenum);
 		m66592_mdfy(m66592, pid, M66592_PID, offset);
 		m66592_mdfy(m66592, pid, M66592_PID, offset);
 	} else
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 }
 }
 
 
 static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
 static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
@@ -186,7 +192,7 @@ static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
 		offset = get_pipectr_addr(pipenum);
 		offset = get_pipectr_addr(pipenum);
 		ret = m66592_read(m66592, offset);
 		ret = m66592_read(m66592, offset);
 	} else
 	} else
-		printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+		pr_err("unexpect pipe num (%d)\n", pipenum);
 
 
 	return ret;
 	return ret;
 }
 }
@@ -203,7 +209,7 @@ static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
 		offset = get_pipectr_addr(pipenum);
 		offset = get_pipectr_addr(pipenum);
 		m66592_bset(m66592, M66592_SQCLR, offset);
 		m66592_bset(m66592, M66592_SQCLR, offset);
 	} else
 	} else
-		printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+		pr_err("unexpect pipe num(%d)\n", pipenum);
 }
 }
 
 
 static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
 static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
@@ -285,7 +291,7 @@ static int pipe_buffer_setting(struct m66592 *m66592,
 		break;
 		break;
 	}
 	}
 	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
 	if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
-		printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
+		pr_err("m66592 pipe memory is insufficient(%d)\n",
 				m66592->bi_bufnum);
 				m66592->bi_bufnum);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -326,7 +332,7 @@ static void pipe_buffer_release(struct m66592 *m66592,
 		if (info->type == M66592_BULK)
 		if (info->type == M66592_BULK)
 			m66592->bulk--;
 			m66592->bulk--;
 	} else
 	} else
-		printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+		pr_err("ep_release: unexpect pipenum (%d)\n",
 				info->pipe);
 				info->pipe);
 }
 }
 
 
@@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
 			ep->fifosel = M66592_D0FIFOSEL;
 			ep->fifosel = M66592_D0FIFOSEL;
 			ep->fifoctr = M66592_D0FIFOCTR;
 			ep->fifoctr = M66592_D0FIFOCTR;
 			ep->fifotrn = M66592_D0FIFOTRN;
 			ep->fifotrn = M66592_D0FIFOTRN;
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
 		} else if (m66592->num_dma == 1) {
 		} else if (m66592->num_dma == 1) {
 			m66592->num_dma++;
 			m66592->num_dma++;
 			ep->use_dma = 1;
 			ep->use_dma = 1;
@@ -367,6 +374,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
 			ep->fifosel = M66592_D1FIFOSEL;
 			ep->fifosel = M66592_D1FIFOSEL;
 			ep->fifoctr = M66592_D1FIFOCTR;
 			ep->fifoctr = M66592_D1FIFOCTR;
 			ep->fifotrn = M66592_D1FIFOTRN;
 			ep->fifotrn = M66592_D1FIFOTRN;
+#endif
 		} else {
 		} else {
 			ep->use_dma = 0;
 			ep->use_dma = 0;
 			ep->fifoaddr = M66592_CFIFO;
 			ep->fifoaddr = M66592_CFIFO;
@@ -422,7 +430,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 	case USB_ENDPOINT_XFER_BULK:
 	case USB_ENDPOINT_XFER_BULK:
 		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
 		if (m66592->bulk >= M66592_MAX_NUM_BULK) {
 			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
 			if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-				printk(KERN_ERR "bulk pipe is insufficient\n");
+				pr_err("bulk pipe is insufficient\n");
 				return -ENODEV;
 				return -ENODEV;
 			} else {
 			} else {
 				info.pipe = M66592_BASE_PIPENUM_ISOC
 				info.pipe = M66592_BASE_PIPENUM_ISOC
@@ -438,7 +446,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 		break;
 		break;
 	case USB_ENDPOINT_XFER_INT:
 	case USB_ENDPOINT_XFER_INT:
 		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
 		if (m66592->interrupt >= M66592_MAX_NUM_INT) {
-			printk(KERN_ERR "interrupt pipe is insufficient\n");
+			pr_err("interrupt pipe is insufficient\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
 		info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
@@ -447,7 +455,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 		break;
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
 	case USB_ENDPOINT_XFER_ISOC:
 		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
 		if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
-			printk(KERN_ERR "isochronous pipe is insufficient\n");
+			pr_err("isochronous pipe is insufficient\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
 		info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
@@ -455,7 +463,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 		counter = &m66592->isochronous;
 		counter = &m66592->isochronous;
 		break;
 		break;
 	default:
 	default:
-		printk(KERN_ERR "unexpect xfer type\n");
+		pr_err("unexpect xfer type\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	ep->type = info.type;
 	ep->type = info.type;
@@ -470,7 +478,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
 
 
 	ret = pipe_buffer_setting(m66592, &info);
 	ret = pipe_buffer_setting(m66592, &info);
 	if (ret < 0) {
 	if (ret < 0) {
-		printk(KERN_ERR "pipe_buffer_setting fail\n");
+		pr_err("pipe_buffer_setting fail\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -606,11 +614,33 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
 		control_end(ep->m66592, 0);
 		control_end(ep->m66592, 0);
 		break;
 		break;
 	default:
 	default:
-		printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+		pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
 		break;
 		break;
 	}
 	}
 }
 }
 
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+static void init_controller(struct m66592 *m66592)
+{
+	usbf_start_clock();
+	m66592_bset(m66592, M66592_HSE, M66592_SYSCFG);		/* High spd */
+	m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+	m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+	m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+	/* This is a workaound for SH7722 2nd cut */
+	m66592_bset(m66592, 0x8000, M66592_DVSTCTR);
+	m66592_bset(m66592, 0x1000, M66592_TESTMODE);
+	m66592_bclr(m66592, 0x8000, M66592_DVSTCTR);
+
+	m66592_bset(m66592, M66592_INTL, M66592_INTENB1);
+
+	m66592_write(m66592, 0, M66592_CFBCFG);
+	m66592_write(m66592, 0, M66592_D0FBCFG);
+	m66592_bset(m66592, endian, M66592_CFBCFG);
+	m66592_bset(m66592, endian, M66592_D0FBCFG);
+}
+#else	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 static void init_controller(struct m66592 *m66592)
 static void init_controller(struct m66592 *m66592)
 {
 {
 	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
 	m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
@@ -636,9 +666,13 @@ static void init_controller(struct m66592 *m66592)
 	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
 	m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
 			M66592_DMA0CFG);
 			M66592_DMA0CFG);
 }
 }
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 
 static void disable_controller(struct m66592 *m66592)
 static void disable_controller(struct m66592 *m66592)
 {
 {
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	usbf_stop_clock();
+#else
 	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
 	m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
 	udelay(1);
 	udelay(1);
 	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
 	m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
@@ -646,15 +680,20 @@ static void disable_controller(struct m66592 *m66592)
 	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
 	m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
 	udelay(1);
 	udelay(1);
 	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
 	m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 }
 
 
 static void m66592_start_xclock(struct m66592 *m66592)
 static void m66592_start_xclock(struct m66592 *m66592)
 {
 {
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	usbf_start_clock();
+#else
 	u16 tmp;
 	u16 tmp;
 
 
 	tmp = m66592_read(m66592, M66592_SYSCFG);
 	tmp = m66592_read(m66592, M66592_SYSCFG);
 	if (!(tmp & M66592_XCKE))
 	if (!(tmp & M66592_XCKE))
 		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
 		m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -709,7 +748,7 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
 	do {
 	do {
 		tmp = m66592_read(m66592, ep->fifoctr);
 		tmp = m66592_read(m66592, ep->fifoctr);
 		if (i++ > 100000) {
 		if (i++ > 100000) {
-			printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+			pr_err("pipe0 is busy. maybe cpu i/o bus "
 				"conflict. please power off this controller.");
 				"conflict. please power off this controller.");
 			return;
 			return;
 		}
 		}
@@ -759,7 +798,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
 	if (unlikely((tmp & M66592_FRDY) == 0)) {
 	if (unlikely((tmp & M66592_FRDY) == 0)) {
 		pipe_stop(m66592, pipenum);
 		pipe_stop(m66592, pipenum);
 		pipe_irq_disable(m66592, pipenum);
 		pipe_irq_disable(m66592, pipenum);
-		printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+		pr_err("write fifo not ready. pipnum=%d\n", pipenum);
 		return;
 		return;
 	}
 	}
 
 
@@ -808,7 +847,7 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
 		req->req.status = -EPIPE;
 		req->req.status = -EPIPE;
 		pipe_stop(m66592, pipenum);
 		pipe_stop(m66592, pipenum);
 		pipe_irq_disable(m66592, pipenum);
 		pipe_irq_disable(m66592, pipenum);
-		printk(KERN_ERR "read fifo not ready");
+		pr_err("read fifo not ready");
 		return;
 		return;
 	}
 	}
 
 
@@ -1063,7 +1102,7 @@ static void m66592_update_usb_speed(struct m66592 *m66592)
 		break;
 		break;
 	default:
 	default:
 		m66592->gadget.speed = USB_SPEED_UNKNOWN;
 		m66592->gadget.speed = USB_SPEED_UNKNOWN;
-		printk(KERN_ERR "USB speed unknown\n");
+		pr_err("USB speed unknown\n");
 	}
 	}
 }
 }
 
 
@@ -1122,7 +1161,7 @@ __acquires(m66592->lock)
 		control_end(m66592, 0);
 		control_end(m66592, 0);
 		break;
 		break;
 	default:
 	default:
-		printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+		pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
 	intsts0 = m66592_read(m66592, M66592_INTSTS0);
 	intsts0 = m66592_read(m66592, M66592_INTSTS0);
 	intenb0 = m66592_read(m66592, M66592_INTENB0);
 	intenb0 = m66592_read(m66592, M66592_INTENB0);
 
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	if (!intsts0 && !intenb0) {
+		/*
+		 * When USB clock stops, it cannot read register. Even if a
+		 * clock stops, the interrupt occurs. So this driver turn on
+		 * a clock by this timing and do re-reading of register.
+		 */
+		m66592_start_xclock(m66592);
+		intsts0 = m66592_read(m66592, M66592_INTSTS0);
+		intenb0 = m66592_read(m66592, M66592_INTENB0);
+	}
+#endif
+
 	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 	savepipe = m66592_read(m66592, M66592_CFIFOSEL);
 
 
 	mask0 = intsts0 & intenb0;
 	mask0 = intsts0 & intenb0;
@@ -1409,13 +1461,13 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 
 
 	retval = device_add(&m66592->gadget.dev);
 	retval = device_add(&m66592->gadget.dev);
 	if (retval) {
 	if (retval) {
-		printk(KERN_ERR "device_add error (%d)\n", retval);
+		pr_err("device_add error (%d)\n", retval);
 		goto error;
 		goto error;
 	}
 	}
 
 
 	retval = driver->bind (&m66592->gadget);
 	retval = driver->bind (&m66592->gadget);
 	if (retval) {
 	if (retval) {
-		printk(KERN_ERR "bind to driver error (%d)\n", retval);
+		pr_err("bind to driver error (%d)\n", retval);
 		device_del(&m66592->gadget.dev);
 		device_del(&m66592->gadget.dev);
 		goto error;
 		goto error;
 	}
 	}
@@ -1456,6 +1508,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 	m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
 
 	driver->unbind(&m66592->gadget);
 	driver->unbind(&m66592->gadget);
+	m66592->gadget.dev.driver = NULL;
 
 
 	init_controller(m66592);
 	init_controller(m66592);
 	disable_controller(m66592);
 	disable_controller(m66592);
@@ -1485,6 +1538,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
 	iounmap(m66592->reg);
 	iounmap(m66592->reg);
 	free_irq(platform_get_irq(pdev, 0), m66592);
 	free_irq(platform_get_irq(pdev, 0), m66592);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 	m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+	usbf_stop_clock();
 	kfree(m66592);
 	kfree(m66592);
 	return 0;
 	return 0;
 }
 }
@@ -1508,28 +1562,28 @@ static int __init m66592_probe(struct platform_device *pdev)
 			(char *)udc_name);
 			(char *)udc_name);
 	if (!res) {
 	if (!res) {
 		ret = -ENODEV;
 		ret = -ENODEV;
-		printk(KERN_ERR "platform_get_resource_byname error.\n");
+		pr_err("platform_get_resource_byname error.\n");
 		goto clean_up;
 		goto clean_up;
 	}
 	}
 
 
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
 		ret = -ENODEV;
 		ret = -ENODEV;
-		printk(KERN_ERR "platform_get_irq error.\n");
+		pr_err("platform_get_irq error.\n");
 		goto clean_up;
 		goto clean_up;
 	}
 	}
 
 
 	reg = ioremap(res->start, resource_len(res));
 	reg = ioremap(res->start, resource_len(res));
 	if (reg == NULL) {
 	if (reg == NULL) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		printk(KERN_ERR "ioremap error.\n");
+		pr_err("ioremap error.\n");
 		goto clean_up;
 		goto clean_up;
 	}
 	}
 
 
 	/* initialize ucd */
 	/* initialize ucd */
 	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
 	m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
 	if (m66592 == NULL) {
 	if (m66592 == NULL) {
-		printk(KERN_ERR "kzalloc error\n");
+		pr_err("kzalloc error\n");
 		goto clean_up;
 		goto clean_up;
 	}
 	}
 
 
@@ -1555,7 +1609,7 @@ static int __init m66592_probe(struct platform_device *pdev)
 	ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
 	ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
 			udc_name, m66592);
 			udc_name, m66592);
 	if (ret < 0) {
 	if (ret < 0) {
-		printk(KERN_ERR "request_irq error (%d)\n", ret);
+		pr_err("request_irq error (%d)\n", ret);
 		goto clean_up;
 		goto clean_up;
 	}
 	}
 
 

+ 54 - 0
drivers/usb/gadget/m66592-udc.h

@@ -72,6 +72,11 @@
 #define   M66592_P_TST_J	 0x0001		/* PERI TEST J */
 #define   M66592_P_TST_J	 0x0001		/* PERI TEST J */
 #define   M66592_P_TST_NORMAL	 0x0000		/* PERI Normal Mode */
 #define   M66592_P_TST_NORMAL	 0x0000		/* PERI Normal Mode */
 
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#define M66592_CFBCFG		0x0A
+#define M66592_D0FBCFG		0x0C
+#define M66592_LITTLE		0x0100	/* b8: Little endian mode */
+#else
 #define M66592_PINCFG		0x0A
 #define M66592_PINCFG		0x0A
 #define M66592_LDRV		0x8000	/* b15: Drive Current Adjust */
 #define M66592_LDRV		0x8000	/* b15: Drive Current Adjust */
 #define M66592_BIGEND		0x0100	/* b8: Big endian mode */
 #define M66592_BIGEND		0x0100	/* b8: Big endian mode */
@@ -91,6 +96,7 @@
 #define M66592_PKTM		0x0020	/* b5: Packet mode */
 #define M66592_PKTM		0x0020	/* b5: Packet mode */
 #define M66592_DENDE		0x0010	/* b4: Dend enable */
 #define M66592_DENDE		0x0010	/* b4: Dend enable */
 #define M66592_OBUS		0x0004	/* b2: OUTbus mode */
 #define M66592_OBUS		0x0004	/* b2: OUTbus mode */
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 
 
 #define M66592_CFIFO		0x10
 #define M66592_CFIFO		0x10
 #define M66592_D0FIFO		0x14
 #define M66592_D0FIFO		0x14
@@ -103,9 +109,13 @@
 #define M66592_REW		0x4000	/* b14: Buffer rewind */
 #define M66592_REW		0x4000	/* b14: Buffer rewind */
 #define M66592_DCLRM		0x2000	/* b13: DMA buffer clear mode */
 #define M66592_DCLRM		0x2000	/* b13: DMA buffer clear mode */
 #define M66592_DREQE		0x1000	/* b12: DREQ output enable */
 #define M66592_DREQE		0x1000	/* b12: DREQ output enable */
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#define M66592_MBW		0x0800	/* b11: Maximum bit width for FIFO */
+#else
 #define M66592_MBW		0x0400	/* b10: Maximum bit width for FIFO */
 #define M66592_MBW		0x0400	/* b10: Maximum bit width for FIFO */
 #define   M66592_MBW_8		 0x0000   /*  8bit */
 #define   M66592_MBW_8		 0x0000   /*  8bit */
 #define   M66592_MBW_16		 0x0400   /* 16bit */
 #define   M66592_MBW_16		 0x0400   /* 16bit */
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 #define M66592_TRENB		0x0200	/* b9: Transaction counter enable */
 #define M66592_TRENB		0x0200	/* b9: Transaction counter enable */
 #define M66592_TRCLR		0x0100	/* b8: Transaction counter clear */
 #define M66592_TRCLR		0x0100	/* b8: Transaction counter clear */
 #define M66592_DEZPM		0x0080	/* b7: Zero-length packet mode */
 #define M66592_DEZPM		0x0080	/* b7: Zero-length packet mode */
@@ -530,8 +540,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592,
 {
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	len = (len + 3) / 4;
+	insl(fifoaddr, buf, len);
+#else
 	len = (len + 1) / 2;
 	len = (len + 1) / 2;
 	insw(fifoaddr, buf, len);
 	insw(fifoaddr, buf, len);
+#endif
 }
 }
 
 
 static inline void m66592_write(struct m66592 *m66592, u16 val,
 static inline void m66592_write(struct m66592 *m66592, u16 val,
@@ -545,6 +560,24 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
 		void *buf, unsigned long len)
 		void *buf, unsigned long len)
 {
 {
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
 	unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+	unsigned long count;
+	unsigned char *pb;
+	int i;
+
+	count = len / 4;
+	outsl(fifoaddr, buf, count);
+
+	if (len & 0x00000003) {
+		pb = buf + count * 4;
+		for (i = 0; i < (len & 0x00000003); i++) {
+			if (m66592_read(m66592, M66592_CFBCFG))	/* little */
+				outb(pb[i], fifoaddr + (3 - i));
+			else
+				outb(pb[i], fifoaddr + i);
+		}
+	}
+#else
 	unsigned long odd = len & 0x0001;
 	unsigned long odd = len & 0x0001;
 
 
 	len = len / 2;
 	len = len / 2;
@@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
 		unsigned char *p = buf + len*2;
 		unsigned char *p = buf + len*2;
 		outb(*p, fifoaddr);
 		outb(*p, fifoaddr);
 	}
 	}
+#endif	/* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
 }
 }
 
 
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
 static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
@@ -570,6 +604,26 @@ static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
 #define m66592_bset(m66592, val, offset)	\
 #define m66592_bset(m66592, val, offset)	\
 			m66592_mdfy(m66592, val, 0, offset)
 			m66592_mdfy(m66592, val, 0, offset)
 
 
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+#include <asm/io.h>
+#define MSTPCR2		0xA4150038	/* for SH7722 */
+#define MSTPCR2_USB	0x00000800
+
+static inline void usbf_start_clock(void)
+{
+	ctrl_outl(ctrl_inl(MSTPCR2) & ~MSTPCR2_USB, MSTPCR2);
+}
+
+static inline void usbf_stop_clock(void)
+{
+	ctrl_outl(ctrl_inl(MSTPCR2) | MSTPCR2_USB, MSTPCR2);
+}
+
+#else
+#define usbf_start_clock(x)
+#define usbf_stop_clock(x)
+#endif	/* if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
+
 #endif	/* ifndef __M66592_UDC_H__ */
 #endif	/* ifndef __M66592_UDC_H__ */
 
 
 
 

+ 1 - 1
drivers/usb/gadget/net2280.c

@@ -2435,7 +2435,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			break;
 			break;
 		default:
 		default:
 delegate:
 delegate:
-			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x"
+			VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x "
 				"ep_cfg %08x\n",
 				"ep_cfg %08x\n",
 				u.r.bRequestType, u.r.bRequest,
 				u.r.bRequestType, u.r.bRequest,
 				w_value, w_index, w_length,
 				w_value, w_index, w_length,

+ 50 - 23
drivers/usb/gadget/omap_udc.c

@@ -4,6 +4,8 @@
  * Copyright (C) 2004 Texas Instruments, Inc.
  * Copyright (C) 2004 Texas Instruments, Inc.
  * Copyright (C) 2004-2005 David Brownell
  * Copyright (C) 2004-2005 David Brownell
  *
  *
+ * OMAP2 & DMA support by Kyungmin Park <kyungmin.park@samsung.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * the Free Software Foundation; either version 2 of the License, or
@@ -60,11 +62,6 @@
 /* bulk DMA seems to be behaving for both IN and OUT */
 /* bulk DMA seems to be behaving for both IN and OUT */
 #define	USE_DMA
 #define	USE_DMA
 
 
-/* FIXME: OMAP2 currently has some problem in DMA mode */
-#ifdef CONFIG_ARCH_OMAP2
-#undef USE_DMA
-#endif
-
 /* ISO too */
 /* ISO too */
 #define	USE_ISO
 #define	USE_ISO
 
 
@@ -73,6 +70,8 @@
 
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
 
+#define OMAP2_DMA_CH(ch)	(((ch) - 1) << 1)
+#define OMAP24XX_DMA(name, ch)	(OMAP24XX_DMA_##name + OMAP2_DMA_CH(ch))
 
 
 /*
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
@@ -571,20 +570,25 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
 	const int	sync_mode = cpu_is_omap15xx()
 	const int	sync_mode = cpu_is_omap15xx()
 				? OMAP_DMA_SYNC_FRAME
 				? OMAP_DMA_SYNC_FRAME
 				: OMAP_DMA_SYNC_ELEMENT;
 				: OMAP_DMA_SYNC_ELEMENT;
+	int		dma_trigger = 0;
+
+	if (cpu_is_omap24xx())
+		dma_trigger = OMAP24XX_DMA(USB_W2FC_TX0, ep->dma_channel);
 
 
 	/* measure length in either bytes or packets */
 	/* measure length in either bytes or packets */
 	if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
 	if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
+			|| (cpu_is_omap24xx() && length < ep->maxpacket)
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 		txdma_ctrl = UDC_TXN_EOT | length;
 		txdma_ctrl = UDC_TXN_EOT | length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				length, 1, sync_mode, 0, 0);
+				length, 1, sync_mode, dma_trigger, 0);
 	} else {
 	} else {
 		length = min(length / ep->maxpacket,
 		length = min(length / ep->maxpacket,
 				(unsigned) UDC_TXN_TSC + 1);
 				(unsigned) UDC_TXN_TSC + 1);
 		txdma_ctrl = length;
 		txdma_ctrl = length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
 				ep->ep.maxpacket >> 1, length, sync_mode,
 				ep->ep.maxpacket >> 1, length, sync_mode,
-				0, 0);
+				dma_trigger, 0);
 		length *= ep->maxpacket;
 		length *= ep->maxpacket;
 	}
 	}
 	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
@@ -622,20 +626,31 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
 
 
 static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
 {
 {
-	unsigned packets;
+	unsigned packets = req->req.length - req->req.actual;
+	int dma_trigger = 0;
+
+	if (cpu_is_omap24xx())
+		dma_trigger = OMAP24XX_DMA(USB_W2FC_RX0, ep->dma_channel);
 
 
 	/* NOTE:  we filtered out "short reads" before, so we know
 	/* NOTE:  we filtered out "short reads" before, so we know
 	 * the buffer has only whole numbers of packets.
 	 * the buffer has only whole numbers of packets.
+	 * except MODE SELECT(6) sent the 24 bytes data in OMAP24XX DMA mode
 	 */
 	 */
-
-	/* set up this DMA transfer, enable the fifo, start */
-	packets = (req->req.length - req->req.actual) / ep->ep.maxpacket;
-	packets = min(packets, (unsigned)UDC_RXN_TC + 1);
-	req->dma_bytes = packets * ep->ep.maxpacket;
-	omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
-			ep->ep.maxpacket >> 1, packets,
-			OMAP_DMA_SYNC_ELEMENT,
-			0, 0);
+	if (cpu_is_omap24xx() && packets < ep->maxpacket) {
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
+				packets, 1, OMAP_DMA_SYNC_ELEMENT,
+				dma_trigger, 0);
+		req->dma_bytes = packets;
+	} else {
+		/* set up this DMA transfer, enable the fifo, start */
+		packets /= ep->ep.maxpacket;
+		packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+		req->dma_bytes = packets * ep->ep.maxpacket;
+		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
+				ep->ep.maxpacket >> 1, packets,
+				OMAP_DMA_SYNC_ELEMENT,
+				dma_trigger, 0);
+	}
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
 		0, 0);
 		0, 0);
@@ -743,6 +758,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 {
 {
 	u16	reg;
 	u16	reg;
 	int	status, restart, is_in;
 	int	status, restart, is_in;
+	int	dma_channel;
 
 
 	is_in = ep->bEndpointAddress & USB_DIR_IN;
 	is_in = ep->bEndpointAddress & USB_DIR_IN;
 	if (is_in)
 	if (is_in)
@@ -769,11 +785,15 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 	ep->dma_channel = channel;
 	ep->dma_channel = channel;
 
 
 	if (is_in) {
 	if (is_in) {
-		status = omap_request_dma(OMAP_DMA_USB_W2FC_TX0 - 1 + channel,
+		if (cpu_is_omap24xx())
+			dma_channel = OMAP24XX_DMA(USB_W2FC_TX0, channel);
+		else
+			dma_channel = OMAP_DMA_USB_W2FC_TX0 - 1 + channel;
+		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 		if (status == 0) {
 			UDC_TXDMA_CFG_REG = reg;
 			UDC_TXDMA_CFG_REG = reg;
-			/* EMIFF */
+			/* EMIFF or SDRC */
 			omap_set_dma_src_burst_mode(ep->lch,
 			omap_set_dma_src_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
 						OMAP_DMA_DATA_BURST_4);
 			omap_set_dma_src_data_pack(ep->lch, 1);
 			omap_set_dma_src_data_pack(ep->lch, 1);
@@ -785,7 +805,12 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 				0, 0);
 				0, 0);
 		}
 		}
 	} else {
 	} else {
-		status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
+		if (cpu_is_omap24xx())
+			dma_channel = OMAP24XX_DMA(USB_W2FC_RX0, channel);
+		else
+			dma_channel = OMAP_DMA_USB_W2FC_RX0 - 1 + channel;
+
+		status = omap_request_dma(dma_channel,
 			ep->ep.name, dma_error, ep, &ep->lch);
 			ep->ep.name, dma_error, ep, &ep->lch);
 		if (status == 0) {
 		if (status == 0) {
 			UDC_RXDMA_CFG_REG = reg;
 			UDC_RXDMA_CFG_REG = reg;
@@ -795,7 +820,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 				OMAP_DMA_AMODE_CONSTANT,
 				OMAP_DMA_AMODE_CONSTANT,
 				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
 				(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
 				0, 0);
 				0, 0);
-			/* EMIFF */
+			/* EMIFF or SDRC */
 			omap_set_dma_dest_burst_mode(ep->lch,
 			omap_set_dma_dest_burst_mode(ep->lch,
 						OMAP_DMA_DATA_BURST_4);
 						OMAP_DMA_DATA_BURST_4);
 			omap_set_dma_dest_data_pack(ep->lch, 1);
 			omap_set_dma_dest_data_pack(ep->lch, 1);
@@ -808,7 +833,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 
 
 		/* channel type P: hw synch (fifo) */
 		/* channel type P: hw synch (fifo) */
-		if (!cpu_is_omap15xx())
+		if (cpu_class_is_omap1() && !cpu_is_omap15xx())
 			OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
 			OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
 	}
 	}
 
 
@@ -926,11 +951,13 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 	/* this isn't bogus, but OMAP DMA isn't the only hardware to
 	/* this isn't bogus, but OMAP DMA isn't the only hardware to
 	 * have a hard time with partial packet reads...  reject it.
 	 * have a hard time with partial packet reads...  reject it.
+	 * Except OMAP2 can handle the small packets.
 	 */
 	 */
 	if (use_dma
 	if (use_dma
 			&& ep->has_dma
 			&& ep->has_dma
 			&& ep->bEndpointAddress != 0
 			&& ep->bEndpointAddress != 0
 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
 			&& (ep->bEndpointAddress & USB_DIR_IN) == 0
+			&& !cpu_class_is_omap2()
 			&& (req->req.length % ep->ep.maxpacket) != 0) {
 			&& (req->req.length % ep->ep.maxpacket) != 0) {
 		DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
 		DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
 		return -EMSGSIZE;
 		return -EMSGSIZE;
@@ -1001,7 +1028,7 @@ omap_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 				/* STATUS for zero length DATA stages is
 				/* STATUS for zero length DATA stages is
 				 * always an IN ... even for IN transfers,
 				 * always an IN ... even for IN transfers,
-				 * a wierd case which seem to stall OMAP.
+				 * a weird case which seem to stall OMAP.
 				 */
 				 */
 				UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR);
 				UDC_EP_NUM_REG = (UDC_EP_SEL|UDC_EP_DIR);
 				UDC_CTRL_REG = UDC_CLR_EP;
 				UDC_CTRL_REG = UDC_CLR_EP;

+ 4 - 9
drivers/usb/gadget/omap_udc.h

@@ -182,21 +182,16 @@ struct omap_udc {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-#ifdef DEBUG
-#define DBG(stuff...)		printk(KERN_DEBUG "udc: " stuff)
-#else
-#define DBG(stuff...)		do{}while(0)
-#endif
-
 #ifdef VERBOSE
 #ifdef VERBOSE
 #    define VDBG		DBG
 #    define VDBG		DBG
 #else
 #else
 #    define VDBG(stuff...)	do{}while(0)
 #    define VDBG(stuff...)	do{}while(0)
 #endif
 #endif
 
 
-#define ERR(stuff...)		printk(KERN_ERR "udc: " stuff)
-#define WARN(stuff...)		printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...)		printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
+#define DBG(stuff...)		pr_debug("udc: " stuff)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 

+ 1592 - 0
drivers/usb/gadget/printer.c

@@ -0,0 +1,1592 @@
+/*
+ * printer.c -- Printer gadget driver
+ *
+ * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2006 Craig W. Nadler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/cdev.h>
+
+#include <asm/byteorder.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <asm/unaligned.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/g_printer.h>
+
+#include "gadget_chips.h"
+
+#define DRIVER_DESC		"Printer Gadget"
+#define DRIVER_VERSION		"2007 OCT 06"
+
+static const char shortname [] = "printer";
+static const char driver_desc [] = DRIVER_DESC;
+
+static dev_t g_printer_devno;
+
+static struct class *usb_gadget_class;
+
+/*-------------------------------------------------------------------------*/
+
+struct printer_dev {
+	spinlock_t		lock;		/* lock this structure */
+	/* lock buffer lists during read/write calls */
+	spinlock_t		lock_printer_io;
+	struct usb_gadget	*gadget;
+	struct usb_request	*req;		/* for control responses */
+	u8			config;
+	s8			interface;
+	struct usb_ep		*in_ep, *out_ep;
+	const struct usb_endpoint_descriptor
+				*in, *out;
+	struct list_head	rx_reqs;	/* List of free RX structs */
+	struct list_head	rx_reqs_active;	/* List of Active RX xfers */
+	struct list_head	rx_buffers;	/* List of completed xfers */
+	/* wait until there is data to be read. */
+	wait_queue_head_t	rx_wait;
+	struct list_head	tx_reqs;	/* List of free TX structs */
+	struct list_head	tx_reqs_active; /* List of Active TX xfers */
+	/* Wait until there are write buffers available to use. */
+	wait_queue_head_t	tx_wait;
+	/* Wait until all write buffers have been sent. */
+	wait_queue_head_t	tx_flush_wait;
+	struct usb_request	*current_rx_req;
+	size_t			current_rx_bytes;
+	u8			*current_rx_buf;
+	u8			printer_status;
+	u8			reset_printer;
+	struct class_device	*printer_class_dev;
+	struct cdev		printer_cdev;
+	struct device		*pdev;
+	u8			printer_cdev_open;
+	wait_queue_head_t	wait;
+};
+
+static struct printer_dev usb_printer_gadget;
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ */
+#define PRINTER_VENDOR_NUM	0x0525		/* NetChip */
+#define PRINTER_PRODUCT_NUM	0xa4a8		/* Linux-USB Printer Gadget */
+
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort __initdata idVendor;
+module_param(idVendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort __initdata idProduct;
+module_param(idProduct, ushort, S_IRUGO);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort __initdata bcdDevice;
+module_param(bcdDevice, ushort, S_IRUGO);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *__initdata iManufacturer;
+module_param(iManufacturer, charp, S_IRUGO);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *__initdata iProduct;
+module_param(iProduct, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *__initdata iSerialNum;
+module_param(iSerialNum, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNum, "1");
+
+static char *__initdata iPNPstring;
+module_param(iPNPstring, charp, S_IRUGO);
+MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
+
+/* Number of requests to allocate per endpoint, not used for ep0. */
+static unsigned qlen = 10;
+module_param(qlen, uint, S_IRUGO|S_IWUSR);
+
+#define QLEN	qlen
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+#define DEVSPEED	USB_SPEED_HIGH
+#else   /* full speed (low speed doesn't do bulk) */
+#define DEVSPEED        USB_SPEED_FULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#define xprintk(d, level, fmt, args...) \
+	printk(level "%s: " fmt, DRIVER_DESC, ## args)
+
+#ifdef DEBUG
+#define DBG(dev, fmt, args...) \
+	xprintk(dev, KERN_DEBUG, fmt, ## args)
+#else
+#define DBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG(dev, fmt, args...) \
+	xprintk(dev, KERN_DEBUG, fmt, ## args)
+#else
+#define VDBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev, fmt, args...) \
+	xprintk(dev, KERN_ERR, fmt, ## args)
+#define WARN(dev, fmt, args...) \
+	xprintk(dev, KERN_WARNING, fmt, ## args)
+#define INFO(dev, fmt, args...) \
+	xprintk(dev, KERN_INFO, fmt, ## args)
+
+/*-------------------------------------------------------------------------*/
+
+/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
+ * ep0 implementation:  descriptors, config management, setup().
+ * also optional class-specific notification interrupt transfer.
+ */
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full) configuration
+ * descriptors are built on demand.
+ */
+
+#define STRING_MANUFACTURER		1
+#define STRING_PRODUCT			2
+#define STRING_SERIALNUM		3
+
+/* holds our biggest descriptor */
+#define USB_DESC_BUFSIZE		256
+#define USB_BUFSIZE			8192
+
+/* This device advertises one configuration. */
+#define DEV_CONFIG_VALUE		1
+#define	PRINTER_INTERFACE		0
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+	.idVendor =		__constant_cpu_to_le16(PRINTER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM),
+	.iManufacturer =	STRING_MANUFACTURER,
+	.iProduct =		STRING_PRODUCT,
+	.iSerialNumber =	STRING_SERIALNUM,
+	.bNumConfigurations =	1
+};
+
+static struct usb_otg_descriptor otg_desc = {
+	.bLength =		sizeof otg_desc,
+	.bDescriptorType =	USB_DT_OTG,
+	.bmAttributes =		USB_OTG_SRP
+};
+
+static struct usb_config_descriptor config_desc = {
+	.bLength =		sizeof config_desc,
+	.bDescriptorType =	USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =	1,
+	.bConfigurationValue =	DEV_CONFIG_VALUE,
+	.iConfiguration =	0,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1	/* Self-Powered */
+};
+
+static struct usb_interface_descriptor intf_desc = {
+	.bLength =		sizeof intf_desc,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bInterfaceNumber =	PRINTER_INTERFACE,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_PRINTER,
+	.bInterfaceSubClass =	1,	/* Printer Sub-Class */
+	.bInterfaceProtocol =	2,	/* Bi-Directional */
+	.iInterface =		0
+};
+
+static struct usb_endpoint_descriptor fs_ep_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 fs_ep_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK
+};
+
+static const struct usb_descriptor_header *fs_printer_function [11] = {
+	(struct usb_descriptor_header *) &otg_desc,
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &fs_ep_in_desc,
+	(struct usb_descriptor_header *) &fs_ep_out_desc,
+	NULL
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+
+/*
+ * usb 2.0 devices need to expose both high speed and full speed
+ * descriptors, unless they only run at full speed.
+ */
+
+static struct usb_endpoint_descriptor hs_ep_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+};
+
+static struct usb_endpoint_descriptor hs_ep_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512)
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PRINTER,
+	.bNumConfigurations =	1
+};
+
+static const struct usb_descriptor_header *hs_printer_function [11] = {
+	(struct usb_descriptor_header *) &otg_desc,
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &hs_ep_in_desc,
+	(struct usb_descriptor_header *) &hs_ep_out_desc,
+	NULL
+};
+
+/* maxpacket and other transfer characteristics vary by speed. */
+#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
+
+#else
+
+/* if there's no high speed support, maxpacket doesn't change. */
+#define ep_desc(g, hs, fs) (((void)(g)), (fs))
+
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
+
+/*-------------------------------------------------------------------------*/
+
+/* descriptors that are built on-demand */
+
+static char				manufacturer [50];
+static char				product_desc [40] = DRIVER_DESC;
+static char				serial_num [40] = "1";
+static char				pnp_string [1024] =
+	"XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
+
+/* static strings, in UTF-8 */
+static struct usb_string		strings [] = {
+	{ STRING_MANUFACTURER,	manufacturer, },
+	{ STRING_PRODUCT,	product_desc, },
+	{ STRING_SERIALNUM,	serial_num, },
+	{  }		/* end of list */
+};
+
+static struct usb_gadget_strings	stringtab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_request *
+printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags)
+{
+	struct usb_request	*req;
+
+	req = usb_ep_alloc_request(ep, gfp_flags);
+
+	if (req != NULL) {
+		req->length = len;
+		req->buf = kmalloc(len, gfp_flags);
+		if (req->buf == NULL) {
+			usb_ep_free_request(ep, req);
+			return NULL;
+		}
+	}
+
+	return req;
+}
+
+static void
+printer_req_free(struct usb_ep *ep, struct usb_request *req)
+{
+	if (ep != NULL && req != NULL) {
+		kfree(req->buf);
+		usb_ep_free_request(ep, req);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct printer_dev	*dev = ep->driver_data;
+	int			status = req->status;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	list_del_init(&req->list);	/* Remode from Active List */
+
+	switch (status) {
+
+	/* normal completion */
+	case 0:
+		list_add_tail(&req->list, &dev->rx_buffers);
+		wake_up_interruptible(&dev->rx_wait);
+		DBG(dev, "G_Printer : rx length %d\n", req->actual);
+		break;
+
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		VDBG(dev, "rx shutdown, code %d\n", status);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+
+	/* for hardware automagic (such as pxa) */
+	case -ECONNABORTED:		/* endpoint reset */
+		DBG(dev, "rx %s reset\n", ep->name);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+
+	/* data overrun */
+	case -EOVERFLOW:
+		/* FALLTHROUGH */
+
+	default:
+		DBG(dev, "rx status %d\n", status);
+		list_add(&req->list, &dev->rx_reqs);
+		break;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct printer_dev	*dev = ep->driver_data;
+
+	switch (req->status) {
+	default:
+		VDBG(dev, "tx err %d\n", req->status);
+		/* FALLTHROUGH */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		break;
+	case 0:
+		break;
+	}
+
+	spin_lock(&dev->lock);
+	/* Take the request struct off the active list and put it on the
+	 * free list.
+	 */
+	list_del_init(&req->list);
+	list_add(&req->list, &dev->tx_reqs);
+	wake_up_interruptible(&dev->tx_wait);
+	if (likely(list_empty(&dev->tx_reqs_active)))
+		wake_up_interruptible(&dev->tx_flush_wait);
+
+	spin_unlock(&dev->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+printer_open(struct inode *inode, struct file *fd)
+{
+	struct printer_dev	*dev;
+	unsigned long		flags;
+	int			ret = -EBUSY;
+
+	dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (!dev->printer_cdev_open) {
+		dev->printer_cdev_open = 1;
+		fd->private_data = dev;
+		ret = 0;
+		/* Change the printer status to show that it's on-line. */
+		dev->printer_status |= PRINTER_SELECTED;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	DBG(dev, "printer_open returned %x\n", ret);
+
+	return ret;
+}
+
+static int
+printer_close(struct inode *inode, struct file *fd)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->printer_cdev_open = 0;
+	fd->private_data = NULL;
+	/* Change printer status to show that the printer is off-line. */
+	dev->printer_status &= ~PRINTER_SELECTED;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	DBG(dev, "printer_close\n");
+
+	return 0;
+}
+
+static ssize_t
+printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
+{
+	struct printer_dev		*dev = fd->private_data;
+	unsigned long			flags;
+	size_t				size;
+	size_t				bytes_copied;
+	struct usb_request		*req;
+	/* This is a pointer to the current USB rx request. */
+	struct usb_request		*current_rx_req;
+	/* This is the number of bytes in the current rx buffer. */
+	size_t				current_rx_bytes;
+	/* This is a pointer to the current rx buffer. */
+	u8				*current_rx_buf;
+
+	if (len == 0)
+		return -EINVAL;
+
+	DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
+
+	spin_lock(&dev->lock_printer_io);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* We will use this flag later to check if a printer reset happened
+	 * after we turn interrupts back on.
+	 */
+	dev->reset_printer = 0;
+
+	while (likely(!list_empty(&dev->rx_reqs))) {
+		int error;
+
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+
+		/* The USB Host sends us whatever amount of data it wants to
+		 * so we always set the length field to the full USB_BUFSIZE.
+		 * If the amount of data is more than the read() caller asked
+		 * for it will be stored in the request buffer until it is
+		 * asked for by read().
+		 */
+		req->length = USB_BUFSIZE;
+		req->complete = rx_complete;
+
+		error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+		if (error) {
+			DBG(dev, "rx submit --> %d\n", error);
+			list_add(&req->list, &dev->rx_reqs);
+			break;
+		} else {
+			list_add(&req->list, &dev->rx_reqs_active);
+		}
+	}
+
+	bytes_copied = 0;
+	current_rx_req = dev->current_rx_req;
+	current_rx_bytes = dev->current_rx_bytes;
+	current_rx_buf = dev->current_rx_buf;
+	dev->current_rx_req = NULL;
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+
+	/* Check if there is any data in the read buffers. Please note that
+	 * current_rx_bytes is the number of bytes in the current rx buffer.
+	 * If it is zero then check if there are any other rx_buffers that
+	 * are on the completed list. We are only out of data if all rx
+	 * buffers are empty.
+	 */
+	if ((current_rx_bytes == 0) &&
+			(likely(list_empty(&dev->rx_buffers)))) {
+		/* Turn interrupts back on before sleeping. */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		/*
+		 * If no data is available check if this is a NON-Blocking
+		 * call or not.
+		 */
+		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* Sleep until data is available */
+		wait_event_interruptible(dev->rx_wait,
+				(likely(!list_empty(&dev->rx_buffers))));
+		spin_lock_irqsave(&dev->lock, flags);
+	}
+
+	/* We have data to return then copy it to the caller's buffer.*/
+	while ((current_rx_bytes || likely(!list_empty(&dev->rx_buffers)))
+			&& len) {
+		if (current_rx_bytes == 0) {
+			req = container_of(dev->rx_buffers.next,
+					struct usb_request, list);
+			list_del_init(&req->list);
+
+			if (req->actual && req->buf) {
+				current_rx_req = req;
+				current_rx_bytes = req->actual;
+				current_rx_buf = req->buf;
+			} else {
+				list_add(&req->list, &dev->rx_reqs);
+				continue;
+			}
+		}
+
+		/* Don't leave irqs off while doing memory copies */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		if (len > current_rx_bytes)
+			size = current_rx_bytes;
+		else
+			size = len;
+
+		size -= copy_to_user(buf, current_rx_buf, size);
+		bytes_copied += size;
+		len -= size;
+		buf += size;
+
+		spin_lock_irqsave(&dev->lock, flags);
+
+		/* We've disconnected or reset free the req and buffer */
+		if (dev->reset_printer) {
+			printer_req_free(dev->out_ep, current_rx_req);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* If we not returning all the data left in this RX request
+		 * buffer then adjust the amount of data left in the buffer.
+		 * Othewise if we are done with this RX request buffer then
+		 * requeue it to get any incoming data from the USB host.
+		 */
+		if (size < current_rx_bytes) {
+			current_rx_bytes -= size;
+			current_rx_buf += size;
+		} else {
+			list_add(&current_rx_req->list, &dev->rx_reqs);
+			current_rx_bytes = 0;
+			current_rx_buf = NULL;
+			current_rx_req = NULL;
+		}
+	}
+
+	dev->current_rx_req = current_rx_req;
+	dev->current_rx_bytes = current_rx_bytes;
+	dev->current_rx_buf = current_rx_buf;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	spin_unlock(&dev->lock_printer_io);
+
+	DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
+
+	if (bytes_copied)
+		return bytes_copied;
+	else
+		return -EAGAIN;
+}
+
+static ssize_t
+printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	size_t			size;	/* Amount of data in a TX request. */
+	size_t			bytes_copied = 0;
+	struct usb_request	*req;
+
+	DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
+
+	if (len == 0)
+		return -EINVAL;
+
+	spin_lock(&dev->lock_printer_io);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* Check if a printer reset happens while we have interrupts on */
+	dev->reset_printer = 0;
+
+	/* Check if there is any available write buffers */
+	if (likely(list_empty(&dev->tx_reqs))) {
+		/* Turn interrupts back on before sleeping. */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		/*
+		 * If write buffers are available check if this is
+		 * a NON-Blocking call or not.
+		 */
+		if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		/* Sleep until a write buffer is available */
+		wait_event_interruptible(dev->tx_wait,
+				(likely(!list_empty(&dev->tx_reqs))));
+		spin_lock_irqsave(&dev->lock, flags);
+	}
+
+	while (likely(!list_empty(&dev->tx_reqs)) && len) {
+
+		if (len > USB_BUFSIZE)
+			size = USB_BUFSIZE;
+		else
+			size = len;
+
+		req = container_of(dev->tx_reqs.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+
+		req->complete = tx_complete;
+		req->length = size;
+
+		/* Check if we need to send a zero length packet. */
+		if (len > size)
+			/* They will be more TX requests so no yet. */
+			req->zero = 0;
+		else
+			/* If the data amount is not a multple of the
+			 * maxpacket size then send a zero length packet.
+			 */
+			req->zero = ((len % dev->in_ep->maxpacket) == 0);
+
+		/* Don't leave irqs off while doing memory copies */
+		spin_unlock_irqrestore(&dev->lock, flags);
+
+		if (copy_from_user(req->buf, buf, size)) {
+			list_add(&req->list, &dev->tx_reqs);
+			spin_unlock(&dev->lock_printer_io);
+			return bytes_copied;
+		}
+
+		bytes_copied += size;
+		len -= size;
+		buf += size;
+
+		spin_lock_irqsave(&dev->lock, flags);
+
+		/* We've disconnected or reset so free the req and buffer */
+		if (dev->reset_printer) {
+			printer_req_free(dev->in_ep, req);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
+			list_add(&req->list, &dev->tx_reqs);
+			spin_unlock_irqrestore(&dev->lock, flags);
+			spin_unlock(&dev->lock_printer_io);
+			return -EAGAIN;
+		}
+
+		list_add(&req->list, &dev->tx_reqs_active);
+
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+	spin_unlock(&dev->lock_printer_io);
+
+	DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
+
+	if (bytes_copied) {
+		return bytes_copied;
+	} else {
+		return -EAGAIN;
+	}
+}
+
+static int
+printer_fsync(struct file *fd, struct dentry *dentry, int datasync)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			tx_list_empty;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!tx_list_empty) {
+		/* Sleep until all data has been sent */
+		wait_event_interruptible(dev->tx_flush_wait,
+				(likely(list_empty(&dev->tx_reqs_active))));
+	}
+
+	return 0;
+}
+
+static unsigned int
+printer_poll(struct file *fd, poll_table *wait)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			status = 0;
+
+	poll_wait(fd, &dev->rx_wait, wait);
+	poll_wait(fd, &dev->tx_wait, wait);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (likely(!list_empty(&dev->tx_reqs)))
+		status |= POLLOUT | POLLWRNORM;
+
+	if (likely(!list_empty(&dev->rx_buffers)))
+		status |= POLLIN | POLLRDNORM;
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+static int
+printer_ioctl(struct inode *inode, struct file *fd, unsigned int code,
+		unsigned long arg)
+{
+	struct printer_dev	*dev = fd->private_data;
+	unsigned long		flags;
+	int			status = 0;
+
+	DBG(dev, "printer_ioctl: cmd=0x%4.4x, arg=%lu\n", code, arg);
+
+	/* handle ioctls */
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	switch (code) {
+	case GADGET_GET_PRINTER_STATUS:
+		status = (int)dev->printer_status;
+		break;
+	case GADGET_SET_PRINTER_STATUS:
+		dev->printer_status = (u8)arg;
+		break;
+	default:
+		/* could not handle ioctl */
+		DBG(dev, "printer_ioctl: ERROR cmd=0x%4.4xis not supported\n",
+				code);
+		status = -ENOTTY;
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+/* used after endpoint configuration */
+static struct file_operations printer_io_operations = {
+	.owner =	THIS_MODULE,
+	.open =		printer_open,
+	.read =		printer_read,
+	.write =	printer_write,
+	.fsync =	printer_fsync,
+	.poll =		printer_poll,
+	.ioctl =	printer_ioctl,
+	.release =	printer_close
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int
+set_printer_interface(struct printer_dev *dev)
+{
+	int			result = 0;
+
+	dev->in = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc);
+	dev->in_ep->driver_data = dev;
+
+	dev->out = ep_desc(dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc);
+	dev->out_ep->driver_data = dev;
+
+	result = usb_ep_enable(dev->in_ep, dev->in);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+		goto done;
+	}
+
+	result = usb_ep_enable(dev->out_ep, dev->out);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n", dev->in_ep->name, result);
+		goto done;
+	}
+
+done:
+	/* on error, disable any endpoints  */
+	if (result != 0) {
+		(void) usb_ep_disable(dev->in_ep);
+		(void) usb_ep_disable(dev->out_ep);
+		dev->in = NULL;
+		dev->out = NULL;
+	}
+
+	/* caller is responsible for cleanup on error */
+	return result;
+}
+
+static void printer_reset_interface(struct printer_dev *dev)
+{
+	if (dev->interface < 0)
+		return;
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	if (dev->in)
+		usb_ep_disable(dev->in_ep);
+
+	if (dev->out)
+		usb_ep_disable(dev->out_ep);
+
+	dev->interface = -1;
+}
+
+/* change our operational config.  must agree with the code
+ * that returns config descriptors, and altsetting code.
+ */
+static int
+printer_set_config(struct printer_dev *dev, unsigned number)
+{
+	int			result = 0;
+	struct usb_gadget	*gadget = dev->gadget;
+
+	if (gadget_is_sa1100(gadget) && dev->config) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO(dev, "can't change configurations\n");
+		return -ESPIPE;
+	}
+
+	switch (number) {
+	case DEV_CONFIG_VALUE:
+		result = 0;
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	case 0:
+		break;
+	}
+
+	if (result) {
+		usb_gadget_vbus_draw(dev->gadget,
+				dev->gadget->is_otg ? 8 : 100);
+	} else {
+		char *speed;
+		unsigned power;
+
+		power = 2 * config_desc.bMaxPower;
+		usb_gadget_vbus_draw(dev->gadget, power);
+
+		switch (gadget->speed) {
+		case USB_SPEED_FULL:	speed = "full"; break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+		case USB_SPEED_HIGH:	speed = "high"; break;
+#endif
+		default:		speed = "?"; break;
+		}
+
+		dev->config = number;
+		INFO(dev, "%s speed config #%d: %d mA, %s\n",
+				speed, number, power, driver_desc);
+	}
+	return result;
+}
+
+static int
+config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index,
+		int is_otg)
+{
+	int					len;
+	const struct usb_descriptor_header	**function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int					hs = (speed == USB_SPEED_HIGH);
+
+	if (type == USB_DT_OTHER_SPEED_CONFIG)
+		hs = !hs;
+
+	if (hs) {
+		function = hs_printer_function;
+	} else {
+		function = fs_printer_function;
+	}
+#else
+	function = fs_printer_function;
+#endif
+
+	if (index >= device_desc.bNumConfigurations)
+		return -EINVAL;
+
+	/* for now, don't advertise srp-only devices */
+	if (!is_otg)
+		function++;
+
+	len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE,
+			function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
+}
+
+/* Change our operational Interface. */
+static int
+set_interface(struct printer_dev *dev, unsigned number)
+{
+	int			result = 0;
+
+	if (gadget_is_sa1100(dev->gadget) && dev->interface < 0) {
+		/* tx fifo is full, but we can't clear it...*/
+		INFO(dev, "can't change interfaces\n");
+		return -ESPIPE;
+	}
+
+	/* Free the current interface */
+	switch (dev->interface) {
+	case PRINTER_INTERFACE:
+		printer_reset_interface(dev);
+		break;
+	}
+
+	switch (number) {
+	case PRINTER_INTERFACE:
+		result = set_printer_interface(dev);
+		if (result) {
+			printer_reset_interface(dev);
+		} else {
+			dev->interface = PRINTER_INTERFACE;
+		}
+		break;
+	default:
+		result = -EINVAL;
+		/* FALL THROUGH */
+	}
+
+	if (!result)
+		INFO(dev, "Using interface %x\n", number);
+
+	return result;
+}
+
+static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DBG((struct printer_dev *) ep->driver_data,
+				"setup complete --> %d, %d/%d\n",
+				req->status, req->actual, req->length);
+}
+
+static void printer_soft_reset(struct printer_dev *dev)
+{
+	struct usb_request	*req;
+
+	INFO(dev, "Received Printer Reset Request\n");
+
+	if (usb_ep_disable(dev->in_ep))
+		DBG(dev, "Failed to disable USB in_ep\n");
+	if (usb_ep_disable(dev->out_ep))
+		DBG(dev, "Failed to disable USB out_ep\n");
+
+	if (dev->current_rx_req != NULL) {
+		list_add(&dev->current_rx_req->list, &dev->rx_reqs);
+		dev->current_rx_req = NULL;
+	}
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+	dev->reset_printer = 1;
+
+	while (likely(!(list_empty(&dev->rx_buffers)))) {
+		req = container_of(dev->rx_buffers.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	while (likely(!(list_empty(&dev->rx_reqs_active)))) {
+		req = container_of(dev->rx_buffers.next, struct usb_request,
+				list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	while (likely(!(list_empty(&dev->tx_reqs_active)))) {
+		req = container_of(dev->tx_reqs_active.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+		list_add(&req->list, &dev->tx_reqs);
+	}
+
+	if (usb_ep_enable(dev->in_ep, dev->in))
+		DBG(dev, "Failed to enable USB in_ep\n");
+	if (usb_ep_enable(dev->out_ep, dev->out))
+		DBG(dev, "Failed to enable USB out_ep\n");
+
+	wake_up_interruptible(&dev->tx_wait);
+	wake_up_interruptible(&dev->tx_flush_wait);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The setup() callback implements all the ep0 functionality that's not
+ * handled lower down.
+ */
+static int
+printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	struct usb_request	*req = dev->req;
+	int			value = -EOPNOTSUPP;
+	u16			wIndex = le16_to_cpu(ctrl->wIndex);
+	u16			wValue = le16_to_cpu(ctrl->wValue);
+	u16			wLength = le16_to_cpu(ctrl->wLength);
+
+	DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
+		ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
+
+	req->complete = printer_setup_complete;
+
+	switch (ctrl->bRequestType&USB_TYPE_MASK) {
+
+	case USB_TYPE_STANDARD:
+		switch (ctrl->bRequest) {
+
+		case USB_REQ_GET_DESCRIPTOR:
+			if (ctrl->bRequestType != USB_DIR_IN)
+				break;
+			switch (wValue >> 8) {
+
+			case USB_DT_DEVICE:
+				value = min(wLength, (u16) sizeof device_desc);
+				memcpy(req->buf, &device_desc, value);
+				break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+			case USB_DT_DEVICE_QUALIFIER:
+				if (!gadget->is_dualspeed)
+					break;
+				value = min(wLength,
+						(u16) sizeof dev_qualifier);
+				memcpy(req->buf, &dev_qualifier, value);
+				break;
+
+			case USB_DT_OTHER_SPEED_CONFIG:
+				if (!gadget->is_dualspeed)
+					break;
+				/* FALLTHROUGH */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
+			case USB_DT_CONFIG:
+				value = config_buf(gadget->speed, req->buf,
+						wValue >> 8,
+						wValue & 0xff,
+						gadget->is_otg);
+				if (value >= 0)
+					value = min(wLength, (u16) value);
+				break;
+
+			case USB_DT_STRING:
+				value = usb_gadget_get_string(&stringtab,
+						wValue & 0xff, req->buf);
+				if (value >= 0)
+					value = min(wLength, (u16) value);
+				break;
+			}
+			break;
+
+		case USB_REQ_SET_CONFIGURATION:
+			if (ctrl->bRequestType != 0)
+				break;
+			if (gadget->a_hnp_support)
+				DBG(dev, "HNP available\n");
+			else if (gadget->a_alt_hnp_support)
+				DBG(dev, "HNP needs a different root port\n");
+			value = printer_set_config(dev, wValue);
+			break;
+		case USB_REQ_GET_CONFIGURATION:
+			if (ctrl->bRequestType != USB_DIR_IN)
+				break;
+			*(u8 *)req->buf = dev->config;
+			value = min(wLength, (u16) 1);
+			break;
+
+		case USB_REQ_SET_INTERFACE:
+			if (ctrl->bRequestType != USB_RECIP_INTERFACE ||
+					!dev->config)
+				break;
+
+			value = set_interface(dev, PRINTER_INTERFACE);
+			break;
+		case USB_REQ_GET_INTERFACE:
+			if (ctrl->bRequestType !=
+					(USB_DIR_IN|USB_RECIP_INTERFACE)
+					|| !dev->config)
+				break;
+
+			*(u8 *)req->buf = dev->interface;
+			value = min(wLength, (u16) 1);
+			break;
+
+		default:
+			goto unknown;
+		}
+		break;
+
+	case USB_TYPE_CLASS:
+		switch (ctrl->bRequest) {
+		case 0: /* Get the IEEE-1284 PNP String */
+			/* Only one printer interface is supported. */
+			if ((wIndex>>8) != PRINTER_INTERFACE)
+				break;
+
+			value = (pnp_string[0]<<8)|pnp_string[1];
+			memcpy(req->buf, pnp_string, value);
+			DBG(dev, "1284 PNP String: %x %s\n", value,
+					&pnp_string[2]);
+			break;
+
+		case 1: /* Get Port Status */
+			/* Only one printer interface is supported. */
+			if (wIndex != PRINTER_INTERFACE)
+				break;
+
+			*(u8 *)req->buf = dev->printer_status;
+			value = min(wLength, (u16) 1);
+			break;
+
+		case 2: /* Soft Reset */
+			/* Only one printer interface is supported. */
+			if (wIndex != PRINTER_INTERFACE)
+				break;
+
+			printer_soft_reset(dev);
+
+			value = 0;
+			break;
+
+		default:
+			goto unknown;
+		}
+		break;
+
+	default:
+unknown:
+		VDBG(dev,
+			"unknown ctrl req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			wValue, wIndex, wLength);
+		break;
+	}
+
+	/* respond with data transfer before status phase? */
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < wLength
+				&& (value % gadget->ep0->maxpacket) == 0;
+		value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			DBG(dev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			printer_setup_complete(gadget->ep0, req);
+		}
+	}
+
+	/* host either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void
+printer_disconnect(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	unsigned long		flags;
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	printer_reset_interface(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static void
+printer_unbind(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev = get_gadget_data(gadget);
+	struct usb_request	*req;
+
+
+	DBG(dev, "%s\n", __FUNCTION__);
+
+	/* Remove sysfs files */
+	device_destroy(usb_gadget_class, g_printer_devno);
+
+	/* Remove Character Device */
+	cdev_del(&dev->printer_cdev);
+
+	/* we must already have been disconnected ... no i/o may be active */
+	WARN_ON(!list_empty(&dev->tx_reqs_active));
+	WARN_ON(!list_empty(&dev->rx_reqs_active));
+
+	/* Free all memory for this driver. */
+	while (!list_empty(&dev->tx_reqs)) {
+		req = container_of(dev->tx_reqs.next, struct usb_request,
+				list);
+		list_del(&req->list);
+		printer_req_free(dev->in_ep, req);
+	}
+
+	if (dev->current_rx_req != NULL);
+		printer_req_free(dev->out_ep, dev->current_rx_req);
+
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del(&req->list);
+		printer_req_free(dev->out_ep, req);
+	}
+
+	while (!list_empty(&dev->rx_buffers)) {
+		req = container_of(dev->rx_buffers.next,
+				struct usb_request, list);
+		list_del(&req->list);
+		printer_req_free(dev->out_ep, req);
+	}
+
+	if (dev->req) {
+		printer_req_free(gadget->ep0, dev->req);
+		dev->req = NULL;
+	}
+
+	set_gadget_data(gadget, NULL);
+}
+
+static int __init
+printer_bind(struct usb_gadget *gadget)
+{
+	struct printer_dev	*dev;
+	struct usb_ep		*in_ep, *out_ep;
+	int			status = -ENOMEM;
+	int			gcnum;
+	size_t			len;
+	u32			i;
+	struct usb_request	*req;
+
+	dev = &usb_printer_gadget;
+
+
+	/* Setup the sysfs files for the printer gadget. */
+	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
+			"g_printer");
+	if (IS_ERR(dev->pdev)) {
+		ERROR(dev, "Failed to create device: g_printer\n");
+		goto fail;
+	}
+
+	/*
+	 * Register a character device as an interface to a user mode
+	 * program that handles the printer specific functionality.
+	 */
+	cdev_init(&dev->printer_cdev, &printer_io_operations);
+	dev->printer_cdev.owner = THIS_MODULE;
+	status = cdev_add(&dev->printer_cdev, g_printer_devno, 1);
+	if (status) {
+		ERROR(dev, "Failed to open char device\n");
+		goto fail;
+	}
+
+	if (gadget_is_sa1100(gadget)) {
+		/* hardware can't write zero length packets. */
+		ERROR(dev, "SA1100 controller is unsupport by this driver\n");
+		goto fail;
+	}
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0) {
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	} else {
+		dev_warn(&gadget->dev, "controller '%s' not recognized\n",
+			gadget->name);
+		/* unrecognized, but safe unless bulk is REALLY quirky */
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0xFFFF);
+	}
+	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+
+	device_desc.idVendor =
+		__constant_cpu_to_le16(PRINTER_VENDOR_NUM);
+	device_desc.idProduct =
+		__constant_cpu_to_le16(PRINTER_PRODUCT_NUM);
+
+	/* support optional vendor/distro customization */
+	if (idVendor) {
+		if (!idProduct) {
+			dev_err(&gadget->dev, "idVendor needs idProduct!\n");
+			return -ENODEV;
+		}
+		device_desc.idVendor = cpu_to_le16(idVendor);
+		device_desc.idProduct = cpu_to_le16(idProduct);
+		if (bcdDevice)
+			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+	}
+
+	if (iManufacturer)
+		strlcpy(manufacturer, iManufacturer, sizeof manufacturer);
+
+	if (iProduct)
+		strlcpy(product_desc, iProduct, sizeof product_desc);
+
+	if (iSerialNum)
+		strlcpy(serial_num, iSerialNum, sizeof serial_num);
+
+	if (iPNPstring)
+		strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2);
+
+	len = strlen(pnp_string);
+	pnp_string[0] = (len >> 8) & 0xFF;
+	pnp_string[1] = len & 0xFF;
+
+	/* all we really need is bulk IN/OUT */
+	usb_ep_autoconfig_reset(gadget);
+	in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc);
+	if (!in_ep) {
+autoconf_fail:
+		dev_err(&gadget->dev, "can't autoconfigure on %s\n",
+			gadget->name);
+		return -ENODEV;
+	}
+	in_ep->driver_data = in_ep;	/* claim */
+
+	out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc);
+	if (!out_ep)
+		goto autoconf_fail;
+	out_ep->driver_data = out_ep;	/* claim */
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
+	/* assumes ep0 uses the same value for both speeds ... */
+	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
+	hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
+#endif	/* DUALSPEED */
+
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+	usb_gadget_set_selfpowered(gadget);
+
+	if (gadget->is_otg) {
+		otg_desc.bmAttributes |= USB_OTG_HNP,
+		config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		config_desc.bMaxPower = 4;
+	}
+
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->lock_printer_io);
+	INIT_LIST_HEAD(&dev->tx_reqs);
+	INIT_LIST_HEAD(&dev->tx_reqs_active);
+	INIT_LIST_HEAD(&dev->rx_reqs);
+	INIT_LIST_HEAD(&dev->rx_reqs_active);
+	INIT_LIST_HEAD(&dev->rx_buffers);
+	init_waitqueue_head(&dev->rx_wait);
+	init_waitqueue_head(&dev->tx_wait);
+	init_waitqueue_head(&dev->tx_flush_wait);
+
+	dev->config = 0;
+	dev->interface = -1;
+	dev->printer_cdev_open = 0;
+	dev->printer_status = PRINTER_NOT_ERROR;
+	dev->current_rx_req = NULL;
+	dev->current_rx_bytes = 0;
+	dev->current_rx_buf = NULL;
+
+	dev->in_ep = in_ep;
+	dev->out_ep = out_ep;
+
+	/* preallocate control message data and buffer */
+	dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE,
+			GFP_KERNEL);
+	if (!dev->req) {
+		status = -ENOMEM;
+		goto fail;
+	}
+
+	for (i = 0; i < QLEN; i++) {
+		req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
+		if (!req) {
+			while (!list_empty(&dev->tx_reqs)) {
+				req = container_of(dev->tx_reqs.next,
+						struct usb_request, list);
+				list_del(&req->list);
+				printer_req_free(dev->in_ep, req);
+			}
+			return -ENOMEM;
+		}
+		list_add(&req->list, &dev->tx_reqs);
+	}
+
+	for (i = 0; i < QLEN; i++) {
+		req = printer_req_alloc(dev->out_ep, USB_BUFSIZE, GFP_KERNEL);
+		if (!req) {
+			while (!list_empty(&dev->rx_reqs)) {
+				req = container_of(dev->rx_reqs.next,
+						struct usb_request, list);
+				list_del(&req->list);
+				printer_req_free(dev->out_ep, req);
+			}
+			return -ENOMEM;
+		}
+		list_add(&req->list, &dev->rx_reqs);
+	}
+
+	dev->req->complete = printer_setup_complete;
+
+	/* finish hookup to lower layer ... */
+	dev->gadget = gadget;
+	set_gadget_data(gadget, dev);
+	gadget->ep0->driver_data = dev;
+
+	INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
+	INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
+			in_ep->name);
+
+	return 0;
+
+fail:
+	printer_unbind(gadget);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver printer_driver = {
+	.speed		= DEVSPEED,
+
+	.function	= (char *) driver_desc,
+	.bind		= printer_bind,
+	.unbind		= printer_unbind,
+
+	.setup		= printer_setup,
+	.disconnect	= printer_disconnect,
+
+	.driver		= {
+		.name		= (char *) shortname,
+		.owner		= THIS_MODULE,
+	},
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Craig Nadler");
+MODULE_LICENSE("GPL");
+
+static int __init
+init(void)
+{
+	int status;
+
+	usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
+	if (IS_ERR(usb_gadget_class)) {
+		status = PTR_ERR(usb_gadget_class);
+		ERROR(dev, "unable to create usb_gadget class %d\n", status);
+		return status;
+	}
+
+	status = alloc_chrdev_region(&g_printer_devno, 0, 1,
+			"USB printer gadget");
+	if (status) {
+		ERROR(dev, "alloc_chrdev_region %d\n", status);
+		class_destroy(usb_gadget_class);
+		return status;
+	}
+
+	status = usb_gadget_register_driver(&printer_driver);
+	if (status) {
+		class_destroy(usb_gadget_class);
+		unregister_chrdev_region(g_printer_devno, 1);
+		DBG(dev, "usb_gadget_register_driver %x\n", status);
+	}
+
+	return status;
+}
+module_init(init);
+
+static void __exit
+cleanup(void)
+{
+	int status;
+
+	spin_lock(&usb_printer_gadget.lock_printer_io);
+	class_destroy(usb_gadget_class);
+	unregister_chrdev_region(g_printer_devno, 2);
+
+	status = usb_gadget_unregister_driver(&printer_driver);
+	if (status)
+		ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
+
+	spin_unlock(&usb_printer_gadget.lock_printer_io);
+}
+module_exit(cleanup);

+ 67 - 74
drivers/usb/gadget/pxa2xx_udc.c

@@ -24,7 +24,7 @@
  *
  *
  */
  */
 
 
-// #define	VERBOSE	DBG_VERBOSE
+/* #define VERBOSE_DEBUG */
 
 
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/module.h>
@@ -38,13 +38,14 @@
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
-#include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
 #include <linux/irq.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
 
 
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include <asm/dma.h>
 #include <asm/dma.h>
@@ -127,8 +128,10 @@ static int is_vbus_present(void)
 {
 {
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
 
 
-	if (mach->gpio_vbus)
-		return gpio_get_value(mach->gpio_vbus);
+	if (mach->gpio_vbus) {
+		int value = gpio_get_value(mach->gpio_vbus);
+		return mach->gpio_vbus_inverted ? !value : value;
+	}
 	if (mach->udc_is_connected)
 	if (mach->udc_is_connected)
 		return mach->udc_is_connected();
 		return mach->udc_is_connected();
 	return 1;
 	return 1;
@@ -677,7 +680,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
 	/* kickstart this i/o queue? */
 	/* kickstart this i/o queue? */
 	if (list_empty(&ep->queue) && !ep->stopped) {
 	if (list_empty(&ep->queue) && !ep->stopped) {
-		if (ep->desc == 0 /* ep0 */) {
+		if (ep->desc == NULL/* ep0 */) {
 			unsigned	length = _req->length;
 			unsigned	length = _req->length;
 
 
 			switch (dev->ep0state) {
 			switch (dev->ep0state) {
@@ -731,7 +734,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	}
 	}
 
 
 	/* pio or dma irq handler advances the queue. */
 	/* pio or dma irq handler advances the queue. */
-	if (likely (req != 0))
+	if (likely(req != NULL))
 		list_add_tail(&req->queue, &ep->queue);
 		list_add_tail(&req->queue, &ep->queue);
 	local_irq_restore(flags);
 	local_irq_restore(flags);
 
 
@@ -991,45 +994,32 @@ static const struct usb_gadget_ops pxa2xx_udc_ops = {
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static const char proc_node_name [] = "driver/udc";
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
 
 
 static int
 static int
-udc_proc_read(char *page, char **start, off_t off, int count,
-		int *eof, void *_dev)
+udc_seq_show(struct seq_file *m, void *d)
 {
 {
-	char			*buf = page;
-	struct pxa2xx_udc	*dev = _dev;
-	char			*next = buf;
-	unsigned		size = count;
+	struct pxa2xx_udc	*dev = m->private;
 	unsigned long		flags;
 	unsigned long		flags;
-	int			i, t;
+	int			i;
 	u32			tmp;
 	u32			tmp;
 
 
-	if (off != 0)
-		return 0;
-
 	local_irq_save(flags);
 	local_irq_save(flags);
 
 
 	/* basic device status */
 	/* basic device status */
-	t = scnprintf(next, size, DRIVER_DESC "\n"
+	seq_printf(m, DRIVER_DESC "\n"
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		"%s version: %s\nGadget driver: %s\nHost %s\n\n",
 		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
 		driver_name, DRIVER_VERSION SIZE_STR "(pio)",
 		dev->driver ? dev->driver->driver.name : "(none)",
 		dev->driver ? dev->driver->driver.name : "(none)",
 		is_vbus_present() ? "full speed" : "disconnected");
 		is_vbus_present() ? "full speed" : "disconnected");
-	size -= t;
-	next += t;
 
 
 	/* registers for device and ep0 */
 	/* registers for device and ep0 */
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
 		"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
-	size -= t;
-	next += t;
 
 
 	tmp = UDCCR;
 	tmp = UDCCR;
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCR_REM) ? " rem" : "",
 		(tmp & UDCCR_REM) ? " rem" : "",
 		(tmp & UDCCR_RSTIR) ? " rstir" : "",
 		(tmp & UDCCR_RSTIR) ? " rstir" : "",
@@ -1039,11 +1029,9 @@ udc_proc_read(char *page, char **start, off_t off, int count,
 		(tmp & UDCCR_RSM) ? " rsm" : "",
 		(tmp & UDCCR_RSM) ? " rsm" : "",
 		(tmp & UDCCR_UDA) ? " uda" : "",
 		(tmp & UDCCR_UDA) ? " uda" : "",
 		(tmp & UDCCR_UDE) ? " ude" : "");
 		(tmp & UDCCR_UDE) ? " ude" : "");
-	size -= t;
-	next += t;
 
 
 	tmp = UDCCS0;
 	tmp = UDCCS0;
-	t = scnprintf(next, size,
+	seq_printf(m,
 		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
 		(tmp & UDCCS0_SA) ? " sa" : "",
 		(tmp & UDCCS0_SA) ? " sa" : "",
 		(tmp & UDCCS0_RNE) ? " rne" : "",
 		(tmp & UDCCS0_RNE) ? " rne" : "",
@@ -1053,28 +1041,22 @@ udc_proc_read(char *page, char **start, off_t off, int count,
 		(tmp & UDCCS0_FTF) ? " ftf" : "",
 		(tmp & UDCCS0_FTF) ? " ftf" : "",
 		(tmp & UDCCS0_IPR) ? " ipr" : "",
 		(tmp & UDCCS0_IPR) ? " ipr" : "",
 		(tmp & UDCCS0_OPR) ? " opr" : "");
 		(tmp & UDCCS0_OPR) ? " opr" : "");
-	size -= t;
-	next += t;
 
 
 	if (dev->has_cfr) {
 	if (dev->has_cfr) {
 		tmp = UDCCFR;
 		tmp = UDCCFR;
-		t = scnprintf(next, size,
+		seq_printf(m,
 			"udccfr %02X =%s%s\n", tmp,
 			"udccfr %02X =%s%s\n", tmp,
 			(tmp & UDCCFR_AREN) ? " aren" : "",
 			(tmp & UDCCFR_AREN) ? " aren" : "",
 			(tmp & UDCCFR_ACM) ? " acm" : "");
 			(tmp & UDCCFR_ACM) ? " acm" : "");
-		size -= t;
-		next += t;
 	}
 	}
 
 
 	if (!is_vbus_present() || !dev->driver)
 	if (!is_vbus_present() || !dev->driver)
 		goto done;
 		goto done;
 
 
-	t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
+	seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
 		dev->stats.write.bytes, dev->stats.write.ops,
 		dev->stats.write.bytes, dev->stats.write.ops,
 		dev->stats.read.bytes, dev->stats.read.ops,
 		dev->stats.read.bytes, dev->stats.read.ops,
 		dev->stats.irqs);
 		dev->stats.irqs);
-	size -= t;
-	next += t;
 
 
 	/* dump endpoint queues */
 	/* dump endpoint queues */
 	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
 	for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1082,61 +1064,68 @@ udc_proc_read(char *page, char **start, off_t off, int count,
 		struct pxa2xx_request	*req;
 		struct pxa2xx_request	*req;
 
 
 		if (i != 0) {
 		if (i != 0) {
-			const struct usb_endpoint_descriptor	*d;
+			const struct usb_endpoint_descriptor	*desc;
 
 
-			d = ep->desc;
-			if (!d)
+			desc = ep->desc;
+			if (!desc)
 				continue;
 				continue;
 			tmp = *dev->ep [i].reg_udccs;
 			tmp = *dev->ep [i].reg_udccs;
-			t = scnprintf(next, size,
+			seq_printf(m,
 				"%s max %d %s udccs %02x irqs %lu\n",
 				"%s max %d %s udccs %02x irqs %lu\n",
-				ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
+				ep->ep.name, le16_to_cpu(desc->wMaxPacketSize),
 				"pio", tmp, ep->pio_irqs);
 				"pio", tmp, ep->pio_irqs);
 			/* TODO translate all five groups of udccs bits! */
 			/* TODO translate all five groups of udccs bits! */
 
 
 		} else /* ep0 should only have one transfer queued */
 		} else /* ep0 should only have one transfer queued */
-			t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n",
+			seq_printf(m, "ep0 max 16 pio irqs %lu\n",
 				ep->pio_irqs);
 				ep->pio_irqs);
-		if (t <= 0 || t > size)
-			goto done;
-		size -= t;
-		next += t;
 
 
 		if (list_empty(&ep->queue)) {
 		if (list_empty(&ep->queue)) {
-			t = scnprintf(next, size, "\t(nothing queued)\n");
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
+			seq_printf(m, "\t(nothing queued)\n");
 			continue;
 			continue;
 		}
 		}
 		list_for_each_entry(req, &ep->queue, queue) {
 		list_for_each_entry(req, &ep->queue, queue) {
-			t = scnprintf(next, size,
+			seq_printf(m,
 					"\treq %p len %d/%d buf %p\n",
 					"\treq %p len %d/%d buf %p\n",
 					&req->req, req->req.actual,
 					&req->req, req->req.actual,
 					req->req.length, req->req.buf);
 					req->req.length, req->req.buf);
-			if (t <= 0 || t > size)
-				goto done;
-			size -= t;
-			next += t;
 		}
 		}
 	}
 	}
 
 
 done:
 done:
 	local_irq_restore(flags);
 	local_irq_restore(flags);
-	*eof = 1;
-	return count - size;
+	return 0;
 }
 }
 
 
-#define create_proc_files() \
-	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
-#define remove_proc_files() \
-	remove_proc_entry(proc_node_name, NULL)
+static int
+udc_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, udc_seq_show, inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+	.open		= udc_debugfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.owner		= THIS_MODULE,
+};
+
+#define create_debug_files(dev) \
+	do { \
+		dev->debugfs_udc = debugfs_create_file(dev->gadget.name, \
+			S_IRUGO, NULL, dev, &debug_fops); \
+	} while (0)
+#define remove_debug_files(dev) \
+	do { \
+		if (dev->debugfs_udc) \
+			debugfs_remove(dev->debugfs_udc); \
+	} while (0)
 
 
 #else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
 #else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
 
 
-#define create_proc_files() do {} while (0)
-#define remove_proc_files() do {} while (0)
+#define create_debug_files(dev) do {} while (0)
+#define remove_debug_files(dev) do {} while (0)
 
 
 #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
 #endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
 
 
@@ -1345,6 +1334,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	local_irq_enable();
 	local_irq_enable();
 
 
 	driver->unbind(&dev->gadget);
 	driver->unbind(&dev->gadget);
+	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
 	dev->driver = NULL;
 
 
 	device_del (&dev->gadget.dev);
 	device_del (&dev->gadget.dev);
@@ -1397,6 +1387,9 @@ static irqreturn_t udc_vbus_irq(int irq, void *_dev)
 	struct pxa2xx_udc	*dev = _dev;
 	struct pxa2xx_udc	*dev = _dev;
 	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
 	int			vbus = gpio_get_value(dev->mach->gpio_vbus);
 
 
+	if (dev->mach->gpio_vbus_inverted)
+		vbus = !vbus;
+
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	pxa2xx_udc_vbus_session(&dev->gadget, vbus);
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
@@ -2099,7 +2092,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 	/* insist on Intel/ARM/XScale */
 	/* insist on Intel/ARM/XScale */
 	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
 	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
 	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
 	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {
-		printk(KERN_ERR "%s: not XScale!\n", driver_name);
+		pr_err("%s: not XScale!\n", driver_name);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -2128,7 +2121,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 		break;
 		break;
 #endif
 #endif
 	default:
 	default:
-		printk(KERN_ERR "%s: unrecognized processor: %08x\n",
+		pr_err("%s: unrecognized processor: %08x\n",
 			driver_name, chiprev);
 			driver_name, chiprev);
 		/* iop3xx, ixp4xx, ... */
 		/* iop3xx, ixp4xx, ... */
 		return -ENODEV;
 		return -ENODEV;
@@ -2199,7 +2192,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 	retval = request_irq(irq, pxa2xx_udc_irq,
 	retval = request_irq(irq, pxa2xx_udc_irq,
 			IRQF_DISABLED, driver_name, dev);
 			IRQF_DISABLED, driver_name, dev);
 	if (retval != 0) {
 	if (retval != 0) {
-		printk(KERN_ERR "%s: can't get irq %d, err %d\n",
+		pr_err("%s: can't get irq %d, err %d\n",
 			driver_name, irq, retval);
 			driver_name, irq, retval);
 		goto err_irq1;
 		goto err_irq1;
 	}
 	}
@@ -2212,7 +2205,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				driver_name, dev);
 				driver_name, dev);
 		if (retval != 0) {
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 lubbock_fail0:
 lubbock_fail0:
 			goto err_irq_lub;
 			goto err_irq_lub;
@@ -2222,7 +2215,7 @@ lubbock_fail0:
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
 				driver_name, dev);
 				driver_name, dev);
 		if (retval != 0) {
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_IRQ, retval);
 				driver_name, LUBBOCK_USB_IRQ, retval);
 			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
 			free_irq(LUBBOCK_USB_DISC_IRQ, dev);
 			goto lubbock_fail0;
 			goto lubbock_fail0;
@@ -2235,12 +2228,12 @@ lubbock_fail0:
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				driver_name, dev);
 				driver_name, dev);
 		if (retval != 0) {
 		if (retval != 0) {
-			printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, vbus_irq, retval);
 				driver_name, vbus_irq, retval);
 			goto err_vbus_irq;
 			goto err_vbus_irq;
 		}
 		}
 	}
 	}
-	create_proc_files();
+	create_debug_files(dev);
 
 
 	return 0;
 	return 0;
 
 
@@ -2277,7 +2270,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
 		return -EBUSY;
 		return -EBUSY;
 
 
 	udc_disable(dev);
 	udc_disable(dev);
-	remove_proc_files();
+	remove_debug_files(dev);
 
 
 	if (dev->got_irq) {
 	if (dev->got_irq) {
 		free_irq(platform_get_irq(pdev, 0), dev);
 		free_irq(platform_get_irq(pdev, 0), dev);
@@ -2361,7 +2354,7 @@ static struct platform_driver udc_driver = {
 
 
 static int __init udc_init(void)
 static int __init udc_init(void)
 {
 {
-	printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
+	pr_info("%s: version %s\n", driver_name, DRIVER_VERSION);
 	return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
 	return platform_driver_probe(&udc_driver, pxa2xx_udc_probe);
 }
 }
 module_init(udc_init);
 module_init(udc_init);

+ 15 - 10
drivers/usb/gadget/pxa2xx_udc.h

@@ -129,6 +129,10 @@ struct pxa2xx_udc {
 	struct pxa2xx_udc_mach_info		*mach;
 	struct pxa2xx_udc_mach_info		*mach;
 	u64					dma_mask;
 	u64					dma_mask;
 	struct pxa2xx_ep			ep [PXA_UDC_NUM_ENDPOINTS];
 	struct pxa2xx_ep			ep [PXA_UDC_NUM_ENDPOINTS];
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FS
+	struct dentry				*debugfs_udc;
+#endif
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -151,17 +155,19 @@ static struct pxa2xx_udc *the_controller;
 #define DBG_NOISY	3	/* ... even more: request level */
 #define DBG_NOISY	3	/* ... even more: request level */
 #define DBG_VERY_NOISY	4	/* ... even more: packet level */
 #define DBG_VERY_NOISY	4	/* ... even more: packet level */
 
 
+#define DMSG(stuff...)	pr_debug("udc: " stuff)
+
 #ifdef DEBUG
 #ifdef DEBUG
 
 
+static int is_vbus_present(void);
+
 static const char *state_name[] = {
 static const char *state_name[] = {
 	"EP0_IDLE",
 	"EP0_IDLE",
 	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
 	"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
 	"EP0_END_XFER", "EP0_STALL"
 	"EP0_END_XFER", "EP0_STALL"
 };
 };
 
 
-#define DMSG(stuff...) printk(KERN_DEBUG "udc: " stuff)
-
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
 #    define UDC_DEBUG DBG_VERBOSE
 #    define UDC_DEBUG DBG_VERBOSE
 #else
 #else
 #    define UDC_DEBUG DBG_NORMAL
 #    define UDC_DEBUG DBG_NORMAL
@@ -207,7 +213,7 @@ dump_state(struct pxa2xx_udc *dev)
 	unsigned	i;
 	unsigned	i;
 
 
 	DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
 	DMSG("%s %s, uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
-		is_usb_connected() ? "host " : "disconnected",
+		is_vbus_present() ? "host " : "disconnected",
 		state_name[dev->ep0state],
 		state_name[dev->ep0state],
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
 		UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
 	dump_udccr("udccr");
 	dump_udccr("udccr");
@@ -224,7 +230,7 @@ dump_state(struct pxa2xx_udc *dev)
 	} else
 	} else
 		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
 		DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
 
 
-	if (!is_usb_connected())
+	if (!is_vbus_present())
 		return;
 		return;
 
 
 	dump_udccs0 ("udccs0");
 	dump_udccs0 ("udccs0");
@@ -233,7 +239,7 @@ dump_state(struct pxa2xx_udc *dev)
 		dev->stats.read.bytes, dev->stats.read.ops);
 		dev->stats.read.bytes, dev->stats.read.ops);
 
 
 	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
 	for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
-		if (dev->ep [i].desc == 0)
+		if (dev->ep [i].desc == NULL)
 			continue;
 			continue;
 		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
 		DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
 	}
 	}
@@ -241,8 +247,6 @@ dump_state(struct pxa2xx_udc *dev)
 
 
 #else
 #else
 
 
-#define DMSG(stuff...)		do{}while(0)
-
 #define	dump_udccr(x)	do{}while(0)
 #define	dump_udccr(x)	do{}while(0)
 #define	dump_udccs0(x)	do{}while(0)
 #define	dump_udccs0(x)	do{}while(0)
 #define	dump_state(x)	do{}while(0)
 #define	dump_state(x)	do{}while(0)
@@ -253,8 +257,9 @@ dump_state(struct pxa2xx_udc *dev)
 
 
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 #define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
 
 
-#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
-#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
+#define ERR(stuff...)		pr_err("udc: " stuff)
+#define WARN(stuff...)		pr_warning("udc: " stuff)
+#define INFO(stuff...)		pr_info("udc: " stuff)
 
 
 
 
 #endif /* __LINUX_USB_GADGET_PXA2XX_H */
 #endif /* __LINUX_USB_GADGET_PXA2XX_H */

+ 8 - 12
drivers/usb/gadget/rndis.c

@@ -53,21 +53,18 @@
  */
  */
 
 
 #if 0
 #if 0
-#define DBG(str,args...) do { \
-	if (rndis_debug) \
-		printk(KERN_DEBUG str , ## args ); \
-	} while (0)
 static int rndis_debug = 0;
 static int rndis_debug = 0;
-
 module_param (rndis_debug, int, 0);
 module_param (rndis_debug, int, 0);
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
-
 #else
 #else
-
 #define rndis_debug		0
 #define rndis_debug		0
-#define DBG(str,args...)	do{}while(0)
 #endif
 #endif
 
 
+#define DBG(str,args...) do { \
+	if (rndis_debug) \
+		pr_debug(str , ## args); \
+	} while (0)
+
 #define RNDIS_MAX_CONFIGS	1
 #define RNDIS_MAX_CONFIGS	1
 
 
 
 
@@ -679,7 +676,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 #endif
 #endif
 
 
 	default:
 	default:
-		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n",
+		pr_warning("%s: query unknown OID 0x%08X\n",
 			 __FUNCTION__, OID);
 			 __FUNCTION__, OID);
 	}
 	}
 	if (retval < 0)
 	if (retval < 0)
@@ -804,7 +801,7 @@ update_linkstate:
 #endif	/* RNDIS_PM */
 #endif	/* RNDIS_PM */
 
 
 	default:
 	default:
-		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n",
+		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
 			 __FUNCTION__, OID, buf_len);
 			 __FUNCTION__, OID, buf_len);
 	}
 	}
 
 
@@ -1126,8 +1123,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
 		 * In one case those messages seemed to relate to the host
 		 * In one case those messages seemed to relate to the host
 		 * suspending itself.
 		 * suspending itself.
 		 */
 		 */
-		printk (KERN_WARNING
-			"%s: unknown RNDIS message 0x%08X len %d\n",
+		pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
 			__FUNCTION__ , MsgType, MsgLength);
 			__FUNCTION__ , MsgType, MsgLength);
 		{
 		{
 			unsigned i;
 			unsigned i;

+ 2 - 2
drivers/usb/gadget/s3c2410_udc.c

@@ -893,7 +893,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
 /*
 /*
  *	s3c2410_udc_irq - interrupt handler
  *	s3c2410_udc_irq - interrupt handler
  */
  */
-static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
+static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
 {
 {
 	struct s3c2410_udc *dev = _dev;
 	struct s3c2410_udc *dev = _dev;
 	int usb_status;
 	int usb_status;
@@ -1016,7 +1016,7 @@ static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
 		}
 		}
 	}
 	}
 
 
-	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
+	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
 
 
 	/* Restore old index */
 	/* Restore old index */
 	udc_write(idx, S3C2410_UDC_INDEX_REG);
 	udc_write(idx, S3C2410_UDC_INDEX_REG);

+ 79 - 74
drivers/usb/gadget/serial.c

@@ -89,9 +89,9 @@ static int debug = 1;
 #endif
 #endif
 
 
 #define gs_debug(format, arg...) \
 #define gs_debug(format, arg...) \
-	do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0)
+	do { if (debug) pr_debug(format, ## arg); } while (0)
 #define gs_debug_level(level, format, arg...) \
 #define gs_debug_level(level, format, arg...) \
-	do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0)
+	do { if (debug >= level) pr_debug(format, ## arg); } while (0)
 
 
 
 
 /* Thanks to NetChip Technologies for donating this product ID.
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -553,7 +553,8 @@ static int __init gs_module_init(void)
 
 
 	retval = usb_gadget_register_driver(&gs_gadget_driver);
 	retval = usb_gadget_register_driver(&gs_gadget_driver);
 	if (retval) {
 	if (retval) {
-		printk(KERN_ERR "gs_module_init: cannot register gadget driver, ret=%d\n", retval);
+		pr_err("gs_module_init: cannot register gadget driver, "
+			"ret=%d\n", retval);
 		return retval;
 		return retval;
 	}
 	}
 
 
@@ -579,11 +580,13 @@ static int __init gs_module_init(void)
 	if (retval) {
 	if (retval) {
 		usb_gadget_unregister_driver(&gs_gadget_driver);
 		usb_gadget_unregister_driver(&gs_gadget_driver);
 		put_tty_driver(gs_tty_driver);
 		put_tty_driver(gs_tty_driver);
-		printk(KERN_ERR "gs_module_init: cannot register tty driver, ret=%d\n", retval);
+		pr_err("gs_module_init: cannot register tty driver, "
+				"ret=%d\n", retval);
 		return retval;
 		return retval;
 	}
 	}
 
 
-	printk(KERN_INFO "gs_module_init: %s %s loaded\n", GS_LONG_NAME, GS_VERSION_STR);
+	pr_info("gs_module_init: %s %s loaded\n",
+			GS_LONG_NAME, GS_VERSION_STR);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -598,7 +601,8 @@ static void __exit gs_module_exit(void)
 	put_tty_driver(gs_tty_driver);
 	put_tty_driver(gs_tty_driver);
 	usb_gadget_unregister_driver(&gs_gadget_driver);
 	usb_gadget_unregister_driver(&gs_gadget_driver);
 
 
-	printk(KERN_INFO "gs_module_exit: %s %s unloaded\n", GS_LONG_NAME, GS_VERSION_STR);
+	pr_info("gs_module_exit: %s %s unloaded\n",
+			GS_LONG_NAME, GS_VERSION_STR);
 }
 }
 
 
 /* TTY Driver */
 /* TTY Driver */
@@ -621,7 +625,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
 	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
 
 
 	if (port_num < 0 || port_num >= GS_NUM_PORTS) {
 	if (port_num < 0 || port_num >= GS_NUM_PORTS) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n",
+		pr_err("gs_open: (%d,%p,%p) invalid port number\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -629,15 +633,14 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 	dev = gs_device;
 	dev = gs_device;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n",
+		pr_err("gs_open: (%d,%p,%p) NULL device pointer\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
 	mtx = &gs_open_close_lock[port_num];
 	mtx = &gs_open_close_lock[port_num];
 	if (mutex_lock_interruptible(mtx)) {
 	if (mutex_lock_interruptible(mtx)) {
-		printk(KERN_ERR
-		"gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
+		pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		return -ERESTARTSYS;
 		return -ERESTARTSYS;
 	}
 	}
@@ -645,8 +648,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 	spin_lock_irqsave(&dev->dev_lock, flags);
 	spin_lock_irqsave(&dev->dev_lock, flags);
 
 
 	if (dev->dev_config == GS_NO_CONFIG_ID) {
 	if (dev->dev_config == GS_NO_CONFIG_ID) {
-		printk(KERN_ERR
-			"gs_open: (%d,%p,%p) device is not connected\n",
+		pr_err("gs_open: (%d,%p,%p) device is not connected\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto exit_unlock_dev;
 		goto exit_unlock_dev;
@@ -655,7 +657,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 	port = dev->dev_port[port_num];
 	port = dev->dev_port[port_num];
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n",
+		pr_err("gs_open: (%d,%p,%p) NULL port pointer\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto exit_unlock_dev;
 		goto exit_unlock_dev;
@@ -665,7 +667,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 	spin_unlock(&dev->dev_lock);
 	spin_unlock(&dev->dev_lock);
 
 
 	if (port->port_dev == NULL) {
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n",
+		pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		ret = -EIO;
 		ret = -EIO;
 		goto exit_unlock_port;
 		goto exit_unlock_port;
@@ -692,8 +694,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 
 
 		/* might have been disconnected while asleep, check */
 		/* might have been disconnected while asleep, check */
 		if (port->port_dev == NULL) {
 		if (port->port_dev == NULL) {
-			printk(KERN_ERR
-				"gs_open: (%d,%p,%p) port disconnected (2)\n",
+			pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n",
 				port_num, tty, file);
 				port_num, tty, file);
 			port->port_in_use = 0;
 			port->port_in_use = 0;
 			ret = -EIO;
 			ret = -EIO;
@@ -701,7 +702,8 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 		}
 		}
 
 
 		if ((port->port_write_buf=buf) == NULL) {
 		if ((port->port_write_buf=buf) == NULL) {
-			printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n",
+			pr_err("gs_open: (%d,%p,%p) cannot allocate "
+				"port write buffer\n",
 				port_num, tty, file);
 				port_num, tty, file);
 			port->port_in_use = 0;
 			port->port_in_use = 0;
 			ret = -ENOMEM;
 			ret = -ENOMEM;
@@ -714,7 +716,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
 
 
 	/* might have been disconnected while asleep, check */
 	/* might have been disconnected while asleep, check */
 	if (port->port_dev == NULL) {
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n",
+		pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n",
 			port_num, tty, file);
 			port_num, tty, file);
 		port->port_in_use = 0;
 		port->port_in_use = 0;
 		ret = -EIO;
 		ret = -EIO;
@@ -762,7 +764,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 	struct mutex *mtx;
 	struct mutex *mtx;
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_close: NULL port pointer\n");
+		pr_err("gs_close: NULL port pointer\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -774,8 +776,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
 	spin_lock_irq(&port->port_lock);
 	spin_lock_irq(&port->port_lock);
 
 
 	if (port->port_open_count == 0) {
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR
-			"gs_close: (%d,%p,%p) port is already closed\n",
+		pr_err("gs_close: (%d,%p,%p) port is already closed\n",
 			port->port_num, tty, file);
 			port->port_num, tty, file);
 		goto exit;
 		goto exit;
 	}
 	}
@@ -837,7 +838,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
 	int ret;
 	int ret;
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_write: NULL port pointer\n");
+		pr_err("gs_write: NULL port pointer\n");
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
@@ -850,14 +851,14 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
 	spin_lock_irqsave(&port->port_lock, flags);
 	spin_lock_irqsave(&port->port_lock, flags);
 
 
 	if (port->port_dev == NULL) {
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n",
+		pr_err("gs_write: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		ret = -EIO;
 		ret = -EIO;
 		goto exit;
 		goto exit;
 	}
 	}
 
 
 	if (port->port_open_count == 0) {
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_write: (%d,%p) port is closed\n",
+		pr_err("gs_write: (%d,%p) port is closed\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		ret = -EBADF;
 		ret = -EBADF;
 		goto exit;
 		goto exit;
@@ -888,7 +889,7 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
 	struct gs_port *port = tty->driver_data;
 	struct gs_port *port = tty->driver_data;
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_put_char: NULL port pointer\n");
+		pr_err("gs_put_char: NULL port pointer\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -898,13 +899,13 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
 	spin_lock_irqsave(&port->port_lock, flags);
 	spin_lock_irqsave(&port->port_lock, flags);
 
 
 	if (port->port_dev == NULL) {
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR "gs_put_char: (%d,%p) port is not connected\n",
+		pr_err("gs_put_char: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		goto exit;
 		goto exit;
 	}
 	}
 
 
 	if (port->port_open_count == 0) {
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n",
+		pr_err("gs_put_char: (%d,%p) port is closed\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		goto exit;
 		goto exit;
 	}
 	}
@@ -924,7 +925,7 @@ static void gs_flush_chars(struct tty_struct *tty)
 	struct gs_port *port = tty->driver_data;
 	struct gs_port *port = tty->driver_data;
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_flush_chars: NULL port pointer\n");
+		pr_err("gs_flush_chars: NULL port pointer\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -933,14 +934,13 @@ static void gs_flush_chars(struct tty_struct *tty)
 	spin_lock_irqsave(&port->port_lock, flags);
 	spin_lock_irqsave(&port->port_lock, flags);
 
 
 	if (port->port_dev == NULL) {
 	if (port->port_dev == NULL) {
-		printk(KERN_ERR
-			"gs_flush_chars: (%d,%p) port is not connected\n",
+		pr_err("gs_flush_chars: (%d,%p) port is not connected\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		goto exit;
 		goto exit;
 	}
 	}
 
 
 	if (port->port_open_count == 0) {
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n",
+		pr_err("gs_flush_chars: (%d,%p) port is closed\n",
 			port->port_num, tty);
 			port->port_num, tty);
 		goto exit;
 		goto exit;
 	}
 	}
@@ -1038,7 +1038,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
 	struct gs_port *port = tty->driver_data;
 	struct gs_port *port = tty->driver_data;
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_ioctl: NULL port pointer\n");
+		pr_err("gs_ioctl: NULL port pointer\n");
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
@@ -1076,7 +1076,7 @@ static int gs_send(struct gs_dev *dev)
 	struct gs_req_entry *req_entry;
 	struct gs_req_entry *req_entry;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_send: NULL device pointer\n");
+		pr_err("gs_send: NULL device pointer\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -1103,7 +1103,7 @@ static int gs_send(struct gs_dev *dev)
 			req->length = len;
 			req->length = len;
 			spin_unlock_irqrestore(&dev->dev_lock, flags);
 			spin_unlock_irqrestore(&dev->dev_lock, flags);
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				printk(KERN_ERR
+				pr_err(
 				"gs_send: cannot queue read request, ret=%d\n",
 				"gs_send: cannot queue read request, ret=%d\n",
 					ret);
 					ret);
 				spin_lock_irqsave(&dev->dev_lock, flags);
 				spin_lock_irqsave(&dev->dev_lock, flags);
@@ -1144,9 +1144,7 @@ static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size)
 	port = dev->dev_port[0];
 	port = dev->dev_port[0];
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR
-			"gs_send_packet: port=%d, NULL port pointer\n",
-			0);
+		pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0);
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
@@ -1193,7 +1191,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
 	port = dev->dev_port[0];
 	port = dev->dev_port[0];
 
 
 	if (port == NULL) {
 	if (port == NULL) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, NULL port pointer\n",
+		pr_err("gs_recv_packet: port=%d, NULL port pointer\n",
 			port->port_num);
 			port->port_num);
 		return -EIO;
 		return -EIO;
 	}
 	}
@@ -1201,7 +1199,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
 	spin_lock(&port->port_lock);
 	spin_lock(&port->port_lock);
 
 
 	if (port->port_open_count == 0) {
 	if (port->port_open_count == 0) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, port is closed\n",
+		pr_err("gs_recv_packet: port=%d, port is closed\n",
 			port->port_num);
 			port->port_num);
 		ret = -EIO;
 		ret = -EIO;
 		goto exit;
 		goto exit;
@@ -1211,14 +1209,14 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
 	tty = port->port_tty;
 	tty = port->port_tty;
 
 
 	if (tty == NULL) {
 	if (tty == NULL) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
+		pr_err("gs_recv_packet: port=%d, NULL tty pointer\n",
 			port->port_num);
 			port->port_num);
 		ret = -EIO;
 		ret = -EIO;
 		goto exit;
 		goto exit;
 	}
 	}
 
 
 	if (port->port_tty->magic != TTY_MAGIC) {
 	if (port->port_tty->magic != TTY_MAGIC) {
-		printk(KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n",
+		pr_err("gs_recv_packet: port=%d, bad tty magic\n",
 			port->port_num);
 			port->port_num);
 		ret = -EIO;
 		ret = -EIO;
 		goto exit;
 		goto exit;
@@ -1245,7 +1243,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
 	struct gs_dev *dev = ep->driver_data;
 	struct gs_dev *dev = ep->driver_data;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_read_complete: NULL device pointer\n");
+		pr_err("gs_read_complete: NULL device pointer\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -1256,7 +1254,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
 requeue:
 requeue:
 		req->length = ep->maxpacket;
 		req->length = ep->maxpacket;
 		if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
 		if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-			printk(KERN_ERR
+			pr_err(
 			"gs_read_complete: cannot queue read request, ret=%d\n",
 			"gs_read_complete: cannot queue read request, ret=%d\n",
 				ret);
 				ret);
 		}
 		}
@@ -1270,7 +1268,7 @@ requeue:
 
 
 	default:
 	default:
 		/* unexpected */
 		/* unexpected */
-		printk(KERN_ERR
+		pr_err(
 		"gs_read_complete: unexpected status error, status=%d\n",
 		"gs_read_complete: unexpected status error, status=%d\n",
 			req->status);
 			req->status);
 		goto requeue;
 		goto requeue;
@@ -1287,7 +1285,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
 	struct gs_req_entry *gs_req = req->context;
 	struct gs_req_entry *gs_req = req->context;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_write_complete: NULL device pointer\n");
+		pr_err("gs_write_complete: NULL device pointer\n");
 		return;
 		return;
 	}
 	}
 
 
@@ -1296,8 +1294,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
 		/* normal completion */
 		/* normal completion */
 requeue:
 requeue:
 		if (gs_req == NULL) {
 		if (gs_req == NULL) {
-			printk(KERN_ERR
-				"gs_write_complete: NULL request pointer\n");
+			pr_err("gs_write_complete: NULL request pointer\n");
 			return;
 			return;
 		}
 		}
 
 
@@ -1316,7 +1313,7 @@ requeue:
 		break;
 		break;
 
 
 	default:
 	default:
-		printk(KERN_ERR
+		pr_err(
 		"gs_write_complete: unexpected status error, status=%d\n",
 		"gs_write_complete: unexpected status error, status=%d\n",
 			req->status);
 			req->status);
 		goto requeue;
 		goto requeue;
@@ -1351,7 +1348,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
 		gs_device_desc.bcdDevice =
 		gs_device_desc.bcdDevice =
 				cpu_to_le16(GS_VERSION_NUM | gcnum);
 				cpu_to_le16(GS_VERSION_NUM | gcnum);
 	else {
 	else {
-		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
+		pr_warning("gs_bind: controller '%s' not recognized\n",
 			gadget->name);
 			gadget->name);
 		/* unrecognized, but safe unless bulk is REALLY quirky */
 		/* unrecognized, but safe unless bulk is REALLY quirky */
 		gs_device_desc.bcdDevice =
 		gs_device_desc.bcdDevice =
@@ -1375,7 +1372,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
 	if (use_acm) {
 	if (use_acm) {
 		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
 		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
 		if (!ep) {
 		if (!ep) {
-			printk(KERN_ERR "gs_bind: cannot run ACM on %s\n", gadget->name);
+			pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
 			goto autoconf_fail;
 			goto autoconf_fail;
 		}
 		}
 		gs_device_desc.idProduct = __constant_cpu_to_le16(
 		gs_device_desc.idProduct = __constant_cpu_to_le16(
@@ -1425,7 +1422,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
 	set_gadget_data(gadget, dev);
 	set_gadget_data(gadget, dev);
 
 
 	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
 	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
-		printk(KERN_ERR "gs_bind: cannot allocate ports\n");
+		pr_err("gs_bind: cannot allocate ports\n");
 		gs_unbind(gadget);
 		gs_unbind(gadget);
 		return ret;
 		return ret;
 	}
 	}
@@ -1441,13 +1438,13 @@ static int __init gs_bind(struct usb_gadget *gadget)
 
 
 	gadget->ep0->driver_data = dev;
 	gadget->ep0->driver_data = dev;
 
 
-	printk(KERN_INFO "gs_bind: %s %s bound\n",
+	pr_info("gs_bind: %s %s bound\n",
 		GS_LONG_NAME, GS_VERSION_STR);
 		GS_LONG_NAME, GS_VERSION_STR);
 
 
 	return 0;
 	return 0;
 
 
 autoconf_fail:
 autoconf_fail:
-	printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);
+	pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 
@@ -1480,7 +1477,7 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
 		set_gadget_data(gadget, NULL);
 		set_gadget_data(gadget, NULL);
 	}
 	}
 
 
-	printk(KERN_INFO "gs_unbind: %s %s unbound\n", GS_LONG_NAME,
+	pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
 		GS_VERSION_STR);
 		GS_VERSION_STR);
 }
 }
 
 
@@ -1513,7 +1510,8 @@ static int gs_setup(struct usb_gadget *gadget,
 		break;
 		break;
 
 
 	default:
 	default:
-		printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
+		pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
+			"value=%04x, index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			ctrl->bRequestType, ctrl->bRequest,
 			wValue, wIndex, wLength);
 			wValue, wIndex, wLength);
 		break;
 		break;
@@ -1526,7 +1524,7 @@ static int gs_setup(struct usb_gadget *gadget,
 				&& (ret % gadget->ep0->maxpacket) == 0;
 				&& (ret % gadget->ep0->maxpacket) == 0;
 		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 		if (ret < 0) {
 		if (ret < 0) {
-			printk(KERN_ERR "gs_setup: cannot queue response, ret=%d\n",
+			pr_err("gs_setup: cannot queue response, ret=%d\n",
 				ret);
 				ret);
 			req->status = 0;
 			req->status = 0;
 			gs_setup_complete(gadget->ep0, req);
 			gs_setup_complete(gadget->ep0, req);
@@ -1656,7 +1654,8 @@ set_interface_done:
 		break;
 		break;
 
 
 	default:
 	default:
-		printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
+		pr_err("gs_setup: unknown standard request, type=%02x, "
+			"request=%02x, value=%04x, index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			ctrl->bRequestType, ctrl->bRequest,
 			wValue, wIndex, wLength);
 			wValue, wIndex, wLength);
 		break;
 		break;
@@ -1682,7 +1681,7 @@ static int gs_setup_class(struct usb_gadget *gadget,
 		 * handler copy that data to port->port_line_coding (iff
 		 * handler copy that data to port->port_line_coding (iff
 		 * it's valid) and maybe pass it on.  Until then, fail.
 		 * it's valid) and maybe pass it on.  Until then, fail.
 		 */
 		 */
-		printk(KERN_WARNING "gs_setup: set_line_coding "
+		pr_warning("gs_setup: set_line_coding "
 				"unuspported\n");
 				"unuspported\n");
 		break;
 		break;
 
 
@@ -1702,12 +1701,12 @@ static int gs_setup_class(struct usb_gadget *gadget,
 		 * handler use that to set the state (iff it's valid) and
 		 * handler use that to set the state (iff it's valid) and
 		 * maybe pass it on.  Until then, fail.
 		 * maybe pass it on.  Until then, fail.
 		 */
 		 */
-		printk(KERN_WARNING "gs_setup: set_control_line_state "
+		pr_warning("gs_setup: set_control_line_state "
 				"unuspported\n");
 				"unuspported\n");
 		break;
 		break;
 
 
 	default:
 	default:
-		printk(KERN_ERR "gs_setup: unknown class request, "
+		pr_err("gs_setup: unknown class request, "
 				"type=%02x, request=%02x, value=%04x, "
 				"type=%02x, request=%02x, value=%04x, "
 				"index=%04x, length=%d\n",
 				"index=%04x, length=%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			ctrl->bRequestType, ctrl->bRequest,
@@ -1724,7 +1723,8 @@ static int gs_setup_class(struct usb_gadget *gadget,
 static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
 static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
 {
 {
 	if (req->status || req->actual != req->length) {
 	if (req->status || req->actual != req->length) {
-		printk(KERN_ERR "gs_setup_complete: status error, status=%d, actual=%d, length=%d\n",
+		pr_err("gs_setup_complete: status error, status=%d, "
+			"actual=%d, length=%d\n",
 			req->status, req->actual, req->length);
 			req->status, req->actual, req->length);
 	}
 	}
 }
 }
@@ -1751,11 +1751,11 @@ static void gs_disconnect(struct usb_gadget *gadget)
 
 
 	/* re-allocate ports for the next connection */
 	/* re-allocate ports for the next connection */
 	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
 	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
-		printk(KERN_ERR "gs_disconnect: cannot re-allocate ports\n");
+		pr_err("gs_disconnect: cannot re-allocate ports\n");
 
 
 	spin_unlock_irqrestore(&dev->dev_lock, flags);
 	spin_unlock_irqrestore(&dev->dev_lock, flags);
 
 
-	printk(KERN_INFO "gs_disconnect: %s disconnected\n", GS_LONG_NAME);
+	pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
 }
 }
 
 
 /*
 /*
@@ -1778,7 +1778,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 	struct gs_req_entry *req_entry;
 	struct gs_req_entry *req_entry;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_set_config: NULL device pointer\n");
+		pr_err("gs_set_config: NULL device pointer\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1823,7 +1823,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 				dev->dev_notify_ep = ep;
 				dev->dev_notify_ep = ep;
 				dev->dev_notify_ep_desc = ep_desc;
 				dev->dev_notify_ep_desc = ep_desc;
 			} else {
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable notify endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable NOTIFY "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 					ep->name, ret);
 				goto exit_reset_config;
 				goto exit_reset_config;
 			}
 			}
@@ -1839,7 +1840,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 				dev->dev_in_ep = ep;
 				dev->dev_in_ep = ep;
 				dev->dev_in_ep_desc = ep_desc;
 				dev->dev_in_ep_desc = ep_desc;
 			} else {
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable in endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable IN "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 					ep->name, ret);
 				goto exit_reset_config;
 				goto exit_reset_config;
 			}
 			}
@@ -1855,7 +1857,8 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 				dev->dev_out_ep = ep;
 				dev->dev_out_ep = ep;
 				dev->dev_out_ep_desc = ep_desc;
 				dev->dev_out_ep_desc = ep_desc;
 			} else {
 			} else {
-				printk(KERN_ERR "gs_set_config: cannot enable out endpoint %s, ret=%d\n",
+				pr_err("gs_set_config: cannot enable OUT "
+					"endpoint %s, ret=%d\n",
 					ep->name, ret);
 					ep->name, ret);
 				goto exit_reset_config;
 				goto exit_reset_config;
 			}
 			}
@@ -1865,7 +1868,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 
 
 	if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL
 	if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL
 	|| (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) {
 	|| (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) {
-		printk(KERN_ERR "gs_set_config: cannot find endpoints\n");
+		pr_err("gs_set_config: cannot find endpoints\n");
 		ret = -ENODEV;
 		ret = -ENODEV;
 		goto exit_reset_config;
 		goto exit_reset_config;
 	}
 	}
@@ -1876,11 +1879,12 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 		if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
 		if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
 			req->complete = gs_read_complete;
 			req->complete = gs_read_complete;
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
 			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				printk(KERN_ERR "gs_set_config: cannot queue read request, ret=%d\n",
-					ret);
+				pr_err("gs_set_config: cannot queue read "
+					"request, ret=%d\n", ret);
 			}
 			}
 		} else {
 		} else {
-			printk(KERN_ERR "gs_set_config: cannot allocate read requests\n");
+			pr_err("gs_set_config: cannot allocate "
+					"read requests\n");
 			ret = -ENOMEM;
 			ret = -ENOMEM;
 			goto exit_reset_config;
 			goto exit_reset_config;
 		}
 		}
@@ -1893,13 +1897,14 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 			req_entry->re_req->complete = gs_write_complete;
 			req_entry->re_req->complete = gs_write_complete;
 			list_add(&req_entry->re_entry, &dev->dev_req_list);
 			list_add(&req_entry->re_entry, &dev->dev_req_list);
 		} else {
 		} else {
-			printk(KERN_ERR "gs_set_config: cannot allocate write requests\n");
+			pr_err("gs_set_config: cannot allocate "
+					"write requests\n");
 			ret = -ENOMEM;
 			ret = -ENOMEM;
 			goto exit_reset_config;
 			goto exit_reset_config;
 		}
 		}
 	}
 	}
 
 
-	printk(KERN_INFO "gs_set_config: %s configured, %s speed %s config\n",
+	pr_info("gs_set_config: %s configured, %s speed %s config\n",
 		GS_LONG_NAME,
 		GS_LONG_NAME,
 		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
 		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
 		config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
 		config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
@@ -1926,7 +1931,7 @@ static void gs_reset_config(struct gs_dev *dev)
 	struct gs_req_entry *req_entry;
 	struct gs_req_entry *req_entry;
 
 
 	if (dev == NULL) {
 	if (dev == NULL) {
-		printk(KERN_ERR "gs_reset_config: NULL device pointer\n");
+		pr_err("gs_reset_config: NULL device pointer\n");
 		return;
 		return;
 	}
 	}
 
 

+ 2 - 2
drivers/usb/gadget/zero.c

@@ -1115,7 +1115,7 @@ zero_bind (struct usb_gadget *gadget)
 	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
 	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
 	if (!ep) {
 	if (!ep) {
 autoconf_fail:
 autoconf_fail:
-		printk (KERN_ERR "%s: can't autoconfigure on %s\n",
+		pr_err("%s: can't autoconfigure on %s\n",
 			shortname, gadget->name);
 			shortname, gadget->name);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
@@ -1139,7 +1139,7 @@ autoconf_fail:
 		 * things like configuration and altsetting numbering
 		 * things like configuration and altsetting numbering
 		 * can need hardware-specific attention though.
 		 * can need hardware-specific attention though.
 		 */
 		 */
-		printk (KERN_WARNING "%s: controller '%s' not recognized\n",
+		pr_warning("%s: controller '%s' not recognized\n",
 			shortname, gadget->name);
 			shortname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
 	}
 	}

+ 11 - 11
drivers/usb/host/Kconfig

@@ -29,15 +29,6 @@ config USB_EHCI_HCD
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called ehci-hcd.
 	  module will be called ehci-hcd.
 
 
-config USB_EHCI_SPLIT_ISO
-	bool "Full speed ISO transactions (EXPERIMENTAL)"
-	depends on USB_EHCI_HCD && EXPERIMENTAL
-	default n
-	---help---
-	  This code is new and hasn't been used with many different
-	  EHCI or USB 2.0 transaction translator implementations.
-	  It should work for ISO-OUT transfers, like audio.
-
 config USB_EHCI_ROOT_HUB_TT
 config USB_EHCI_ROOT_HUB_TT
 	bool "Root Hub Transaction Translators (EXPERIMENTAL)"
 	bool "Root Hub Transaction Translators (EXPERIMENTAL)"
 	depends on USB_EHCI_HCD && EXPERIMENTAL
 	depends on USB_EHCI_HCD && EXPERIMENTAL
@@ -69,21 +60,30 @@ config USB_EHCI_TT_NEWSCHED
 
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
 	bool
-	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX)
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX)
 	default y
 	default y
 
 
 config USB_EHCI_BIG_ENDIAN_DESC
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
 	bool
-	depends on USB_EHCI_HCD && 440EPX
+	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX)
 	default y
 	default y
 
 
 config USB_EHCI_FSL
 config USB_EHCI_FSL
 	bool
 	bool
+	depends on USB_EHCI_HCD
 	select USB_EHCI_ROOT_HUB_TT
 	select USB_EHCI_ROOT_HUB_TT
 	default y if MPC834x || PPC_MPC831x
 	default y if MPC834x || PPC_MPC831x
 	---help---
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 	  Variation of ARC USB block used in some Freescale chips.
 
 
+config USB_EHCI_HCD_PPC_OF
+	bool "EHCI support for PPC USB controller on OF platform bus"
+	depends on USB_EHCI_HCD && PPC_OF
+	default y
+	---help---
+	  Enables support for the USB controller present on the PowerPC
+	  OpenFirmware platform bus.
+
 config USB_ISP116X_HCD
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	tristate "ISP116X HCD support"
 	depends on USB
 	depends on USB

+ 1 - 0
drivers/usb/host/ehci-au1xxx.c

@@ -222,6 +222,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
 	.hub_control = ehci_hub_control,
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 188 - 43
drivers/usb/host/ehci-dbg.c

@@ -323,7 +323,43 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
 
 
 #else
 #else
 
 
-/* troubleshooting help: expose state in sysfs */
+/* troubleshooting help: expose state in debugfs */
+
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+
+static struct dentry *ehci_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);	/* fill method */
+	struct usb_bus *bus;
+	struct mutex mutex;	/* protect filling of buffer */
+	size_t count;		/* number of characters filled into buffer */
+	char *page;
+};
 
 
 #define speed_char(info1) ({ char tmp; \
 #define speed_char(info1) ({ char tmp; \
 		switch (info1 & (3 << 12)) { \
 		switch (info1 & (3 << 12)) { \
@@ -441,10 +477,8 @@ done:
 	*nextp = next;
 	*nextp = next;
 }
 }
 
 
-static ssize_t
-show_async (struct class_device *class_dev, char *buf)
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	unsigned long		flags;
@@ -452,14 +486,13 @@ show_async (struct class_device *class_dev, char *buf)
 	char			*next;
 	char			*next;
 	struct ehci_qh		*qh;
 	struct ehci_qh		*qh;
 
 
-	*buf = 0;
-
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 	size = PAGE_SIZE;
 
 
+	*next = 0;
+
 	/* dumps a snapshot of the async schedule.
 	/* dumps a snapshot of the async schedule.
 	 * usually empty except for long-term bulk reads, or head.
 	 * usually empty except for long-term bulk reads, or head.
 	 * one QH per line, and TDs we know about
 	 * one QH per line, and TDs we know about
@@ -477,16 +510,12 @@ show_async (struct class_device *class_dev, char *buf)
 	}
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
 
-	return strlen (buf);
+	return strlen(buf->page);
 }
 }
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
 
 
 #define DBG_SCHED_LIMIT 64
 #define DBG_SCHED_LIMIT 64
-
-static ssize_t
-show_periodic (struct class_device *class_dev, char *buf)
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	unsigned long		flags;
@@ -500,10 +529,9 @@ show_periodic (struct class_device *class_dev, char *buf)
 		return 0;
 		return 0;
 	seen_count = 0;
 	seen_count = 0;
 
 
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 	size = PAGE_SIZE;
 
 
 	temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
 	temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size);
@@ -623,14 +651,10 @@ show_periodic (struct class_device *class_dev, char *buf)
 
 
 	return PAGE_SIZE - size;
 	return PAGE_SIZE - size;
 }
 }
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
 #undef DBG_SCHED_LIMIT
 #undef DBG_SCHED_LIMIT
 
 
-static ssize_t
-show_registers (struct class_device *class_dev, char *buf)
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
 {
-	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
 	struct ehci_hcd		*ehci;
 	struct ehci_hcd		*ehci;
 	unsigned long		flags;
 	unsigned long		flags;
@@ -639,15 +663,14 @@ show_registers (struct class_device *class_dev, char *buf)
 	static char		fmt [] = "%*s\n";
 	static char		fmt [] = "%*s\n";
 	static char		label [] = "";
 	static char		label [] = "";
 
 
-	bus = class_get_devdata(class_dev);
-	hcd = bus_to_hcd(bus);
+	hcd = bus_to_hcd(buf->bus);
 	ehci = hcd_to_ehci (hcd);
 	ehci = hcd_to_ehci (hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 	size = PAGE_SIZE;
 
 
 	spin_lock_irqsave (&ehci->lock, flags);
 	spin_lock_irqsave (&ehci->lock, flags);
 
 
-	if (bus->controller->power.power_state.event) {
+	if (buf->bus->controller->power.power_state.event) {
 		size = scnprintf (next, size,
 		size = scnprintf (next, size,
 			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
 			"bus %s, device %s (driver " DRIVER_VERSION ")\n"
 			"%s\n"
 			"%s\n"
@@ -763,9 +786,7 @@ show_registers (struct class_device *class_dev, char *buf)
 	}
 	}
 
 
 	if (ehci->reclaim) {
 	if (ehci->reclaim) {
-		temp = scnprintf (next, size, "reclaim qh %p%s\n",
-				ehci->reclaim,
-				ehci->reclaim_ready ? " ready" : "");
+		temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim);
 		size -= temp;
 		size -= temp;
 		next += temp;
 		next += temp;
 	}
 	}
@@ -789,26 +810,150 @@ done:
 
 
 	return PAGE_SIZE - size;
 	return PAGE_SIZE - size;
 }
 }
-static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 
-static inline void create_debug_files (struct ehci_hcd *ehci)
+static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
+				ssize_t (*fill_func)(struct debug_buffer *))
 {
 {
-	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
-	int retval;
+	struct debug_buffer *buf;
+
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
 
 
-	retval = class_device_create_file(cldev, &class_device_attr_async);
-	retval = class_device_create_file(cldev, &class_device_attr_periodic);
-	retval = class_device_create_file(cldev, &class_device_attr_registers);
+	if (buf) {
+		buf->bus = bus;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+	}
+
+	return buf;
 }
 }
 
 
-static inline void remove_debug_files (struct ehci_hcd *ehci)
+static int fill_buffer(struct debug_buffer *buf)
 {
 {
-	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+	int ret = 0;
+
+	if (!buf->page)
+		buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+
+	if (!buf->page) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
 
 
-	class_device_remove_file(cldev, &class_device_attr_async);
-	class_device_remove_file(cldev, &class_device_attr_periodic);
-	class_device_remove_file(cldev, &class_device_attr_registers);
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
 }
 }
 
 
-#endif /* STUB_DEBUG_FILES */
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			    size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+				      buf->page, buf->count);
+
+out:
+	return ret;
+
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
 
 
+	if (buf) {
+		if (buf->page)
+			free_page((unsigned long)buf->page);
+		kfree(buf);
+	}
+
+	return 0;
+}
+static int debug_async_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_periodic_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static inline void create_debug_files (struct ehci_hcd *ehci)
+{
+	struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
+
+	ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root);
+	if (!ehci->debug_dir)
+		goto dir_error;
+
+	ehci->debug_async = debugfs_create_file("async", S_IRUGO,
+						ehci->debug_dir, bus,
+						&debug_async_fops);
+	if (!ehci->debug_async)
+		goto async_error;
+
+	ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
+						   ehci->debug_dir, bus,
+						   &debug_periodic_fops);
+	if (!ehci->debug_periodic)
+		goto periodic_error;
+
+	ehci->debug_registers = debugfs_create_file("registers", S_IRUGO,
+						    ehci->debug_dir, bus,
+						    &debug_registers_fops);
+	if (!ehci->debug_registers)
+		goto registers_error;
+	return;
+
+registers_error:
+	debugfs_remove(ehci->debug_periodic);
+periodic_error:
+	debugfs_remove(ehci->debug_async);
+async_error:
+	debugfs_remove(ehci->debug_dir);
+dir_error:
+	ehci->debug_periodic = NULL;
+	ehci->debug_async = NULL;
+	ehci->debug_dir = NULL;
+}
+
+static inline void remove_debug_files (struct ehci_hcd *ehci)
+{
+	debugfs_remove(ehci->debug_registers);
+	debugfs_remove(ehci->debug_periodic);
+	debugfs_remove(ehci->debug_async);
+	debugfs_remove(ehci->debug_dir);
+}
+
+#endif /* STUB_DEBUG_FILES */

+ 2 - 1
drivers/usb/host/ehci-fsl.c

@@ -25,7 +25,7 @@
 
 
 #include "ehci-fsl.h"
 #include "ehci-fsl.h"
 
 
-/* FIXME: Power Managment is un-ported so temporarily disable it */
+/* FIXME: Power Management is un-ported so temporarily disable it */
 #undef CONFIG_PM
 #undef CONFIG_PM
 
 
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
@@ -323,6 +323,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
 	.hub_control = ehci_hub_control,
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 };
 
 
 static int ehci_fsl_drv_probe(struct platform_device *pdev)
 static int ehci_fsl_drv_probe(struct platform_device *pdev)

+ 118 - 41
drivers/usb/host/ehci-hcd.c

@@ -33,6 +33,7 @@
 #include <linux/usb.h>
 #include <linux/usb.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
+#include <linux/debugfs.h>
 
 
 #include "../core/hcd.h"
 #include "../core/hcd.h"
 
 
@@ -109,7 +110,7 @@ static const char	hcd_name [] = "ehci_hcd";
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_MULT_TT	1
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 #define	EHCI_TUNE_FLS		2	/* (small) 256 frame schedule */
 
 
-#define EHCI_IAA_JIFFIES	(HZ/100)	/* arbitrary; ~10 msec */
+#define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
 #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
 #define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
@@ -266,6 +267,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
+static void end_unlink_async(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 
 
 #include "ehci-hub.c"
 #include "ehci-hub.c"
@@ -275,25 +277,41 @@ static void ehci_work(struct ehci_hcd *ehci);
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
-static void ehci_watchdog (unsigned long param)
+static void ehci_iaa_watchdog(unsigned long param)
 {
 {
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
 	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
 	unsigned long		flags;
 	unsigned long		flags;
+	u32			status, cmd;
 
 
 	spin_lock_irqsave (&ehci->lock, flags);
 	spin_lock_irqsave (&ehci->lock, flags);
+	WARN_ON(!ehci->reclaim);
 
 
-	/* lost IAA irqs wedge things badly; seen with a vt8235 */
+	status = ehci_readl(ehci, &ehci->regs->status);
+	cmd = ehci_readl(ehci, &ehci->regs->command);
+	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+
+	/* lost IAA irqs wedge things badly; seen first with a vt8235 */
 	if (ehci->reclaim) {
 	if (ehci->reclaim) {
-		u32		status = ehci_readl(ehci, &ehci->regs->status);
 		if (status & STS_IAA) {
 		if (status & STS_IAA) {
 			ehci_vdbg (ehci, "lost IAA\n");
 			ehci_vdbg (ehci, "lost IAA\n");
 			COUNT (ehci->stats.lost_iaa);
 			COUNT (ehci->stats.lost_iaa);
 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
 			ehci_writel(ehci, STS_IAA, &ehci->regs->status);
-			ehci->reclaim_ready = 1;
 		}
 		}
+		ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
+		end_unlink_async(ehci);
 	}
 	}
 
 
- 	/* stop async processing after it's idled a bit */
+	spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_watchdog(unsigned long param)
+{
+	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+
+	/* stop async processing after it's idled a bit */
 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
 	if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
 		start_unlink_async (ehci, ehci->async);
 		start_unlink_async (ehci, ehci->async);
 
 
@@ -363,8 +381,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 static void ehci_work (struct ehci_hcd *ehci)
 static void ehci_work (struct ehci_hcd *ehci)
 {
 {
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
-	if (ehci->reclaim_ready)
-		end_unlink_async (ehci);
 
 
 	/* another CPU may drop ehci->lock during a schedule scan while
 	/* another CPU may drop ehci->lock during a schedule scan while
 	 * it reports urb completions.  this flag guards against bogus
 	 * it reports urb completions.  this flag guards against bogus
@@ -399,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd)
 
 
 	/* no more interrupts ... */
 	/* no more interrupts ... */
 	del_timer_sync (&ehci->watchdog);
 	del_timer_sync (&ehci->watchdog);
+	del_timer_sync(&ehci->iaa_watchdog);
 
 
 	spin_lock_irq(&ehci->lock);
 	spin_lock_irq(&ehci->lock);
 	if (HC_IS_RUNNING (hcd->state))
 	if (HC_IS_RUNNING (hcd->state))
@@ -447,6 +464,10 @@ static int ehci_init(struct usb_hcd *hcd)
 	ehci->watchdog.function = ehci_watchdog;
 	ehci->watchdog.function = ehci_watchdog;
 	ehci->watchdog.data = (unsigned long) ehci;
 	ehci->watchdog.data = (unsigned long) ehci;
 
 
+	init_timer(&ehci->iaa_watchdog);
+	ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+	ehci->iaa_watchdog.data = (unsigned long) ehci;
+
 	/*
 	/*
 	 * hw default: 1K periodic list heads, one per frame.
 	 * hw default: 1K periodic list heads, one per frame.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -463,7 +484,6 @@ static int ehci_init(struct usb_hcd *hcd)
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 		ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
 
 	ehci->reclaim = NULL;
 	ehci->reclaim = NULL;
-	ehci->reclaim_ready = 0;
 	ehci->next_uframe = -1;
 	ehci->next_uframe = -1;
 
 
 	/*
 	/*
@@ -654,8 +674,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 	/* complete the unlinking of some qh [4.15.2.3] */
 	/* complete the unlinking of some qh [4.15.2.3] */
 	if (status & STS_IAA) {
 	if (status & STS_IAA) {
 		COUNT (ehci->stats.reclaim);
 		COUNT (ehci->stats.reclaim);
-		ehci->reclaim_ready = 1;
-		bh = 1;
+		end_unlink_async(ehci);
 	}
 	}
 
 
 	/* remote wakeup [4.3.1] */
 	/* remote wakeup [4.3.1] */
@@ -761,10 +780,16 @@ static int ehci_urb_enqueue (
 
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 {
-	/* if we need to use IAA and it's busy, defer */
-	if (qh->qh_state == QH_STATE_LINKED
-			&& ehci->reclaim
-			&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+	/* failfast */
+	if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
+		end_unlink_async(ehci);
+
+	/* if it's not linked then there's nothing to do */
+	if (qh->qh_state != QH_STATE_LINKED)
+		;
+
+	/* defer till later if busy */
+	else if (ehci->reclaim) {
 		struct ehci_qh		*last;
 		struct ehci_qh		*last;
 
 
 		for (last = ehci->reclaim;
 		for (last = ehci->reclaim;
@@ -774,12 +799,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		qh->qh_state = QH_STATE_UNLINK_WAIT;
 		qh->qh_state = QH_STATE_UNLINK_WAIT;
 		last->reclaim = qh;
 		last->reclaim = qh;
 
 
-	/* bypass IAA if the hc can't care */
-	} else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
-		end_unlink_async (ehci);
-
-	/* something else might have unlinked the qh by now */
-	if (qh->qh_state == QH_STATE_LINKED)
+	/* start IAA cycle */
+	} else
 		start_unlink_async (ehci, qh);
 		start_unlink_async (ehci, qh);
 }
 }
 
 
@@ -806,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		qh = (struct ehci_qh *) urb->hcpriv;
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 		if (!qh)
 			break;
 			break;
-		unlink_async (ehci, qh);
+		switch (qh->qh_state) {
+		case QH_STATE_LINKED:
+		case QH_STATE_COMPLETING:
+			unlink_async(ehci, qh);
+			break;
+		case QH_STATE_UNLINK:
+		case QH_STATE_UNLINK_WAIT:
+			/* already started */
+			break;
+		case QH_STATE_IDLE:
+			WARN_ON(1);
+			break;
+		}
 		break;
 		break;
 
 
 	case PIPE_INTERRUPT:
 	case PIPE_INTERRUPT:
@@ -829,16 +862,16 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 		/* reschedule QH iff another request is queued */
 		/* reschedule QH iff another request is queued */
 		if (!list_empty (&qh->qtd_list)
 		if (!list_empty (&qh->qtd_list)
 				&& HC_IS_RUNNING (hcd->state)) {
 				&& HC_IS_RUNNING (hcd->state)) {
-			int status;
+			int schedule_status;
 
 
-			status = qh_schedule (ehci, qh);
+			schedule_status = qh_schedule (ehci, qh);
 			spin_unlock_irqrestore (&ehci->lock, flags);
 			spin_unlock_irqrestore (&ehci->lock, flags);
 
 
-			if (status != 0) {
+			if (schedule_status != 0) {
 				// shouldn't happen often, but ...
 				// shouldn't happen often, but ...
 				// FIXME kill those tds' urbs
 				// FIXME kill those tds' urbs
 				err ("can't reschedule qh %p, err %d",
 				err ("can't reschedule qh %p, err %d",
-					qh, status);
+					qh, schedule_status);
 			}
 			}
 			return status;
 			return status;
 		}
 		}
@@ -898,6 +931,7 @@ rescan:
 		unlink_async (ehci, qh);
 		unlink_async (ehci, qh);
 		/* FALL THROUGH */
 		/* FALL THROUGH */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
+	case QH_STATE_UNLINK_WAIT:
 idle_timeout:
 idle_timeout:
 		spin_unlock_irqrestore (&ehci->lock, flags);
 		spin_unlock_irqrestore (&ehci->lock, flags);
 		schedule_timeout_uninterruptible(1);
 		schedule_timeout_uninterruptible(1);
@@ -959,11 +993,26 @@ MODULE_LICENSE ("GPL");
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver
 #endif
 #endif
 
 
-#ifdef CONFIG_440EPX
+#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE)
 #include "ehci-ppc-soc.c"
 #include "ehci-ppc-soc.c"
 #define	PLATFORM_DRIVER		ehci_ppc_soc_driver
 #define	PLATFORM_DRIVER		ehci_ppc_soc_driver
 #endif
 #endif
 
 
+#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
+#include "ehci-ppc-of.c"
+#define OF_PLATFORM_DRIVER	ehci_hcd_ppc_of_driver
+#endif
+
+#ifdef CONFIG_ARCH_ORION
+#include "ehci-orion.c"
+#define	PLATFORM_DRIVER		ehci_orion_driver
+#endif
+
+#ifdef CONFIG_ARCH_IXP4XX
+#include "ehci-ixp4xx.c"
+#define	PLATFORM_DRIVER		ixp4xx_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER)
     !defined(PS3_SYSTEM_BUS_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #error "missing bus glue for ehci-hcd"
@@ -978,41 +1027,66 @@ static int __init ehci_hcd_init(void)
 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
 		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
 		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
 		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
 
 
+#ifdef DEBUG
+	ehci_debug_root = debugfs_create_dir("ehci", NULL);
+	if (!ehci_debug_root)
+		return -ENOENT;
+#endif
+
 #ifdef PLATFORM_DRIVER
 #ifdef PLATFORM_DRIVER
 	retval = platform_driver_register(&PLATFORM_DRIVER);
 	retval = platform_driver_register(&PLATFORM_DRIVER);
 	if (retval < 0)
 	if (retval < 0)
-		return retval;
+		goto clean0;
 #endif
 #endif
 
 
 #ifdef PCI_DRIVER
 #ifdef PCI_DRIVER
 	retval = pci_register_driver(&PCI_DRIVER);
 	retval = pci_register_driver(&PCI_DRIVER);
-	if (retval < 0) {
-#ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
-#endif
-		return retval;
-	}
+	if (retval < 0)
+		goto clean1;
 #endif
 #endif
 
 
 #ifdef PS3_SYSTEM_BUS_DRIVER
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
 	retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
-	if (retval < 0) {
-#ifdef PLATFORM_DRIVER
-		platform_driver_unregister(&PLATFORM_DRIVER);
+	if (retval < 0)
+		goto clean2;
+#endif
+
+#ifdef OF_PLATFORM_DRIVER
+	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	if (retval < 0)
+		goto clean3;
+#endif
+	return retval;
+
+#ifdef OF_PLATFORM_DRIVER
+	/* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */
+clean3:
+#endif
+#ifdef PS3_SYSTEM_BUS_DRIVER
+	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+clean2:
 #endif
 #endif
 #ifdef PCI_DRIVER
 #ifdef PCI_DRIVER
-		pci_unregister_driver(&PCI_DRIVER);
+	pci_unregister_driver(&PCI_DRIVER);
+clean1:
 #endif
 #endif
-		return retval;
-	}
+#ifdef PLATFORM_DRIVER
+	platform_driver_unregister(&PLATFORM_DRIVER);
+clean0:
+#endif
+#ifdef DEBUG
+	debugfs_remove(ehci_debug_root);
+	ehci_debug_root = NULL;
 #endif
 #endif
-
 	return retval;
 	return retval;
 }
 }
 module_init(ehci_hcd_init);
 module_init(ehci_hcd_init);
 
 
 static void __exit ehci_hcd_cleanup(void)
 static void __exit ehci_hcd_cleanup(void)
 {
 {
+#ifdef OF_PLATFORM_DRIVER
+	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
 #ifdef PLATFORM_DRIVER
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
 #endif
@@ -1022,6 +1096,9 @@ static void __exit ehci_hcd_cleanup(void)
 #ifdef PS3_SYSTEM_BUS_DRIVER
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 	ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 #endif
+#ifdef DEBUG
+	debugfs_remove(ehci_debug_root);
+#endif
 }
 }
 module_exit(ehci_hcd_cleanup);
 module_exit(ehci_hcd_cleanup);
 
 

+ 61 - 37
drivers/usb/host/ehci-hub.c

@@ -123,6 +123,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 
 
 	if (time_before (jiffies, ehci->next_statechange))
 	if (time_before (jiffies, ehci->next_statechange))
 		msleep(5);
 		msleep(5);
+	del_timer_sync(&ehci->watchdog);
+	del_timer_sync(&ehci->iaa_watchdog);
 
 
 	port = HCS_N_PORTS (ehci->hcs_params);
 	port = HCS_N_PORTS (ehci->hcs_params);
 	spin_lock_irq (&ehci->lock);
 	spin_lock_irq (&ehci->lock);
@@ -134,7 +136,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 	}
 	}
 	ehci->command = ehci_readl(ehci, &ehci->regs->command);
 	ehci->command = ehci_readl(ehci, &ehci->regs->command);
 	if (ehci->reclaim)
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async(ehci);
 	ehci_work(ehci);
 	ehci_work(ehci);
 
 
 	/* Unlike other USB host controller types, EHCI doesn't have
 	/* Unlike other USB host controller types, EHCI doesn't have
@@ -170,8 +172,11 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
 		}
 		}
 	}
 	}
 
 
+	/* Apparently some devices need a >= 1-uframe delay here */
+	if (ehci->bus_suspended)
+		udelay(150);
+
 	/* turn off now-idle HC */
 	/* turn off now-idle HC */
-	del_timer_sync (&ehci->watchdog);
 	ehci_halt (ehci);
 	ehci_halt (ehci);
 	hcd->state = HC_STATE_SUSPENDED;
 	hcd->state = HC_STATE_SUSPENDED;
 
 
@@ -291,14 +296,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /* Display the ports dedicated to the companion controller */
 /* Display the ports dedicated to the companion controller */
-static ssize_t show_companion(struct class_device *class_dev, char *buf)
+static ssize_t show_companion(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
 {
 {
 	struct ehci_hcd		*ehci;
 	struct ehci_hcd		*ehci;
 	int			nports, index, n;
 	int			nports, index, n;
 	int			count = PAGE_SIZE;
 	int			count = PAGE_SIZE;
 	char			*ptr = buf;
 	char			*ptr = buf;
 
 
-	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
 	nports = HCS_N_PORTS(ehci->hcs_params);
 	nports = HCS_N_PORTS(ehci->hcs_params);
 
 
 	for (index = 0; index < nports; ++index) {
 	for (index = 0; index < nports; ++index) {
@@ -312,40 +319,21 @@ static ssize_t show_companion(struct class_device *class_dev, char *buf)
 }
 }
 
 
 /*
 /*
- * Dedicate or undedicate a port to the companion controller.
- * Syntax is "[-]portnum", where a leading '-' sign means
- * return control of the port to the EHCI controller.
+ * Sets the owner of a port
  */
  */
-static ssize_t store_companion(struct class_device *class_dev,
-		const char *buf, size_t count)
+static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
 {
 {
-	struct ehci_hcd		*ehci;
-	int			portnum, new_owner, try;
 	u32 __iomem		*status_reg;
 	u32 __iomem		*status_reg;
 	u32			port_status;
 	u32			port_status;
+	int 			try;
 
 
-	ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev)));
-	new_owner = PORT_OWNER;		/* Owned by companion */
-	if (sscanf(buf, "%d", &portnum) != 1)
-		return -EINVAL;
-	if (portnum < 0) {
-		portnum = - portnum;
-		new_owner = 0;		/* Owned by EHCI */
-	}
-	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
-		return -ENOENT;
-	status_reg = &ehci->regs->port_status[--portnum];
-	if (new_owner)
-		set_bit(portnum, &ehci->companion_ports);
-	else
-		clear_bit(portnum, &ehci->companion_ports);
+	status_reg = &ehci->regs->port_status[portnum];
 
 
 	/*
 	/*
 	 * The controller won't set the OWNER bit if the port is
 	 * The controller won't set the OWNER bit if the port is
 	 * enabled, so this loop will sometimes require at least two
 	 * enabled, so this loop will sometimes require at least two
 	 * iterations: one to disable the port and one to set OWNER.
 	 * iterations: one to disable the port and one to set OWNER.
 	 */
 	 */
-
 	for (try = 4; try > 0; --try) {
 	for (try = 4; try > 0; --try) {
 		spin_lock_irq(&ehci->lock);
 		spin_lock_irq(&ehci->lock);
 		port_status = ehci_readl(ehci, status_reg);
 		port_status = ehci_readl(ehci, status_reg);
@@ -362,9 +350,39 @@ static ssize_t store_companion(struct class_device *class_dev,
 		if (try > 1)
 		if (try > 1)
 			msleep(5);
 			msleep(5);
 	}
 	}
+}
+
+/*
+ * Dedicate or undedicate a port to the companion controller.
+ * Syntax is "[-]portnum", where a leading '-' sign means
+ * return control of the port to the EHCI controller.
+ */
+static ssize_t store_companion(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct ehci_hcd		*ehci;
+	int			portnum, new_owner;
+
+	ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+	new_owner = PORT_OWNER;		/* Owned by companion */
+	if (sscanf(buf, "%d", &portnum) != 1)
+		return -EINVAL;
+	if (portnum < 0) {
+		portnum = - portnum;
+		new_owner = 0;		/* Owned by EHCI */
+	}
+	if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
+		return -ENOENT;
+	portnum--;
+	if (new_owner)
+		set_bit(portnum, &ehci->companion_ports);
+	else
+		clear_bit(portnum, &ehci->companion_ports);
+	set_owner(ehci, portnum, new_owner);
 	return count;
 	return count;
 }
 }
-static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion);
+static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
 
 
 static inline void create_companion_file(struct ehci_hcd *ehci)
 static inline void create_companion_file(struct ehci_hcd *ehci)
 {
 {
@@ -372,16 +390,16 @@ static inline void create_companion_file(struct ehci_hcd *ehci)
 
 
 	/* with integrated TT there is no companion! */
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
 	if (!ehci_is_TDI(ehci))
-		i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev,
-				&class_device_attr_companion);
+		i = device_create_file(ehci_to_hcd(ehci)->self.dev,
+				       &dev_attr_companion);
 }
 }
 
 
 static inline void remove_companion_file(struct ehci_hcd *ehci)
 static inline void remove_companion_file(struct ehci_hcd *ehci)
 {
 {
 	/* with integrated TT there is no companion! */
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
 	if (!ehci_is_TDI(ehci))
-		class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev,
-				&class_device_attr_companion);
+		device_remove_file(ehci_to_hcd(ehci)->self.dev,
+				   &dev_attr_companion);
 }
 }
 
 
 
 
@@ -393,10 +411,8 @@ static int check_reset_complete (
 	u32 __iomem	*status_reg,
 	u32 __iomem	*status_reg,
 	int		port_status
 	int		port_status
 ) {
 ) {
-	if (!(port_status & PORT_CONNECT)) {
-		ehci->reset_done [index] = 0;
+	if (!(port_status & PORT_CONNECT))
 		return port_status;
 		return port_status;
-	}
 
 
 	/* if reset finished and it's still not enabled -- handoff */
 	/* if reset finished and it's still not enabled -- handoff */
 	if (!(port_status & PORT_PE)) {
 	if (!(port_status & PORT_PE)) {
@@ -475,8 +491,6 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 		 * controller by the user.
 		 * controller by the user.
 		 */
 		 */
 
 
-		if (!(temp & PORT_CONNECT))
-			ehci->reset_done [i] = 0;
 		if ((temp & mask) != 0
 		if ((temp & mask) != 0
 				|| ((temp & PORT_RESUME) != 0
 				|| ((temp & PORT_RESUME) != 0
 					&& time_after_eq(jiffies,
 					&& time_after_eq(jiffies,
@@ -864,3 +878,13 @@ error:
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	return retval;
 	return retval;
 }
 }
+
+static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+
+	if (ehci_is_TDI(ehci))
+		return;
+	set_owner(ehci, --portnum, PORT_OWNER);
+}
+

+ 152 - 0
drivers/usb/host/ehci-ixp4xx.c

@@ -0,0 +1,152 @@
+/*
+ * IXP4XX EHCI Host Controller Driver
+ *
+ * Author: Vladimir Barinov <vbarinov@ru.mvista.com>
+ *
+ * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/platform_device.h>
+
+static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval = 0;
+
+	ehci->big_endian_desc = 1;
+	ehci->big_endian_mmio = 1;
+
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100
+		+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	ehci->is_tdi_rh_tt = 1;
+	ehci_reset(ehci);
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver ixp4xx_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "IXP4XX EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+	.reset			= ixp4xx_ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#if defined(CONFIG_PM)
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+};
+
+static int ixp4xx_ehci_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
+	struct resource *res;
+	int irq;
+	int retval;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			pdev->dev.bus_id);
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto fail_create_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			pdev->dev.bus_id);
+		retval = -ENODEV;
+		goto fail_request_resource;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		retval = -EBUSY;
+		goto fail_request_resource;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		retval = -EFAULT;
+		goto fail_ioremap;
+	}
+
+	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (retval)
+		goto fail_add_hcd;
+
+	return retval;
+
+fail_add_hcd:
+	iounmap(hcd->regs);
+fail_ioremap:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+fail_request_resource:
+	usb_put_hcd(hcd);
+fail_create_hcd:
+	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+	return retval;
+}
+
+static int ixp4xx_ehci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+MODULE_ALIAS("ixp4xx-ehci");
+
+static struct platform_driver ixp4xx_ehci_driver = {
+	.probe = ixp4xx_ehci_probe,
+	.remove = ixp4xx_ehci_remove,
+	.driver = {
+		.name = "ixp4xx-ehci",
+		.bus = &platform_bus_type
+	},
+};

+ 272 - 0
drivers/usb/host/ehci-orion.c

@@ -0,0 +1,272 @@
+/*
+ * drivers/usb/host/ehci-orion.c
+ *
+ * Tzachi Perelstein <tzachi@marvell.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/arch/orion.h>
+
+#define rdl(off)	__raw_readl(hcd->regs + (off))
+#define wrl(off, val)	__raw_writel((val), hcd->regs + (off))
+
+#define USB_CAUSE		0x310
+#define USB_MASK		0x314
+#define USB_CMD			0x140
+#define USB_MODE		0x1a8
+#define USB_IPG			0x360
+#define USB_PHY_PWR_CTRL	0x400
+#define USB_PHY_TX_CTRL		0x420
+#define USB_PHY_RX_CTRL		0x430
+#define USB_PHY_IVREF_CTRL	0x440
+#define USB_PHY_TST_GRP_CTRL	0x450
+
+/*
+ * Implement Orion USB controller specification guidelines
+ */
+static void orion_usb_setup(struct usb_hcd *hcd)
+{
+	/*
+	 * Clear interrupt cause and mask
+	 */
+	wrl(USB_CAUSE, 0);
+	wrl(USB_MASK, 0);
+
+	/*
+	 * Reset controller
+	 */
+	wrl(USB_CMD, rdl(USB_CMD) | 0x2);
+	while (rdl(USB_CMD) & 0x2);
+
+	/*
+	 * GL# USB-10: Set IPG for non start of frame packets
+	 * Bits[14:8]=0xc
+	 */
+	wrl(USB_IPG, (rdl(USB_IPG) & ~0x7f00) | 0xc00);
+
+	/*
+	 * GL# USB-9: USB 2.0 Power Control
+	 * BG_VSEL[7:6]=0x1
+	 */
+	wrl(USB_PHY_PWR_CTRL, (rdl(USB_PHY_PWR_CTRL) & ~0xc0)| 0x40);
+
+	/*
+	 * GL# USB-1: USB PHY Tx Control - force calibration to '8'
+	 * TXDATA_BLOCK_EN[21]=0x1, EXT_RCAL_EN[13]=0x1, IMP_CAL[6:3]=0x8
+	 */
+	wrl(USB_PHY_TX_CTRL, (rdl(USB_PHY_TX_CTRL) & ~0x78) | 0x202040);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY Rx Control
+	 * RXDATA_BLOCK_LENGHT[31:30]=0x3, EDGE_DET_SEL[27:26]=0,
+	 * CDR_FASTLOCK_EN[21]=0, DISCON_THRESHOLD[9:8]=0, SQ_THRESH[7:4]=0x1
+	 */
+	wrl(USB_PHY_RX_CTRL, (rdl(USB_PHY_RX_CTRL) & ~0xc2003f0) | 0xc0000010);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY IVREF Control
+	 * PLLVDD12[1:0]=0x2, RXVDD[5:4]=0x3, Reserved[19]=0
+	 */
+	wrl(USB_PHY_IVREF_CTRL, (rdl(USB_PHY_IVREF_CTRL) & ~0x80003 ) | 0x32);
+
+	/*
+	 * GL# USB-3 GL# USB-9: USB PHY Test Group Control
+	 * REG_FIFO_SQ_RST[15]=0
+	 */
+	wrl(USB_PHY_TST_GRP_CTRL, rdl(USB_PHY_TST_GRP_CTRL) & ~0x8000);
+
+	/*
+	 * Stop and reset controller
+	 */
+	wrl(USB_CMD, rdl(USB_CMD) & ~0x1);
+	wrl(USB_CMD, rdl(USB_CMD) | 0x2);
+	while (rdl(USB_CMD) & 0x2);
+
+	/*
+	 * GL# USB-5 Streaming disable REG_USB_MODE[4]=1
+	 * TBD: This need to be done after each reset!
+	 * GL# USB-4 Setup USB Host mode
+	 */
+	wrl(USB_MODE, 0x13);
+}
+
+static int ehci_orion_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/*
+	 * data structure init
+	 */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci_reset(ehci);
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+static const struct hc_driver ehci_orion_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Marvell Orion EHCI",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_orion_setup,
+	.start = ehci_run,
+#ifdef CONFIG_PM
+	.suspend = ehci_bus_suspend,
+	.resume = ehci_bus_resume,
+#endif
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+	.bus_suspend = ehci_bus_suspend,
+	.bus_resume = ehci_bus_resume,
+};
+
+static int __init ehci_orion_drv_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	void __iomem *regs;
+	int irq, err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_debug("Initializing Orion-SoC USB Host Controller\n");
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev,
+			"Found HC with no IRQ. Check %s setup!\n",
+			pdev->dev.bus_id);
+		err = -ENODEV;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			pdev->dev.bus_id);
+		err = -ENODEV;
+		goto err1;
+	}
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				ehci_orion_hc_driver.description)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		err = -EBUSY;
+		goto err1;
+	}
+
+	regs = ioremap(res->start, res->end - res->start + 1);
+	if (regs == NULL) {
+		dev_dbg(&pdev->dev, "error mapping memory\n");
+		err = -EFAULT;
+		goto err2;
+	}
+
+	hcd = usb_create_hcd(&ehci_orion_hc_driver,
+			&pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		err = -ENOMEM;
+		goto err3;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->regs = regs;
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	ehci->is_tdi_rh_tt = 1;
+	ehci->sbrn = 0x20;
+
+	/*
+	 * setup Orion USB controller
+	 */
+	orion_usb_setup(hcd);
+
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
+	if (err)
+		goto err4;
+
+	return 0;
+
+err4:
+	usb_put_hcd(hcd);
+err3:
+	iounmap(regs);
+err2:
+	release_mem_region(res->start, res->end - res->start + 1);
+err1:
+	dev_err(&pdev->dev, "init %s fail, %d\n",
+		pdev->dev.bus_id, err);
+
+	return err;
+}
+
+static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+MODULE_ALIAS("platform:orion-ehci");
+
+static struct platform_driver ehci_orion_driver = {
+	.probe		= ehci_orion_drv_probe,
+	.remove		= __exit_p(ehci_orion_drv_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver.name	= "orion-ehci",
+};

+ 2 - 1
drivers/usb/host/ehci-pci.c

@@ -305,7 +305,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 	/* emptying the schedule aborts any urbs */
 	/* emptying the schedule aborts any urbs */
 	spin_lock_irq(&ehci->lock);
 	spin_lock_irq(&ehci->lock);
 	if (ehci->reclaim)
 	if (ehci->reclaim)
-		ehci->reclaim_ready = 1;
+		end_unlink_async(ehci);
 	ehci_work(ehci);
 	ehci_work(ehci);
 	spin_unlock_irq(&ehci->lock);
 	spin_unlock_irq(&ehci->lock);
 
 
@@ -364,6 +364,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
 	.hub_control =		ehci_hub_control,
 	.hub_control =		ehci_hub_control,
 	.bus_suspend =		ehci_bus_suspend,
 	.bus_suspend =		ehci_bus_suspend,
 	.bus_resume =		ehci_bus_resume,
 	.bus_resume =		ehci_bus_resume,
+	.relinquish_port = 	ehci_relinquish_port,
 };
 };
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 238 - 0
drivers/usb/host/ehci-ppc-of.c

@@ -0,0 +1,238 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus
+ * Tested on AMCC PPC 440EPx
+ *
+ * Valentine Barshak <vbarshak@ru.mvista.com>
+ *
+ * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
+ * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+/* called during probe() after chip reset completes */
+static int ehci_ppc_of_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		retval;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+	return ehci_reset(ehci);
+}
+
+
+static const struct hc_driver ehci_ppc_of_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "OF EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_ppc_of_setup,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+};
+
+
+/*
+ * 440EPx Errata USBH_3
+ * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+ */
+#define PPC440EPX_EHCI0_INSREG_BMT	(0x1 << 0)
+static int __devinit
+ppc44x_enable_bmt(struct device_node *dn)
+{
+	__iomem u32 *insreg_virt;
+
+	insreg_virt = of_iomap(dn, 1);
+	if (!insreg_virt)
+		return  -EINVAL;
+
+	out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT);
+
+	iounmap(insreg_virt);
+	return 0;
+}
+
+
+static int __devinit
+ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct usb_hcd *hcd;
+	struct ehci_hcd	*ehci;
+	struct resource res;
+	int irq;
+	int rv;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+	rv = of_address_to_resource(dn, 0, &res);
+	if (rv)
+		return rv;
+
+	hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res.start;
+	hcd->rsrc_len = res.end - res.start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		rv = -EBUSY;
+		goto err_rmr;
+	}
+
+	irq = irq_of_parse_and_map(dn, 0);
+	if (irq == NO_IRQ) {
+		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		rv = -EBUSY;
+		goto err_irq;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		rv = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+
+	if (of_get_property(dn, "big-endian", NULL)) {
+		ehci->big_endian_mmio = 1;
+		ehci->big_endian_desc = 1;
+	}
+	if (of_get_property(dn, "big-endian-regs", NULL))
+		ehci->big_endian_mmio = 1;
+	if (of_get_property(dn, "big-endian-desc", NULL))
+		ehci->big_endian_desc = 1;
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) {
+		rv = ppc44x_enable_bmt(dn);
+		ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n",
+				rv ? "NOT ": "");
+	}
+
+	rv = usb_add_hcd(hcd, irq, 0);
+	if (rv == 0)
+		return 0;
+
+	iounmap(hcd->regs);
+err_ioremap:
+	irq_dispose_mapping(irq);
+err_irq:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_rmr:
+	usb_put_hcd(hcd);
+
+	return rv;
+}
+
+
+static int ehci_hcd_ppc_of_remove(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+	dev_set_drvdata(&op->dev, NULL);
+
+	dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+	usb_remove_hcd(hcd);
+
+	iounmap(hcd->regs);
+	irq_dispose_mapping(hcd->irq);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+
+static int ehci_hcd_ppc_of_shutdown(struct of_device *op)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+
+	return 0;
+}
+
+
+static struct of_device_id ehci_hcd_ppc_of_match[] = {
+	{
+		.compatible = "usb-ehci",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
+
+
+static struct of_platform_driver ehci_hcd_ppc_of_driver = {
+	.name		= "ppc-of-ehci",
+	.match_table	= ehci_hcd_ppc_of_match,
+	.probe		= ehci_hcd_ppc_of_probe,
+	.remove		= ehci_hcd_ppc_of_remove,
+	.shutdown	= ehci_hcd_ppc_of_shutdown,
+	.driver		= {
+		.name	= "ppc-of-ehci",
+		.owner	= THIS_MODULE,
+	},
+};

+ 1 - 0
drivers/usb/host/ehci-ppc-soc.c

@@ -162,6 +162,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
 	.hub_control = ehci_hub_control,
 	.hub_control = ehci_hub_control,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_suspend = ehci_bus_suspend,
 	.bus_resume = ehci_bus_resume,
 	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
 };
 };
 
 
 static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
 static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)

+ 1 - 0
drivers/usb/host/ehci-ps3.c

@@ -72,6 +72,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 	.bus_suspend		= ehci_bus_suspend,
 	.bus_suspend		= ehci_bus_suspend,
 	.bus_resume		= ehci_bus_resume,
 	.bus_resume		= ehci_bus_resume,
 #endif
 #endif
+	.relinquish_port	= ehci_relinquish_port,
 };
 };
 
 
 static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
 static int ps3_ehci_probe(struct ps3_system_bus_device *dev)

+ 13 - 12
drivers/usb/host/ehci-q.c

@@ -198,7 +198,8 @@ static int qtd_copy_status (
 
 
 		/* if async CSPLIT failed, try cleaning out the TT buffer */
 		/* if async CSPLIT failed, try cleaning out the TT buffer */
 		if (status != -EPIPE
 		if (status != -EPIPE
-				&& urb->dev->tt && !usb_pipeint (urb->pipe)
+				&& urb->dev->tt
+				&& !usb_pipeint(urb->pipe)
 				&& ((token & QTD_STS_MMF) != 0
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
 					|| QTD_CERR(token) == 0)
 				&& (!ehci_is_TDI(ehci)
 				&& (!ehci_is_TDI(ehci)
@@ -211,6 +212,9 @@ static int qtd_copy_status (
 				urb->dev->ttport, urb->dev->devnum,
 				urb->dev->ttport, urb->dev->devnum,
 				usb_pipeendpoint (urb->pipe), token);
 				usb_pipeendpoint (urb->pipe), token);
 #endif /* DEBUG */
 #endif /* DEBUG */
+			/* REVISIT ARC-derived cores don't clear the root
+			 * hub TT buffer in this way...
+			 */
 			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
 			usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
 		}
 		}
 	}
 	}
@@ -638,6 +642,7 @@ qh_make (
 	u32			info1 = 0, info2 = 0;
 	u32			info1 = 0, info2 = 0;
 	int			is_input, type;
 	int			is_input, type;
 	int			maxp = 0;
 	int			maxp = 0;
+	struct usb_tt		*tt = urb->dev->tt;
 
 
 	if (!qh)
 	if (!qh)
 		return qh;
 		return qh;
@@ -661,8 +666,9 @@ qh_make (
 	 * For control/bulk requests, the HC or TT handles these.
 	 * For control/bulk requests, the HC or TT handles these.
 	 */
 	 */
 	if (type == PIPE_INTERRUPT) {
 	if (type == PIPE_INTERRUPT) {
-		qh->usecs = NS_TO_US (usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0,
-				hb_mult (maxp) * max_packet (maxp)));
+		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+				is_input, 0,
+				hb_mult(maxp) * max_packet(maxp)));
 		qh->start = NO_FRAME;
 		qh->start = NO_FRAME;
 
 
 		if (urb->dev->speed == USB_SPEED_HIGH) {
 		if (urb->dev->speed == USB_SPEED_HIGH) {
@@ -680,7 +686,6 @@ qh_make (
 				goto done;
 				goto done;
 			}
 			}
 		} else {
 		} else {
-			struct usb_tt	*tt = urb->dev->tt;
 			int		think_time;
 			int		think_time;
 
 
 			/* gap is f(FS/LS transfer times) */
 			/* gap is f(FS/LS transfer times) */
@@ -736,10 +741,8 @@ qh_make (
 		/* set the address of the TT; for TDI's integrated
 		/* set the address of the TT; for TDI's integrated
 		 * root hub tt, leave it zeroed.
 		 * root hub tt, leave it zeroed.
 		 */
 		 */
-		if (!ehci_is_TDI(ehci)
-				|| urb->dev->tt->hub !=
-					ehci_to_hcd(ehci)->self.root_hub)
-			info2 |= urb->dev->tt->hub->devnum << 16;
+		if (tt && tt->hub != ehci_to_hcd(ehci)->self.root_hub)
+			info2 |= tt->hub->devnum << 16;
 
 
 		/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
 		/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
 
 
@@ -973,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*qh = ehci->reclaim;
 	struct ehci_qh		*next;
 	struct ehci_qh		*next;
 
 
-	timer_action_done (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_done(ehci);
 
 
 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	// qh->hw_next = cpu_to_hc32(qh->qh_dma);
 	qh->qh_state = QH_STATE_IDLE;
 	qh->qh_state = QH_STATE_IDLE;
@@ -983,7 +986,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	/* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
 	next = qh->reclaim;
 	next = qh->reclaim;
 	ehci->reclaim = next;
 	ehci->reclaim = next;
-	ehci->reclaim_ready = 0;
 	qh->reclaim = NULL;
 	qh->reclaim = NULL;
 
 
 	qh_completions (ehci, qh);
 	qh_completions (ehci, qh);
@@ -1059,11 +1061,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 		return;
 		return;
 	}
 	}
 
 
-	ehci->reclaim_ready = 0;
 	cmd |= CMD_IAAD;
 	cmd |= CMD_IAAD;
 	ehci_writel(ehci, cmd, &ehci->regs->command);
 	ehci_writel(ehci, cmd, &ehci->regs->command);
 	(void)ehci_readl(ehci, &ehci->regs->command);
 	(void)ehci_readl(ehci, &ehci->regs->command);
-	timer_action (ehci, TIMER_IAA_WATCHDOG);
+	iaa_watchdog_start(ehci);
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/

+ 84 - 68
drivers/usb/host/ehci-sched.c

@@ -119,7 +119,8 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 			q = &q->fstn->fstn_next;
 			q = &q->fstn->fstn_next;
 			break;
 			break;
 		case Q_TYPE_ITD:
 		case Q_TYPE_ITD:
-			usecs += q->itd->usecs [uframe];
+			if (q->itd->hw_transaction[uframe])
+				usecs += q->itd->stream->usecs;
 			hw_p = &q->itd->hw_next;
 			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
 			q = &q->itd->itd_next;
 			break;
 			break;
@@ -211,7 +212,7 @@ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
  * low/fullspeed transfer can "carry over" from one uframe to the next,
  * low/fullspeed transfer can "carry over" from one uframe to the next,
  * since the TT just performs downstream transfers in sequence.
  * since the TT just performs downstream transfers in sequence.
  *
  *
- * For example two seperate 100 usec transfers can start in the same uframe,
+ * For example two separate 100 usec transfers can start in the same uframe,
  * and the second one would "carry over" 75 usecs into the next uframe.
  * and the second one would "carry over" 75 usecs into the next uframe.
  */
  */
 static void
 static void
@@ -1536,7 +1537,6 @@ itd_link_urb (
 		uframe = next_uframe & 0x07;
 		uframe = next_uframe & 0x07;
 		frame = next_uframe >> 3;
 		frame = next_uframe >> 3;
 
 
-		itd->usecs [uframe] = stream->usecs;
 		itd_patch(ehci, itd, iso_sched, packet, uframe);
 		itd_patch(ehci, itd, iso_sched, packet, uframe);
 
 
 		next_uframe += stream->interval;
 		next_uframe += stream->interval;
@@ -1565,6 +1565,16 @@ itd_link_urb (
 
 
 #define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 #define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 
 
+/* Process and recycle a completed ITD.  Return true iff its urb completed,
+ * and hence its completion callback probably added things to the hardware
+ * schedule.
+ *
+ * Note that we carefully avoid recycling this descriptor until after any
+ * completion callback runs, so that it won't be reused quickly.  That is,
+ * assuming (a) no more than two urbs per frame on this endpoint, and also
+ * (b) only this endpoint's completions submit URBs.  It seems some silicon
+ * corrupts things if you reuse completed descriptors very quickly...
+ */
 static unsigned
 static unsigned
 itd_complete (
 itd_complete (
 	struct ehci_hcd	*ehci,
 	struct ehci_hcd	*ehci,
@@ -1577,6 +1587,7 @@ itd_complete (
 	int					urb_index = -1;
 	int					urb_index = -1;
 	struct ehci_iso_stream			*stream = itd->stream;
 	struct ehci_iso_stream			*stream = itd->stream;
 	struct usb_device			*dev;
 	struct usb_device			*dev;
+	unsigned				retval = false;
 
 
 	/* for each uframe with a packet */
 	/* for each uframe with a packet */
 	for (uframe = 0; uframe < 8; uframe++) {
 	for (uframe = 0; uframe < 8; uframe++) {
@@ -1610,30 +1621,21 @@ itd_complete (
 		}
 		}
 	}
 	}
 
 
-	usb_put_urb (urb);
-	itd->urb = NULL;
-	itd->stream = NULL;
-	list_move (&itd->itd_list, &stream->free_list);
-	iso_stream_put (ehci, stream);
-
 	/* handle completion now? */
 	/* handle completion now? */
 	if (likely ((urb_index + 1) != urb->number_of_packets))
 	if (likely ((urb_index + 1) != urb->number_of_packets))
-		return 0;
+		goto done;
 
 
 	/* ASSERT: it's really the last itd for this urb
 	/* ASSERT: it's really the last itd for this urb
 	list_for_each_entry (itd, &stream->td_list, itd_list)
 	list_for_each_entry (itd, &stream->td_list, itd_list)
 		BUG_ON (itd->urb == urb);
 		BUG_ON (itd->urb == urb);
 	 */
 	 */
 
 
-	/* give urb back to the driver ... can be out-of-order */
+	/* give urb back to the driver; completion often (re)submits */
 	dev = urb->dev;
 	dev = urb->dev;
 	ehci_urb_done(ehci, urb, 0);
 	ehci_urb_done(ehci, urb, 0);
+	retval = true;
 	urb = NULL;
 	urb = NULL;
-
-	/* defer stopping schedule; completion can submit */
 	ehci->periodic_sched--;
 	ehci->periodic_sched--;
-	if (unlikely (!ehci->periodic_sched))
-		(void) disable_periodic (ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 
 	if (unlikely (list_empty (&stream->td_list))) {
 	if (unlikely (list_empty (&stream->td_list))) {
@@ -1645,8 +1647,15 @@ itd_complete (
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	}
 	iso_stream_put (ehci, stream);
 	iso_stream_put (ehci, stream);
+	/* OK to recycle this ITD now that its completion callback ran. */
+done:
+	usb_put_urb(urb);
+	itd->urb = NULL;
+	itd->stream = NULL;
+	list_move(&itd->itd_list, &stream->free_list);
+	iso_stream_put(ehci, stream);
 
 
-	return 1;
+	return retval;
 }
 }
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -1712,8 +1721,6 @@ done:
 	return status;
 	return status;
 }
 }
 
 
-#ifdef CONFIG_USB_EHCI_SPLIT_ISO
-
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 /*
 /*
@@ -1950,6 +1957,16 @@ sitd_link_urb (
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
 #define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
 				| SITD_STS_XACT | SITD_STS_MMF)
 				| SITD_STS_XACT | SITD_STS_MMF)
 
 
+/* Process and recycle a completed SITD.  Return true iff its urb completed,
+ * and hence its completion callback probably added things to the hardware
+ * schedule.
+ *
+ * Note that we carefully avoid recycling this descriptor until after any
+ * completion callback runs, so that it won't be reused quickly.  That is,
+ * assuming (a) no more than two urbs per frame on this endpoint, and also
+ * (b) only this endpoint's completions submit URBs.  It seems some silicon
+ * corrupts things if you reuse completed descriptors very quickly...
+ */
 static unsigned
 static unsigned
 sitd_complete (
 sitd_complete (
 	struct ehci_hcd		*ehci,
 	struct ehci_hcd		*ehci,
@@ -1961,6 +1978,7 @@ sitd_complete (
 	int					urb_index = -1;
 	int					urb_index = -1;
 	struct ehci_iso_stream			*stream = sitd->stream;
 	struct ehci_iso_stream			*stream = sitd->stream;
 	struct usb_device			*dev;
 	struct usb_device			*dev;
+	unsigned				retval = false;
 
 
 	urb_index = sitd->index;
 	urb_index = sitd->index;
 	desc = &urb->iso_frame_desc [urb_index];
 	desc = &urb->iso_frame_desc [urb_index];
@@ -1981,32 +1999,23 @@ sitd_complete (
 		desc->status = 0;
 		desc->status = 0;
 		desc->actual_length = desc->length - SITD_LENGTH (t);
 		desc->actual_length = desc->length - SITD_LENGTH (t);
 	}
 	}
-
-	usb_put_urb (urb);
-	sitd->urb = NULL;
-	sitd->stream = NULL;
-	list_move (&sitd->sitd_list, &stream->free_list);
 	stream->depth -= stream->interval << 3;
 	stream->depth -= stream->interval << 3;
-	iso_stream_put (ehci, stream);
 
 
 	/* handle completion now? */
 	/* handle completion now? */
 	if ((urb_index + 1) != urb->number_of_packets)
 	if ((urb_index + 1) != urb->number_of_packets)
-		return 0;
+		goto done;
 
 
 	/* ASSERT: it's really the last sitd for this urb
 	/* ASSERT: it's really the last sitd for this urb
 	list_for_each_entry (sitd, &stream->td_list, sitd_list)
 	list_for_each_entry (sitd, &stream->td_list, sitd_list)
 		BUG_ON (sitd->urb == urb);
 		BUG_ON (sitd->urb == urb);
 	 */
 	 */
 
 
-	/* give urb back to the driver */
+	/* give urb back to the driver; completion often (re)submits */
 	dev = urb->dev;
 	dev = urb->dev;
 	ehci_urb_done(ehci, urb, 0);
 	ehci_urb_done(ehci, urb, 0);
+	retval = true;
 	urb = NULL;
 	urb = NULL;
-
-	/* defer stopping schedule; completion can submit */
 	ehci->periodic_sched--;
 	ehci->periodic_sched--;
-	if (!ehci->periodic_sched)
-		(void) disable_periodic (ehci);
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 
 	if (list_empty (&stream->td_list)) {
 	if (list_empty (&stream->td_list)) {
@@ -2018,8 +2027,15 @@ sitd_complete (
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	}
 	iso_stream_put (ehci, stream);
 	iso_stream_put (ehci, stream);
+	/* OK to recycle this SITD now that its completion callback ran. */
+done:
+	usb_put_urb(urb);
+	sitd->urb = NULL;
+	sitd->stream = NULL;
+	list_move(&sitd->sitd_list, &stream->free_list);
+	iso_stream_put(ehci, stream);
 
 
-	return 1;
+	return retval;
 }
 }
 
 
 
 
@@ -2082,26 +2098,6 @@ done:
 	return status;
 	return status;
 }
 }
 
 
-#else
-
-static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags)
-{
-	ehci_dbg (ehci, "split iso support is disabled\n");
-	return -ENOSYS;
-}
-
-static inline unsigned
-sitd_complete (
-	struct ehci_hcd		*ehci,
-	struct ehci_sitd	*sitd
-) {
-	ehci_err (ehci, "sitd_complete %p?\n", sitd);
-	return 0;
-}
-
-#endif /* USB_EHCI_SPLIT_ISO */
-
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
 
 
 static void
 static void
@@ -2127,17 +2123,9 @@ scan_periodic (struct ehci_hcd *ehci)
 	for (;;) {
 	for (;;) {
 		union ehci_shadow	q, *q_p;
 		union ehci_shadow	q, *q_p;
 		__hc32			type, *hw_p;
 		__hc32			type, *hw_p;
-		unsigned		uframes;
+		unsigned		incomplete = false;
 
 
-		/* don't scan past the live uframe */
 		frame = now_uframe >> 3;
 		frame = now_uframe >> 3;
-		if (frame == (clock >> 3))
-			uframes = now_uframe & 0x07;
-		else {
-			/* safe to scan the whole frame at once */
-			now_uframe |= 0x07;
-			uframes = 8;
-		}
 
 
 restart:
 restart:
 		/* scan each element in frame's queue for completions */
 		/* scan each element in frame's queue for completions */
@@ -2175,12 +2163,15 @@ restart:
 				q = q.fstn->fstn_next;
 				q = q.fstn->fstn_next;
 				break;
 				break;
 			case Q_TYPE_ITD:
 			case Q_TYPE_ITD:
-				/* skip itds for later in the frame */
+				/* If this ITD is still active, leave it for
+				 * later processing ... check the next entry.
+				 */
 				rmb ();
 				rmb ();
-				for (uf = live ? uframes : 8; uf < 8; uf++) {
+				for (uf = 0; uf < 8 && live; uf++) {
 					if (0 == (q.itd->hw_transaction [uf]
 					if (0 == (q.itd->hw_transaction [uf]
 							& ITD_ACTIVE(ehci)))
 							& ITD_ACTIVE(ehci)))
 						continue;
 						continue;
+					incomplete = true;
 					q_p = &q.itd->itd_next;
 					q_p = &q.itd->itd_next;
 					hw_p = &q.itd->hw_next;
 					hw_p = &q.itd->hw_next;
 					type = Q_NEXT_TYPE(ehci,
 					type = Q_NEXT_TYPE(ehci,
@@ -2188,10 +2179,12 @@ restart:
 					q = *q_p;
 					q = *q_p;
 					break;
 					break;
 				}
 				}
-				if (uf != 8)
+				if (uf < 8 && live)
 					break;
 					break;
 
 
-				/* this one's ready ... HC won't cache the
+				/* Take finished ITDs out of the schedule
+				 * and process them:  recycle, maybe report
+				 * URB completion.  HC won't cache the
 				 * pointer for much longer, if at all.
 				 * pointer for much longer, if at all.
 				 */
 				 */
 				*q_p = q.itd->itd_next;
 				*q_p = q.itd->itd_next;
@@ -2202,8 +2195,12 @@ restart:
 				q = *q_p;
 				q = *q_p;
 				break;
 				break;
 			case Q_TYPE_SITD:
 			case Q_TYPE_SITD:
+				/* If this SITD is still active, leave it for
+				 * later processing ... check the next entry.
+				 */
 				if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
 				if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
 						&& live) {
 						&& live) {
+					incomplete = true;
 					q_p = &q.sitd->sitd_next;
 					q_p = &q.sitd->sitd_next;
 					hw_p = &q.sitd->hw_next;
 					hw_p = &q.sitd->hw_next;
 					type = Q_NEXT_TYPE(ehci,
 					type = Q_NEXT_TYPE(ehci,
@@ -2211,6 +2208,11 @@ restart:
 					q = *q_p;
 					q = *q_p;
 					break;
 					break;
 				}
 				}
+
+				/* Take finished SITDs out of the schedule
+				 * and process them:  recycle, maybe report
+				 * URB completion.
+				 */
 				*q_p = q.sitd->sitd_next;
 				*q_p = q.sitd->sitd_next;
 				*hw_p = q.sitd->hw_next;
 				*hw_p = q.sitd->hw_next;
 				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
 				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
@@ -2226,11 +2228,24 @@ restart:
 			}
 			}
 
 
 			/* assume completion callbacks modify the queue */
 			/* assume completion callbacks modify the queue */
-			if (unlikely (modified))
-				goto restart;
+			if (unlikely (modified)) {
+				if (likely(ehci->periodic_sched > 0))
+					goto restart;
+				/* maybe we can short-circuit this scan! */
+				disable_periodic(ehci);
+				now_uframe = clock;
+				break;
+			}
 		}
 		}
 
 
-		/* stop when we catch up to the HC */
+		/* If we can tell we caught up to the hardware, stop now.
+		 * We can't advance our scan without collecting the ISO
+		 * transfers that are still pending in this frame.
+		 */
+		if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
+			ehci->next_uframe = now_uframe;
+			break;
+		}
 
 
 		// FIXME:  this assumes we won't get lapped when
 		// FIXME:  this assumes we won't get lapped when
 		// latencies climb; that should be rare, but...
 		// latencies climb; that should be rare, but...
@@ -2243,7 +2258,8 @@ restart:
 		if (now_uframe == clock) {
 		if (now_uframe == clock) {
 			unsigned	now;
 			unsigned	now;
 
 
-			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+			if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
+					|| ehci->periodic_sched == 0)
 				break;
 				break;
 			ehci->next_uframe = now_uframe;
 			ehci->next_uframe = now_uframe;
 			now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
 			now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;

+ 30 - 10
drivers/usb/host/ehci.h

@@ -74,7 +74,6 @@ struct ehci_hcd {			/* one per controller */
 	/* async schedule support */
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
 	struct ehci_qh		*reclaim;
-	unsigned		reclaim_ready : 1;
 	unsigned		scanning : 1;
 	unsigned		scanning : 1;
 
 
 	/* periodic schedule support */
 	/* periodic schedule support */
@@ -105,6 +104,7 @@ struct ehci_hcd {			/* one per controller */
 	struct dma_pool		*itd_pool;	/* itd per iso urb */
 	struct dma_pool		*itd_pool;	/* itd per iso urb */
 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
 	struct dma_pool		*sitd_pool;	/* sitd per split iso urb */
 
 
+	struct timer_list	iaa_watchdog;
 	struct timer_list	watchdog;
 	struct timer_list	watchdog;
 	unsigned long		actions;
 	unsigned long		actions;
 	unsigned		stamp;
 	unsigned		stamp;
@@ -126,6 +126,14 @@ struct ehci_hcd {			/* one per controller */
 #	define COUNT(x) do { (x)++; } while (0)
 #	define COUNT(x) do { (x)++; } while (0)
 #else
 #else
 #	define COUNT(x) do {} while (0)
 #	define COUNT(x) do {} while (0)
+#endif
+
+	/* debug files */
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+	struct dentry		*debug_async;
+	struct dentry		*debug_periodic;
+	struct dentry		*debug_registers;
 #endif
 #endif
 };
 };
 
 
@@ -140,9 +148,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
 }
 }
 
 
 
 
+static inline void
+iaa_watchdog_start(struct ehci_hcd *ehci)
+{
+	WARN_ON(timer_pending(&ehci->iaa_watchdog));
+	mod_timer(&ehci->iaa_watchdog,
+			jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
+}
+
+static inline void iaa_watchdog_done(struct ehci_hcd *ehci)
+{
+	del_timer(&ehci->iaa_watchdog);
+}
+
 enum ehci_timer_action {
 enum ehci_timer_action {
 	TIMER_IO_WATCHDOG,
 	TIMER_IO_WATCHDOG,
-	TIMER_IAA_WATCHDOG,
 	TIMER_ASYNC_SHRINK,
 	TIMER_ASYNC_SHRINK,
 	TIMER_ASYNC_OFF,
 	TIMER_ASYNC_OFF,
 };
 };
@@ -160,9 +180,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 		unsigned long t;
 		unsigned long t;
 
 
 		switch (action) {
 		switch (action) {
-		case TIMER_IAA_WATCHDOG:
-			t = EHCI_IAA_JIFFIES;
-			break;
 		case TIMER_IO_WATCHDOG:
 		case TIMER_IO_WATCHDOG:
 			t = EHCI_IO_JIFFIES;
 			t = EHCI_IO_JIFFIES;
 			break;
 			break;
@@ -179,8 +196,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 		// async queue SHRINK often precedes IAA.  while it's ready
 		// async queue SHRINK often precedes IAA.  while it's ready
 		// to go OFF neither can matter, and afterwards the IO
 		// to go OFF neither can matter, and afterwards the IO
 		// watchdog stops unless there's still periodic traffic.
 		// watchdog stops unless there's still periodic traffic.
-		if (action != TIMER_IAA_WATCHDOG
-				&& t > ehci->watchdog.expires
+		if (time_before_eq(t, ehci->watchdog.expires)
 				&& timer_pending (&ehci->watchdog))
 				&& timer_pending (&ehci->watchdog))
 			return;
 			return;
 		mod_timer (&ehci->watchdog, t);
 		mod_timer (&ehci->watchdog, t);
@@ -534,8 +550,8 @@ struct ehci_iso_stream {
 	 * trusting urb->interval == f(epdesc->bInterval) and
 	 * trusting urb->interval == f(epdesc->bInterval) and
 	 * including the extra info for hw_bufp[0..2]
 	 * including the extra info for hw_bufp[0..2]
 	 */
 	 */
-	u8			interval;
 	u8			usecs, c_usecs;
 	u8			usecs, c_usecs;
+	u16			interval;
 	u16			tt_usecs;
 	u16			tt_usecs;
 	u16			maxp;
 	u16			maxp;
 	u16			raw_mask;
 	u16			raw_mask;
@@ -586,7 +602,6 @@ struct ehci_itd {
 	unsigned		frame;		/* where scheduled */
 	unsigned		frame;		/* where scheduled */
 	unsigned		pg;
 	unsigned		pg;
 	unsigned		index[8];	/* in urb->iso_frame_desc */
 	unsigned		index[8];	/* in urb->iso_frame_desc */
-	u8			usecs[8];
 } __attribute__ ((aligned (32)));
 } __attribute__ ((aligned (32)));
 
 
 /*-------------------------------------------------------------------------*/
 /*-------------------------------------------------------------------------*/
@@ -725,11 +740,16 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
  * definition below can die once the 4xx support is
  * definition below can die once the 4xx support is
  * finally ported over.
  * finally ported over.
  */
  */
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
 #define readl_be(addr)		in_be32((__force unsigned *)addr)
 #define readl_be(addr)		in_be32((__force unsigned *)addr)
 #define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
 #define writel_be(val, addr)	out_be32((__force unsigned *)addr, val)
 #endif
 #endif
 
 
+#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX)
+#define readl_be(addr)		__raw_readl((__force unsigned *)addr)
+#define writel_be(val, addr)	__raw_writel(val, (__force unsigned *)addr)
+#endif
+
 static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
 static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
 		__u32 __iomem * regs)
 		__u32 __iomem * regs)
 {
 {

+ 0 - 1
drivers/usb/host/isp116x-hcd.c

@@ -918,7 +918,6 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf)
 			      | RH_PS_OCIC | RH_PS_PRSC)) {
 			      | RH_PS_OCIC | RH_PS_PRSC)) {
 			changed = 1;
 			changed = 1;
 			buf[0] |= 1 << (i + 1);
 			buf[0] |= 1 << (i + 1);
-			continue;
 		}
 		}
 	}
 	}
 	spin_unlock_irqrestore(&isp116x->lock, flags);
 	spin_unlock_irqrestore(&isp116x->lock, flags);

+ 31 - 0
drivers/usb/host/ohci-at91.c

@@ -17,6 +17,8 @@
 
 
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/hardware.h>
+#include <asm/gpio.h>
+
 #include <asm/arch/board.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/cpu.h>
 
 
@@ -271,12 +273,41 @@ static const struct hc_driver ohci_at91_hc_driver = {
 
 
 static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
 {
+	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+	int			i;
+
+	if (pdata) {
+		/* REVISIT make the driver support per-port power switching,
+		 * and also overcurrent detection.  Here we assume the ports
+		 * are always powered while this driver is active, and use
+		 * active-low power switches.
+		 */
+		for (i = 0; i < pdata->ports; i++) {
+			if (pdata->vbus_pin[i] <= 0)
+				continue;
+			gpio_request(pdata->vbus_pin[i], "ohci_vbus");
+			gpio_direction_output(pdata->vbus_pin[i], 0);
+		}
+	}
+
 	device_init_wakeup(&pdev->dev, 1);
 	device_init_wakeup(&pdev->dev, 1);
 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
 }
 
 
 static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
 {
+	struct at91_usbh_data	*pdata = pdev->dev.platform_data;
+	int			i;
+
+	if (pdata) {
+		for (i = 0; i < pdata->ports; i++) {
+			if (pdata->vbus_pin[i] <= 0)
+				continue;
+			gpio_direction_output(pdata->vbus_pin[i], 1);
+			gpio_free(pdata->vbus_pin[i]);
+		}
+	}
+
 	device_init_wakeup(&pdev->dev, 0);
 	device_init_wakeup(&pdev->dev, 0);
 	return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
 	return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
 }
 }

+ 184 - 29
drivers/usb/host/ohci-dbg.c

@@ -401,6 +401,42 @@ static inline void remove_debug_files (struct ohci_hcd *bus) { }
 
 
 #else
 #else
 
 
+static int debug_async_open(struct inode *, struct file *);
+static int debug_periodic_open(struct inode *, struct file *);
+static int debug_registers_open(struct inode *, struct file *);
+static int debug_async_open(struct inode *, struct file *);
+static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
+static int debug_close(struct inode *, struct file *);
+
+static const struct file_operations debug_async_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_async_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_periodic_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_periodic_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+static const struct file_operations debug_registers_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_registers_open,
+	.read		= debug_output,
+	.release	= debug_close,
+};
+
+static struct dentry *ohci_debug_root;
+
+struct debug_buffer {
+	ssize_t (*fill_func)(struct debug_buffer *);	/* fill method */
+	struct device *dev;
+	struct mutex mutex;	/* protect filling of buffer */
+	size_t count;		/* number of characters filled into buffer */
+	char *page;
+};
+
 static ssize_t
 static ssize_t
 show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 {
 {
@@ -467,8 +503,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 	return count - size;
 	return count - size;
 }
 }
 
 
-static ssize_t
-show_async (struct class_device *class_dev, char *buf)
+static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
 {
 	struct usb_bus		*bus;
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
@@ -476,25 +511,23 @@ show_async (struct class_device *class_dev, char *buf)
 	size_t			temp;
 	size_t			temp;
 	unsigned long		flags;
 	unsigned long		flags;
 
 
-	bus = class_get_devdata(class_dev);
+	bus = dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	ohci = hcd_to_ohci(hcd);
 
 
 	/* display control and bulk lists together, for simplicity */
 	/* display control and bulk lists together, for simplicity */
 	spin_lock_irqsave (&ohci->lock, flags);
 	spin_lock_irqsave (&ohci->lock, flags);
-	temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail);
-	temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail);
+	temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail);
+	temp += show_list(ohci, buf->page + temp, buf->count - temp,
+			  ohci->ed_bulktail);
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	spin_unlock_irqrestore (&ohci->lock, flags);
 
 
 	return temp;
 	return temp;
 }
 }
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
-
 
 
 #define DBG_SCHED_LIMIT 64
 #define DBG_SCHED_LIMIT 64
 
 
-static ssize_t
-show_periodic (struct class_device *class_dev, char *buf)
+static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
 {
 	struct usb_bus		*bus;
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
@@ -509,10 +542,10 @@ show_periodic (struct class_device *class_dev, char *buf)
 		return 0;
 		return 0;
 	seen_count = 0;
 	seen_count = 0;
 
 
-	bus = class_get_devdata(class_dev);
+	bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	ohci = hcd_to_ohci(hcd);
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 	size = PAGE_SIZE;
 
 
 	temp = scnprintf (next, size, "size = %d\n", NUM_INTS);
 	temp = scnprintf (next, size, "size = %d\n", NUM_INTS);
@@ -589,13 +622,9 @@ show_periodic (struct class_device *class_dev, char *buf)
 
 
 	return PAGE_SIZE - size;
 	return PAGE_SIZE - size;
 }
 }
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
-
 #undef DBG_SCHED_LIMIT
 #undef DBG_SCHED_LIMIT
 
 
-static ssize_t
-show_registers (struct class_device *class_dev, char *buf)
+static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
 {
 	struct usb_bus		*bus;
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct usb_hcd		*hcd;
@@ -606,11 +635,11 @@ show_registers (struct class_device *class_dev, char *buf)
 	char			*next;
 	char			*next;
 	u32			rdata;
 	u32			rdata;
 
 
-	bus = class_get_devdata(class_dev);
+	bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
 	hcd = bus_to_hcd(bus);
 	hcd = bus_to_hcd(bus);
 	ohci = hcd_to_ohci(hcd);
 	ohci = hcd_to_ohci(hcd);
 	regs = ohci->regs;
 	regs = ohci->regs;
-	next = buf;
+	next = buf->page;
 	size = PAGE_SIZE;
 	size = PAGE_SIZE;
 
 
 	spin_lock_irqsave (&ohci->lock, flags);
 	spin_lock_irqsave (&ohci->lock, flags);
@@ -677,29 +706,155 @@ show_registers (struct class_device *class_dev, char *buf)
 
 
 done:
 done:
 	spin_unlock_irqrestore (&ohci->lock, flags);
 	spin_unlock_irqrestore (&ohci->lock, flags);
+
 	return PAGE_SIZE - size;
 	return PAGE_SIZE - size;
 }
 }
-static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 
+static struct debug_buffer *alloc_buffer(struct device *dev,
+				ssize_t (*fill_func)(struct debug_buffer *))
+{
+	struct debug_buffer *buf;
+
+	buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
 
 
+	if (buf) {
+		buf->dev = dev;
+		buf->fill_func = fill_func;
+		mutex_init(&buf->mutex);
+	}
+
+	return buf;
+}
+
+static int fill_buffer(struct debug_buffer *buf)
+{
+	int ret = 0;
+
+	if (!buf->page)
+		buf->page = (char *)get_zeroed_page(GFP_KERNEL);
+
+	if (!buf->page) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = buf->fill_func(buf);
+
+	if (ret >= 0) {
+		buf->count = ret;
+		ret = 0;
+	}
+
+out:
+	return ret;
+}
+
+static ssize_t debug_output(struct file *file, char __user *user_buf,
+			size_t len, loff_t *offset)
+{
+	struct debug_buffer *buf = file->private_data;
+	int ret = 0;
+
+	mutex_lock(&buf->mutex);
+	if (buf->count == 0) {
+		ret = fill_buffer(buf);
+		if (ret != 0) {
+			mutex_unlock(&buf->mutex);
+			goto out;
+		}
+	}
+	mutex_unlock(&buf->mutex);
+
+	ret = simple_read_from_buffer(user_buf, len, offset,
+				      buf->page, buf->count);
+
+out:
+	return ret;
+
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	struct debug_buffer *buf = file->private_data;
+
+	if (buf) {
+		if (buf->page)
+			free_page((unsigned long)buf->page);
+		kfree(buf);
+	}
+
+	return 0;
+}
+static int debug_async_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_periodic_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_periodic_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
+static int debug_registers_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+					  fill_registers_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
 static inline void create_debug_files (struct ohci_hcd *ohci)
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
 {
-	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
-	int retval;
+	struct usb_bus *bus = &ohci_to_hcd(ohci)->self;
+	struct device *dev = bus->dev;
+
+	ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root);
+	if (!ohci->debug_dir)
+		goto dir_error;
+
+	ohci->debug_async = debugfs_create_file("async", S_IRUGO,
+						ohci->debug_dir, dev,
+						&debug_async_fops);
+	if (!ohci->debug_async)
+		goto async_error;
+
+	ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO,
+						   ohci->debug_dir, dev,
+						   &debug_periodic_fops);
+	if (!ohci->debug_periodic)
+		goto periodic_error;
+
+	ohci->debug_registers = debugfs_create_file("registers", S_IRUGO,
+						    ohci->debug_dir, dev,
+						    &debug_registers_fops);
+	if (!ohci->debug_registers)
+		goto registers_error;
 
 
-	retval = class_device_create_file(cldev, &class_device_attr_async);
-	retval = class_device_create_file(cldev, &class_device_attr_periodic);
-	retval = class_device_create_file(cldev, &class_device_attr_registers);
 	ohci_dbg (ohci, "created debug files\n");
 	ohci_dbg (ohci, "created debug files\n");
+	return;
+
+registers_error:
+	debugfs_remove(ohci->debug_periodic);
+periodic_error:
+	debugfs_remove(ohci->debug_async);
+async_error:
+	debugfs_remove(ohci->debug_dir);
+dir_error:
+	ohci->debug_periodic = NULL;
+	ohci->debug_async = NULL;
+	ohci->debug_dir = NULL;
 }
 }
 
 
 static inline void remove_debug_files (struct ohci_hcd *ohci)
 static inline void remove_debug_files (struct ohci_hcd *ohci)
 {
 {
-	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
-
-	class_device_remove_file(cldev, &class_device_attr_async);
-	class_device_remove_file(cldev, &class_device_attr_periodic);
-	class_device_remove_file(cldev, &class_device_attr_registers);
+	debugfs_remove(ohci->debug_registers);
+	debugfs_remove(ohci->debug_periodic);
+	debugfs_remove(ohci->debug_async);
+	debugfs_remove(ohci->debug_dir);
 }
 }
 
 
 #endif
 #endif

+ 30 - 4
drivers/usb/host/ohci-hcd.c

@@ -36,6 +36,7 @@
 #include <linux/dmapool.h>
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
 #include <linux/reboot.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
+#include <linux/debugfs.h>
 
 
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
@@ -809,13 +810,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
 	}
 	}
 
 
 	if (ints & OHCI_INTR_WDH) {
 	if (ints & OHCI_INTR_WDH) {
-		if (HC_IS_RUNNING(hcd->state))
-			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
 		spin_lock (&ohci->lock);
 		spin_lock (&ohci->lock);
 		dl_done_list (ohci);
 		dl_done_list (ohci);
 		spin_unlock (&ohci->lock);
 		spin_unlock (&ohci->lock);
-		if (HC_IS_RUNNING(hcd->state))
-			ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
 	}
 	}
 
 
 	if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
 	if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
@@ -1032,6 +1029,13 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
 #define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
 #endif
 #endif
 
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7763)
+#include "ohci-sh.c"
+#define PLATFORM_DRIVER		ohci_hcd_sh_driver
+#endif
+
 
 
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
 #include "ohci-ppc-of.c"
@@ -1048,6 +1052,11 @@ MODULE_LICENSE ("GPL");
 #define SSB_OHCI_DRIVER		ssb_ohci_driver
 #define SSB_OHCI_DRIVER		ssb_ohci_driver
 #endif
 #endif
 
 
+#ifdef CONFIG_MFD_SM501
+#include "ohci-sm501.c"
+#define PLATFORM_DRIVER		ohci_hcd_sm501_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OF_PLATFORM_DRIVER) &&	\
 	!defined(OF_PLATFORM_DRIVER) &&	\
@@ -1068,6 +1077,14 @@ static int __init ohci_hcd_mod_init(void)
 	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 		sizeof (struct ed), sizeof (struct td));
 		sizeof (struct ed), sizeof (struct td));
 
 
+#ifdef DEBUG
+	ohci_debug_root = debugfs_create_dir("ohci", NULL);
+	if (!ohci_debug_root) {
+		retval = -ENOENT;
+		goto error_debug;
+	}
+#endif
+
 #ifdef PS3_SYSTEM_BUS_DRIVER
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
 	retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
 	if (retval < 0)
 	if (retval < 0)
@@ -1130,6 +1147,12 @@ static int __init ohci_hcd_mod_init(void)
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
  error_ps3:
  error_ps3:
 #endif
 #endif
+#ifdef DEBUG
+	debugfs_remove(ohci_debug_root);
+	ohci_debug_root = NULL;
+ error_debug:
+#endif
+
 	return retval;
 	return retval;
 }
 }
 module_init(ohci_hcd_mod_init);
 module_init(ohci_hcd_mod_init);
@@ -1154,6 +1177,9 @@ static void __exit ohci_hcd_mod_exit(void)
 #ifdef PS3_SYSTEM_BUS_DRIVER
 #ifdef PS3_SYSTEM_BUS_DRIVER
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
 #endif
+#ifdef DEBUG
+	debugfs_remove(ohci_debug_root);
+#endif
 }
 }
 module_exit(ohci_hcd_mod_exit);
 module_exit(ohci_hcd_mod_exit);
 
 

+ 143 - 0
drivers/usb/host/ohci-sh.c

@@ -0,0 +1,143 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/platform_device.h>
+
+static int ohci_sh_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	ohci_hcd_init(ohci);
+	ohci_init(ohci);
+	ohci_run(ohci);
+	hcd->state = HC_STATE_RUNNING;
+	return 0;
+}
+
+static const struct hc_driver ohci_sh_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"SuperH OHCI",
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_sh_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int ohci_hcd_sh_probe(struct platform_device *pdev)
+{
+	struct resource *res = NULL;
+	struct usb_hcd *hcd = NULL;
+	int irq = -1;
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err("platform_get_resource error.");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		err("platform_get_irq error.");
+		return -ENODEV;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
+	if (!hcd) {
+		err("Failed to create hcd");
+		return -ENOMEM;
+	}
+
+	hcd->regs = (void __iomem *)res->start;
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_len(res);
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (ret != 0) {
+		err("Failed to add hcd");
+		usb_put_hcd(hcd);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int ohci_hcd_sh_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver ohci_hcd_sh_driver = {
+	.probe		= ohci_hcd_sh_probe,
+	.remove		= ohci_hcd_sh_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.name	= "sh_ohci",
+		.owner	= THIS_MODULE,
+	},
+};
+

+ 264 - 0
drivers/usb/host/ohci-sm501.c

@@ -0,0 +1,264 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2005 David Brownell
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2008 Magnus Damm
+ *
+ * SM501 Bus Glue - based on ohci-omap.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
+static int ohci_sm501_init(struct usb_hcd *hcd)
+{
+	return ohci_init(hcd_to_ohci(hcd));
+}
+
+static int ohci_sm501_start(struct usb_hcd *hcd)
+{
+	struct device *dev = hcd->self.controller;
+	int ret;
+
+	ret = ohci_run(hcd_to_ohci(hcd));
+	if (ret < 0) {
+		dev_err(dev, "can't start %s", hcd->self.bus_name);
+		ohci_stop(hcd);
+	}
+
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_sm501_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"SM501 OHCI",
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		ohci_sm501_init,
+	.start =		ohci_sm501_start,
+	.stop =			ohci_stop,
+	.shutdown =		ohci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+	.hub_irq_enable =	ohci_rhsc_enable,
+#ifdef	CONFIG_PM
+	.bus_suspend =		ohci_bus_suspend,
+	.bus_resume =		ohci_bus_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
+{
+	const struct hc_driver *driver = &ohci_sm501_hc_driver;
+	struct device *dev = &pdev->dev;
+	struct resource	*res, *mem;
+	int retval, irq;
+	struct usb_hcd *hcd = 0;
+
+	irq = retval = platform_get_irq(pdev, 0);
+	if (retval < 0)
+		goto err0;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (mem == NULL) {
+		dev_err(dev, "no resource definition for memory\n");
+		retval = -ENOENT;
+		goto err0;
+	}
+
+	if (!request_mem_region(mem->start, mem->end - mem->start + 1,
+				pdev->name)) {
+		dev_err(dev, "request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err0;
+	}
+
+	/* The sm501 chip is equipped with local memory that may be used
+	 * by on-chip devices such as the video controller and the usb host.
+	 * This driver uses dma_declare_coherent_memory() to make sure
+	 * usb allocations with dma_alloc_coherent() allocate from
+	 * this local memory. The dma_handle returned by dma_alloc_coherent()
+	 * will be an offset starting from 0 for the first local memory byte.
+	 *
+	 * So as long as data is allocated using dma_alloc_coherent() all is
+	 * fine. This is however not always the case - buffers may be allocated
+	 * using kmalloc() - so the usb core needs to be told that it must copy
+	 * data into our local memory if the buffers happen to be placed in
+	 * regular memory. The HCD_LOCAL_MEM flag does just that.
+	 */
+
+	if (!dma_declare_coherent_memory(dev, mem->start,
+					 mem->start - mem->parent->start,
+					 (mem->end - mem->start) + 1,
+					 DMA_MEMORY_MAP |
+					 DMA_MEMORY_EXCLUSIVE)) {
+		dev_err(dev, "cannot declare coherent memory\n");
+		retval = -ENXIO;
+		goto err1;
+	}
+
+	/* allocate, reserve and remap resources for registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for registers\n");
+		retval = -ENOENT;
+		goto err2;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,	pdev->name)) {
+		dev_err(dev, "request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err3;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (hcd->regs == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		retval = -ENXIO;
+		goto err4;
+	}
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (retval)
+		goto err4;
+
+	/* enable power and unmask interrupts */
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+	sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
+
+	return 0;
+err4:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err3:
+	usb_put_hcd(hcd);
+err2:
+	dma_release_declared_memory(dev);
+err1:
+	release_mem_region(mem->start, mem->end - mem->start + 1);
+err0:
+	return retval;
+}
+
+static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct resource	*mem;
+
+	usb_remove_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	dma_release_declared_memory(&pdev->dev);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	release_mem_region(mem->start, mem->end - mem->start + 1);
+
+	/* mask interrupts and disable power */
+
+	sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6);
+	sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct device *dev = &pdev->dev;
+	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
+	ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+	dev->power.power_state = PMSG_SUSPEND;
+	return 0;
+}
+
+static int ohci_sm501_resume(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
+	dev->power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(platform_get_drvdata(pdev));
+	return 0;
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Driver definition to register with the SM501 bus
+ */
+static struct platform_driver ohci_hcd_sm501_driver = {
+	.probe		= ohci_hcd_sm501_drv_probe,
+	.remove		= ohci_hcd_sm501_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+#ifdef	CONFIG_PM
+	.suspend	= ohci_sm501_suspend,
+	.resume		= ohci_sm501_resume,
+#endif
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "sm501-usb",
+	},
+};

+ 7 - 0
drivers/usb/host/ohci.h

@@ -408,6 +408,13 @@ struct ohci_hcd {
 	unsigned		eds_scheduled;
 	unsigned		eds_scheduled;
 	struct ed		*ed_to_check;
 	struct ed		*ed_to_check;
 	unsigned		zf_delay;
 	unsigned		zf_delay;
+
+#ifdef DEBUG
+	struct dentry		*debug_dir;
+	struct dentry		*debug_async;
+	struct dentry		*debug_periodic;
+	struct dentry		*debug_registers;
+#endif
 };
 };
 
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI

+ 1 - 1
drivers/usb/host/r8a66597.h

@@ -405,7 +405,7 @@
 
 
 struct r8a66597_pipe_info {
 struct r8a66597_pipe_info {
 	u16 pipenum;
 	u16 pipenum;
-	u16 address;	/* R8A66597 HCD usb addres */
+	u16 address;	/* R8A66597 HCD usb address */
 	u16 epnum;
 	u16 epnum;
 	u16 maxpacket;
 	u16 maxpacket;
 	u16 type;
 	u16 type;

+ 0 - 2
drivers/usb/image/mdc800.c

@@ -478,8 +478,6 @@ static int mdc800_usb_probe (struct usb_interface *intf,
 				{
 				{
 					irq_interval=intf_desc->endpoint [j].desc.bInterval;
 					irq_interval=intf_desc->endpoint [j].desc.bInterval;
 				}
 				}
-
-				continue;
 			}
 			}
 		}
 		}
 		if (mdc800->endpoint[i] == -1)
 		if (mdc800->endpoint[i] == -1)

+ 5 - 2
drivers/usb/misc/cypress_cy7c63.c

@@ -1,7 +1,7 @@
 /*
 /*
 * cypress_cy7c63.c
 * cypress_cy7c63.c
 *
 *
-* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de)
+* Copyright (c) 2006-2007 Oliver Bock (bock@tfh-berlin.de)
 *
 *
 *	This driver is based on the Cypress USB Driver by Marcus Maul
 *	This driver is based on the Cypress USB Driver by Marcus Maul
 *	(cyport) and the 2.0 version of Greg Kroah-Hartman's
 *	(cyport) and the 2.0 version of Greg Kroah-Hartman's
@@ -21,6 +21,9 @@
 *	Supported functions:	Read/Write Ports
 *	Supported functions:	Read/Write Ports
 *
 *
 *
 *
+*	For up-to-date information please visit:
+*	http://www.obock.de/kernel/cypress
+*
 *	This program is free software; you can redistribute it and/or
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation, version 2.
 *	published by the Free Software Foundation, version 2.
@@ -31,7 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/usb.h>
 
 
-#define DRIVER_AUTHOR		"Oliver Bock (o.bock@fh-wolfenbuettel.de)"
+#define DRIVER_AUTHOR		"Oliver Bock (bock@tfh-berlin.de)"
 #define DRIVER_DESC		"Cypress CY7C63xxx USB driver"
 #define DRIVER_DESC		"Cypress CY7C63xxx USB driver"
 
 
 #define CYPRESS_VENDOR_ID	0xa2c
 #define CYPRESS_VENDOR_ID	0xa2c

+ 1 - 1
drivers/usb/misc/iowarrior.c

@@ -715,7 +715,7 @@ static unsigned iowarrior_poll(struct file *file, poll_table * wait)
  * would use "struct net_driver" instead, and a serial
  * would use "struct net_driver" instead, and a serial
  * device would use "struct tty_driver".
  * device would use "struct tty_driver".
  */
  */
-static struct file_operations iowarrior_fops = {
+static const struct file_operations iowarrior_fops = {
 	.owner = THIS_MODULE,
 	.owner = THIS_MODULE,
 	.write = iowarrior_write,
 	.write = iowarrior_write,
 	.read = iowarrior_read,
 	.read = iowarrior_read,

+ 16 - 14
drivers/usb/misc/legousbtower.c

@@ -205,7 +205,7 @@ static DEFINE_MUTEX(open_disc_mutex);
 
 
 /* Structure to hold all of our device specific stuff */
 /* Structure to hold all of our device specific stuff */
 struct lego_usb_tower {
 struct lego_usb_tower {
-	struct semaphore	sem;		/* locks this structure */
+	struct mutex		lock;		/* locks this structure */
 	struct usb_device*	udev;		/* save off the usb device pointer */
 	struct usb_device*	udev;		/* save off the usb device pointer */
 	unsigned char		minor;		/* the starting minor number for this device */
 	unsigned char		minor;		/* the starting minor number for this device */
 
 
@@ -361,7 +361,7 @@ static int tower_open (struct inode *inode, struct file *file)
 	}
 	}
 
 
 	/* lock this device */
 	/* lock this device */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		mutex_unlock(&open_disc_mutex);
 		mutex_unlock(&open_disc_mutex);
 	        retval = -ERESTARTSYS;
 	        retval = -ERESTARTSYS;
 		goto exit;
 		goto exit;
@@ -421,7 +421,7 @@ static int tower_open (struct inode *inode, struct file *file)
 	file->private_data = dev;
 	file->private_data = dev;
 
 
 unlock_exit:
 unlock_exit:
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 
 exit:
 exit:
 	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
 	dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
@@ -448,7 +448,7 @@ static int tower_release (struct inode *inode, struct file *file)
 	}
 	}
 
 
 	mutex_lock(&open_disc_mutex);
 	mutex_lock(&open_disc_mutex);
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 	        retval = -ERESTARTSYS;
 	        retval = -ERESTARTSYS;
 		goto exit;
 		goto exit;
 	}
 	}
@@ -460,7 +460,9 @@ static int tower_release (struct inode *inode, struct file *file)
 	}
 	}
 	if (dev->udev == NULL) {
 	if (dev->udev == NULL) {
 		/* the device was unplugged before the file was released */
 		/* the device was unplugged before the file was released */
-		up (&dev->sem);	/* unlock here as tower_delete frees dev */
+
+		/* unlock here as tower_delete frees dev */
+		mutex_unlock(&dev->lock);
 		tower_delete (dev);
 		tower_delete (dev);
 		goto exit;
 		goto exit;
 	}
 	}
@@ -473,7 +475,7 @@ static int tower_release (struct inode *inode, struct file *file)
 	dev->open_count = 0;
 	dev->open_count = 0;
 
 
 unlock_exit:
 unlock_exit:
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 
 exit:
 exit:
 	mutex_unlock(&open_disc_mutex);
 	mutex_unlock(&open_disc_mutex);
@@ -586,7 +588,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
 	dev = (struct lego_usb_tower *)file->private_data;
 	dev = (struct lego_usb_tower *)file->private_data;
 
 
 	/* lock this object */
 	/* lock this object */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		retval = -ERESTARTSYS;
 		retval = -ERESTARTSYS;
 		goto exit;
 		goto exit;
 	}
 	}
@@ -653,7 +655,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
 
 
 unlock_exit:
 unlock_exit:
 	/* unlock the device */
 	/* unlock the device */
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 
 exit:
 exit:
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
@@ -675,7 +677,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 	dev = (struct lego_usb_tower *)file->private_data;
 	dev = (struct lego_usb_tower *)file->private_data;
 
 
 	/* lock this object */
 	/* lock this object */
-	if (down_interruptible (&dev->sem)) {
+	if (mutex_lock_interruptible(&dev->lock)) {
 		retval = -ERESTARTSYS;
 		retval = -ERESTARTSYS;
 		goto exit;
 		goto exit;
 	}
 	}
@@ -737,7 +739,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 
 
 unlock_exit:
 unlock_exit:
 	/* unlock the device */
 	/* unlock the device */
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 
 
 exit:
 exit:
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
 	dbg(2, "%s: leave, return value %d", __FUNCTION__, retval);
@@ -862,7 +864,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 		goto exit;
 		goto exit;
 	}
 	}
 
 
-	init_MUTEX (&dev->sem);
+	mutex_init(&dev->lock);
 
 
 	dev->udev = udev;
 	dev->udev = udev;
 	dev->open_count = 0;
 	dev->open_count = 0;
@@ -1007,16 +1009,16 @@ static void tower_disconnect (struct usb_interface *interface)
 	/* give back our minor */
 	/* give back our minor */
 	usb_deregister_dev (interface, &tower_class);
 	usb_deregister_dev (interface, &tower_class);
 
 
-	down (&dev->sem);
+	mutex_lock(&dev->lock);
 	mutex_unlock(&open_disc_mutex);
 	mutex_unlock(&open_disc_mutex);
 
 
 	/* if the device is not opened, then we clean up right now */
 	/* if the device is not opened, then we clean up right now */
 	if (!dev->open_count) {
 	if (!dev->open_count) {
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 		tower_delete (dev);
 		tower_delete (dev);
 	} else {
 	} else {
 		dev->udev = NULL;
 		dev->udev = NULL;
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 	}
 	}
 
 
 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
 	info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));

+ 1 - 28
drivers/usb/misc/sisusbvga/sisusb.c

@@ -323,7 +323,7 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data,
 			usb_kill_urb(urb);
 			usb_kill_urb(urb);
 			retval = -ETIMEDOUT;
 			retval = -ETIMEDOUT;
 		} else {
 		} else {
-			/* URB completed within timout */
+			/* URB completed within timeout */
 			retval = urb->status;
 			retval = urb->status;
 			readbytes = urb->actual_length;
 			readbytes = urb->actual_length;
 		}
 		}
@@ -3195,20 +3195,6 @@ static int sisusb_probe(struct usb_interface *intf,
 
 
 	sisusb->present = 1;
 	sisusb->present = 1;
 
 
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	{
-	int ret;
-	/* Our ioctls are all "32/64bit compatible" */
-	ret =  register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
-	ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG,      NULL);
-	ret |= register_ioctl32_conversion(SISUSB_COMMAND,         NULL);
-	if (ret)
-		dev_err(&sisusb->sisusb_dev->dev, "Error registering ioctl32 translations\n");
-	else
-		sisusb->ioctl32registered = 1;
-	}
-#endif
-
 	if (dev->speed == USB_SPEED_HIGH) {
 	if (dev->speed == USB_SPEED_HIGH) {
 		int initscreen = 1;
 		int initscreen = 1;
 #ifdef INCL_SISUSB_CON
 #ifdef INCL_SISUSB_CON
@@ -3271,19 +3257,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
 
 
 	usb_set_intfdata(intf, NULL);
 	usb_set_intfdata(intf, NULL);
 
 
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	if (sisusb->ioctl32registered) {
-		int ret;
-		sisusb->ioctl32registered = 0;
-		ret =  unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
-		ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
-		ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
-		if (ret) {
-			dev_err(&sisusb->sisusb_dev->dev, "Error unregistering ioctl32 translations\n");
-		}
-	}
-#endif
-
 	sisusb->present = 0;
 	sisusb->present = 0;
 	sisusb->ready = 0;
 	sisusb->ready = 0;
 
 

+ 0 - 3
drivers/usb/misc/sisusbvga/sisusb.h

@@ -120,9 +120,6 @@ struct sisusb_usb_data {
 	int isopen;		/* !=0 if open */
 	int isopen;		/* !=0 if open */
 	int present;		/* !=0 if device is present on the bus */
 	int present;		/* !=0 if device is present on the bus */
 	int ready;		/* !=0 if device is ready for userland */
 	int ready;		/* !=0 if device is ready for userland */
-#ifdef SISUSB_OLD_CONFIG_COMPAT
-	int ioctl32registered;
-#endif
 	int numobufs;		/* number of obufs = number of out urbs */
 	int numobufs;		/* number of obufs = number of out urbs */
 	char *obuf[NUMOBUFS], *ibuf;	/* transfer buffers */
 	char *obuf[NUMOBUFS], *ibuf;	/* transfer buffers */
 	int obufsize, ibufsize;
 	int obufsize, ibufsize;

+ 10 - 10
drivers/usb/misc/usbtest.c

@@ -6,6 +6,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/scatterlist.h>
 #include <linux/scatterlist.h>
+#include <linux/mutex.h>
 
 
 #include <linux/usb.h>
 #include <linux/usb.h>
 
 
@@ -64,7 +65,7 @@ struct usbtest_dev {
 	int			in_iso_pipe;
 	int			in_iso_pipe;
 	int			out_iso_pipe;
 	int			out_iso_pipe;
 	struct usb_endpoint_descriptor	*iso_in, *iso_out;
 	struct usb_endpoint_descriptor	*iso_in, *iso_out;
-	struct semaphore	sem;
+	struct mutex		lock;
 
 
 #define TBUF_SIZE	256
 #define TBUF_SIZE	256
 	u8			*buf;
 	u8			*buf;
@@ -1151,6 +1152,7 @@ static int verify_halted (int ep, struct urb *urb)
 		dbg ("ep %02x couldn't get halt status, %d", ep, retval);
 		dbg ("ep %02x couldn't get halt status, %d", ep, retval);
 		return retval;
 		return retval;
 	}
 	}
+	le16_to_cpus(&status);
 	if (status != 1) {
 	if (status != 1) {
 		dbg ("ep %02x bogus status: %04x != 1", ep, status);
 		dbg ("ep %02x bogus status: %04x != 1", ep, status);
 		return -EINVAL;
 		return -EINVAL;
@@ -1310,7 +1312,7 @@ static int ctrl_out (struct usbtest_dev *dev,
 		len += vary;
 		len += vary;
 
 
 		/* [real world] the "zero bytes IN" case isn't really used.
 		/* [real world] the "zero bytes IN" case isn't really used.
-		 * hardware can easily trip up in this wierd case, since its
+		 * hardware can easily trip up in this weird case, since its
 		 * status stage is IN, not OUT like other ep0in transfers.
 		 * status stage is IN, not OUT like other ep0in transfers.
 		 */
 		 */
 		if (len > length)
 		if (len > length)
@@ -1558,11 +1560,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
 			|| param->sglen < 0 || param->vary < 0)
 			|| param->sglen < 0 || param->vary < 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (down_interruptible (&dev->sem))
+	if (mutex_lock_interruptible(&dev->lock))
 		return -ERESTARTSYS;
 		return -ERESTARTSYS;
 
 
 	if (intf->dev.power.power_state.event != PM_EVENT_ON) {
 	if (intf->dev.power.power_state.event != PM_EVENT_ON) {
-		up (&dev->sem);
+		mutex_unlock(&dev->lock);
 		return -EHOSTUNREACH;
 		return -EHOSTUNREACH;
 	}
 	}
 
 
@@ -1574,7 +1576,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
 	    	int	res;
 	    	int	res;
 
 
 		if (intf->altsetting->desc.bInterfaceNumber) {
 		if (intf->altsetting->desc.bInterfaceNumber) {
-			up (&dev->sem);
+			mutex_unlock(&dev->lock);
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 		res = set_altsetting (dev, dev->info->alt);
 		res = set_altsetting (dev, dev->info->alt);
@@ -1582,7 +1584,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
 			dev_err (&intf->dev,
 			dev_err (&intf->dev,
 					"set altsetting to %d failed, %d\n",
 					"set altsetting to %d failed, %d\n",
 					dev->info->alt, res);
 					dev->info->alt, res);
-			up (&dev->sem);
+			mutex_unlock(&dev->lock);
 			return res;
 			return res;
 		}
 		}
 	}
 	}
@@ -1855,7 +1857,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
 		param->duration.tv_usec += 1000 * 1000;
 		param->duration.tv_usec += 1000 * 1000;
 		param->duration.tv_sec -= 1;
 		param->duration.tv_sec -= 1;
 	}
 	}
-	up (&dev->sem);
+	mutex_unlock(&dev->lock);
 	return retval;
 	return retval;
 }
 }
 
 
@@ -1905,7 +1907,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
 		return -ENOMEM;
 		return -ENOMEM;
 	info = (struct usbtest_info *) id->driver_info;
 	info = (struct usbtest_info *) id->driver_info;
 	dev->info = info;
 	dev->info = info;
-	init_MUTEX (&dev->sem);
+	mutex_init(&dev->lock);
 
 
 	dev->intf = intf;
 	dev->intf = intf;
 
 
@@ -1990,8 +1992,6 @@ static void usbtest_disconnect (struct usb_interface *intf)
 {
 {
 	struct usbtest_dev	*dev = usb_get_intfdata (intf);
 	struct usbtest_dev	*dev = usb_get_intfdata (intf);
 
 
-	down (&dev->sem);
-
 	usb_set_intfdata (intf, NULL);
 	usb_set_intfdata (intf, NULL);
 	dev_dbg (&intf->dev, "disconnect\n");
 	dev_dbg (&intf->dev, "disconnect\n");
 	kfree (dev);
 	kfree (dev);

+ 12 - 10
drivers/usb/mon/mon_bin.c

@@ -1026,6 +1026,8 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 	return mask;
 	return mask;
 }
 }
 
 
+#if 0
+
 /*
 /*
  * open and close: just keep track of how many times the device is
  * open and close: just keep track of how many times the device is
  * mapped, to use the proper memory allocation function.
  * mapped, to use the proper memory allocation function.
@@ -1045,33 +1047,31 @@ static void mon_bin_vma_close(struct vm_area_struct *vma)
 /*
 /*
  * Map ring pages to user space.
  * Map ring pages to user space.
  */
  */
-struct page *mon_bin_vma_nopage(struct vm_area_struct *vma,
-                                unsigned long address, int *type)
+static int mon_bin_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 {
 	struct mon_reader_bin *rp = vma->vm_private_data;
 	struct mon_reader_bin *rp = vma->vm_private_data;
 	unsigned long offset, chunk_idx;
 	unsigned long offset, chunk_idx;
 	struct page *pageptr;
 	struct page *pageptr;
 
 
-	offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+	offset = vmf->pgoff << PAGE_SHIFT;
 	if (offset >= rp->b_size)
 	if (offset >= rp->b_size)
-		return NOPAGE_SIGBUS;
+		return VM_FAULT_SIGBUS;
 	chunk_idx = offset / CHUNK_SIZE;
 	chunk_idx = offset / CHUNK_SIZE;
 	pageptr = rp->b_vec[chunk_idx].pg;
 	pageptr = rp->b_vec[chunk_idx].pg;
 	get_page(pageptr);
 	get_page(pageptr);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return pageptr;
+	vmf->page = pageptr;
+	return 0;
 }
 }
 
 
 struct vm_operations_struct mon_bin_vm_ops = {
 struct vm_operations_struct mon_bin_vm_ops = {
 	.open =     mon_bin_vma_open,
 	.open =     mon_bin_vma_open,
 	.close =    mon_bin_vma_close,
 	.close =    mon_bin_vma_close,
-	.nopage =   mon_bin_vma_nopage,
+	.fault =    mon_bin_vma_fault,
 };
 };
 
 
 int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
 int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 {
-	/* don't do anything here: "nopage" will set up page table entries */
+	/* don't do anything here: "fault" will set up page table entries */
 	vma->vm_ops = &mon_bin_vm_ops;
 	vma->vm_ops = &mon_bin_vm_ops;
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_private_data = filp->private_data;
 	vma->vm_private_data = filp->private_data;
@@ -1079,7 +1079,9 @@ int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
 	return 0;
 	return 0;
 }
 }
 
 
-struct file_operations mon_fops_binary = {
+#endif  /*  0  */
+
+static const struct file_operations mon_fops_binary = {
 	.owner =	THIS_MODULE,
 	.owner =	THIS_MODULE,
 	.open =		mon_bin_open,
 	.open =		mon_bin_open,
 	.llseek =	no_llseek,
 	.llseek =	no_llseek,

+ 25 - 12
drivers/usb/serial/Kconfig

@@ -2,10 +2,7 @@
 # USB Serial device configuration
 # USB Serial device configuration
 #
 #
 
 
-menu "USB Serial Converter support"
-	depends on USB!=n
-
-config USB_SERIAL
+menuconfig USB_SERIAL
 	tristate "USB Serial Converter support"
 	tristate "USB Serial Converter support"
 	depends on USB
 	depends on USB
 	---help---
 	---help---
@@ -20,6 +17,8 @@ config USB_SERIAL
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbserial.
 	  module will be called usbserial.
 
 
+if USB_SERIAL
+
 config USB_SERIAL_CONSOLE
 config USB_SERIAL_CONSOLE
 	bool "USB Serial Console device support (EXPERIMENTAL)"
 	bool "USB Serial Console device support (EXPERIMENTAL)"
 	depends on USB_SERIAL=y && EXPERIMENTAL
 	depends on USB_SERIAL=y && EXPERIMENTAL
@@ -43,6 +42,12 @@ config USB_SERIAL_CONSOLE
 
 
 	  If unsure, say N.
 	  If unsure, say N.
 
 
+config USB_EZUSB
+	bool "Functions for loading firmware on EZUSB chips"
+	depends on USB_SERIAL
+	help
+	    Say Y here if you need EZUSB device support.
+
 config USB_SERIAL_GENERIC
 config USB_SERIAL_GENERIC
 	bool "USB Generic Serial Driver"
 	bool "USB Generic Serial Driver"
 	depends on USB_SERIAL
 	depends on USB_SERIAL
@@ -105,6 +110,7 @@ config USB_SERIAL_CH341
 config USB_SERIAL_WHITEHEAT
 config USB_SERIAL_WHITEHEAT
 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
 	depends on USB_SERIAL
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	help
 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
 	  USB to serial converter device.
 	  USB to serial converter device.
@@ -282,9 +288,21 @@ config USB_SERIAL_IPW
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called ipw.
 	  module will be called ipw.
 
 
+config USB_SERIAL_IUU
+	tristate "USB Infinity USB Unlimited Phoenix Driver (Experimental)"
+	depends on USB_SERIAL && EXPERIMENTAL
+	help
+	  Say Y here if you want to use a IUU in phoenix mode and get
+	  an extra ttyUSBx device. More information available on
+	  http://eczema.ecze.com/iuu_phoenix.html
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iuu_phoenix.o
+
 config USB_SERIAL_KEYSPAN_PDA
 config USB_SERIAL_KEYSPAN_PDA
 	tristate "USB Keyspan PDA Single Port Serial Driver"
 	tristate "USB Keyspan PDA Single Port Serial Driver"
 	depends on USB_SERIAL
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	help
 	  Say Y here if you want to use a Keyspan PDA single port USB to
 	  Say Y here if you want to use a Keyspan PDA single port USB to
 	  serial converter device.  This driver makes use of firmware
 	  serial converter device.  This driver makes use of firmware
@@ -296,6 +314,7 @@ config USB_SERIAL_KEYSPAN_PDA
 config USB_SERIAL_KEYSPAN
 config USB_SERIAL_KEYSPAN
 	tristate "USB Keyspan USA-xxx Serial Driver"
 	tristate "USB Keyspan USA-xxx Serial Driver"
 	depends on USB_SERIAL
 	depends on USB_SERIAL
+	select USB_EZUSB
 	---help---
 	---help---
 	  Say Y here if you want to use Keyspan USB to serial converter
 	  Say Y here if you want to use Keyspan USB to serial converter
 	  devices.  This driver makes use of Keyspan's official firmware
 	  devices.  This driver makes use of Keyspan's official firmware
@@ -538,6 +557,7 @@ config USB_SERIAL_CYBERJACK
 config USB_SERIAL_XIRCOM
 config USB_SERIAL_XIRCOM
 	tristate "USB Xircom / Entregra Single Port Serial Driver"
 	tristate "USB Xircom / Entregra Single Port Serial Driver"
 	depends on USB_SERIAL
 	depends on USB_SERIAL
+	select USB_EZUSB
 	help
 	help
 	  Say Y here if you want to use a Xircom or Entregra single port USB to
 	  Say Y here if you want to use a Xircom or Entregra single port USB to
 	  serial converter device.  This driver makes use of firmware
 	  serial converter device.  This driver makes use of firmware
@@ -585,11 +605,4 @@ config USB_SERIAL_DEBUG
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called usb-debug.
 	  module will be called usb-debug.
 
 
-config USB_EZUSB
-	bool
-	depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
-	default y
-
-
-endmenu
-
+endif # USB_SERIAL

+ 1 - 0
drivers/usb/serial/Makefile

@@ -30,6 +30,7 @@ obj-$(CONFIG_USB_SERIAL_GARMIN)			+= garmin_gps.o
 obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
 obj-$(CONFIG_USB_SERIAL_HP4X)			+= hp4x.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
 obj-$(CONFIG_USB_SERIAL_IPAQ)			+= ipaq.o
 obj-$(CONFIG_USB_SERIAL_IPW)			+= ipw.o
 obj-$(CONFIG_USB_SERIAL_IPW)			+= ipw.o
+obj-$(CONFIG_USB_SERIAL_IUU)			+= iuu_phoenix.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN)		+= keyspan.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN)		+= keyspan.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)		+= keyspan_pda.o

+ 4 - 1
drivers/usb/serial/airprime.c

@@ -217,7 +217,10 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
 	priv->rts_state = 0;
 	priv->rts_state = 0;
 	priv->dtr_state = 0;
 	priv->dtr_state = 0;
 
 
-	airprime_send_setup(port);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
+		airprime_send_setup(port);
+	mutex_lock(&port->serial->disc_mutex);
 
 
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 	for (i = 0; i < NUM_READ_URBS; ++i) {
 		usb_kill_urb (priv->read_urbp[i]);
 		usb_kill_urb (priv->read_urbp[i]);

+ 3 - 1
drivers/usb/serial/ark3116.c

@@ -151,8 +151,10 @@ static int ark3116_attach(struct usb_serial *serial)
 	return 0;
 	return 0;
 
 
 cleanup:
 cleanup:
-	for (--i; i >= 0; --i)
+	for (--i; i >= 0; --i) {
+		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
 		usb_set_serial_port_data(serial->port[i], NULL);
+	}
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
 
 

+ 16 - 21
drivers/usb/serial/belkin_sa.c

@@ -350,14 +350,12 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
 	unsigned long control_state;
 	unsigned long control_state;
 	int bad_flow_control;
 	int bad_flow_control;
 	speed_t baud;
 	speed_t baud;
+	struct ktermios *termios = port->tty->termios;
 	
 	
-	if ((!port->tty) || (!port->tty->termios)) {
-		dbg ("%s - no tty or termios structure", __FUNCTION__);
-		return;
-	}
+	iflag = termios->c_iflag;
+	cflag = termios->c_cflag;
 
 
-	iflag = port->tty->termios->c_iflag;
-	cflag = port->tty->termios->c_cflag;
+	termios->c_cflag &= ~CMSPAR;
 
 
 	/* get a local copy of the current port settings */
 	/* get a local copy of the current port settings */
 	spin_lock_irqsave(&priv->lock, flags);
 	spin_lock_irqsave(&priv->lock, flags);
@@ -369,33 +367,30 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
 	old_cflag = old_termios->c_cflag;
 	old_cflag = old_termios->c_cflag;
 
 
 	/* Set the baud rate */
 	/* Set the baud rate */
-	if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
+	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
 		/* reassert DTR and (maybe) RTS on transition from B0 */
 		/* reassert DTR and (maybe) RTS on transition from B0 */
 		if( (old_cflag&CBAUD) == B0 ) {
 		if( (old_cflag&CBAUD) == B0 ) {
 			control_state |= (TIOCM_DTR|TIOCM_RTS);
 			control_state |= (TIOCM_DTR|TIOCM_RTS);
 			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
 			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
 				err("Set DTR error");
 				err("Set DTR error");
 			/* don't set RTS if using hardware flow control */
 			/* don't set RTS if using hardware flow control */
-			if (!(old_cflag&CRTSCTS) )
+			if (!(old_cflag & CRTSCTS))
 				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
 				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
 					err("Set RTS error");
 					err("Set RTS error");
 		}
 		}
 	}
 	}
 
 
 	baud = tty_get_baud_rate(port->tty);
 	baud = tty_get_baud_rate(port->tty);
-	if (baud == 0) {
-		dbg("%s - tty_get_baud_rate says 0 baud", __FUNCTION__);
-		return;
-	}
-	urb_value = BELKIN_SA_BAUD(baud);
-	/* Clip to maximum speed */
-	if (urb_value == 0)
-		urb_value = 1;
-	/* Turn it back into a resulting real baud rate */
-	baud = BELKIN_SA_BAUD(urb_value);
-	/* FIXME: Once the tty updates are done then push this back to the tty */
-
-	if ((cflag & CBAUD) != B0 ) {
+	if (baud) {
+		urb_value = BELKIN_SA_BAUD(baud);
+		/* Clip to maximum speed */
+		if (urb_value == 0)
+			urb_value = 1;
+		/* Turn it back into a resulting real baud rate */
+		baud = BELKIN_SA_BAUD(urb_value);
+
+		/* Report the actual baud rate back to the caller */
+		tty_encode_baud_rate(port->tty, baud, baud);
 		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
 		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
 			err("Set baudrate error");
 			err("Set baudrate error");
 	} else {
 	} else {

+ 54 - 36
drivers/usb/serial/console.c

@@ -64,8 +64,8 @@ static int usb_console_setup(struct console *co, char *options)
 	struct usb_serial *serial;
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	struct usb_serial_port *port;
 	int retval = 0;
 	int retval = 0;
-	struct tty_struct *tty;
-	struct ktermios *termios;
+	struct tty_struct *tty = NULL;
+	struct ktermios *termios = NULL, dummy;
 
 
 	dbg ("%s", __FUNCTION__);
 	dbg ("%s", __FUNCTION__);
 
 
@@ -133,11 +133,14 @@ static int usb_console_setup(struct console *co, char *options)
 	}
 	}
 	co->cflag = cflag;
 	co->cflag = cflag;
 
 
-	/* grab the first serial port that happens to be connected */
-	serial = usb_serial_get_by_index(0);
+	/*
+	 * no need to check the index here: if the index is wrong, console
+	 * code won't call us
+	 */
+	serial = usb_serial_get_by_index(co->index);
 	if (serial == NULL) {
 	if (serial == NULL) {
 		/* no device is connected yet, sorry :( */
 		/* no device is connected yet, sorry :( */
-		err ("No USB device connected to ttyUSB0");
+		err ("No USB device connected to ttyUSB%i", co->index);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -148,49 +151,64 @@ static int usb_console_setup(struct console *co, char *options)
 	 
 	 
 	++port->open_count;
 	++port->open_count;
 	if (port->open_count == 1) {
 	if (port->open_count == 1) {
+		if (serial->type->set_termios) {
+			/*
+			 * allocate a fake tty so the driver can initialize
+			 * the termios structure, then later call set_termios to
+			 * configure according to command line arguments
+			 */
+			tty = kzalloc(sizeof(*tty), GFP_KERNEL);
+			if (!tty) {
+				retval = -ENOMEM;
+				err("no more memory");
+				goto reset_open_count;
+			}
+			termios = kzalloc(sizeof(*termios), GFP_KERNEL);
+			if (!termios) {
+				retval = -ENOMEM;
+				err("no more memory");
+				goto free_tty;
+			}
+			memset(&dummy, 0, sizeof(struct ktermios));
+			tty->termios = termios;
+			port->tty = tty;
+		}
+
 		/* only call the device specific open if this 
 		/* only call the device specific open if this 
 		 * is the first time the port is opened */
 		 * is the first time the port is opened */
 		if (serial->type->open)
 		if (serial->type->open)
 			retval = serial->type->open(port, NULL);
 			retval = serial->type->open(port, NULL);
 		else
 		else
 			retval = usb_serial_generic_open(port, NULL);
 			retval = usb_serial_generic_open(port, NULL);
-		if (retval)
-			port->open_count = 0;
-	}
 
 
-	if (retval) {
-		err ("could not open USB console port");
-		return retval;
-	}
-
-	if (serial->type->set_termios) {
-		struct ktermios dummy;
-		/* build up a fake tty structure so that the open call has something
-		 * to look at to get the cflag value */
-		tty = kzalloc(sizeof(*tty), GFP_KERNEL);
-		if (!tty) {
-			err ("no more memory");
-			return -ENOMEM;
+		if (retval) {
+			err("could not open USB console port");
+			goto free_termios;
 		}
 		}
-		termios = kzalloc(sizeof(*termios), GFP_KERNEL);
-		if (!termios) {
-			err ("no more memory");
-			kfree (tty);
-			return -ENOMEM;
-		}
-		memset(&dummy, 0, sizeof(struct ktermios));
-		termios->c_cflag = cflag;
-		tty->termios = termios;
-		port->tty = tty;
 
 
-		/* set up the initial termios settings */
-		serial->type->set_termios(port, &dummy);
-		port->tty = NULL;
-		kfree (termios);
-		kfree (tty);
+		if (serial->type->set_termios) {
+			termios->c_cflag = cflag;
+			serial->type->set_termios(port, &dummy);
+
+			port->tty = NULL;
+			kfree(termios);
+			kfree(tty);
+		}
 	}
 	}
 
 
+	port->console = 1;
+	retval = 0;
+
+out:
 	return retval;
 	return retval;
+free_termios:
+	kfree(termios);
+	port->tty = NULL;
+free_tty:
+	kfree(tty);
+reset_open_count:
+	port->open_count = 0;
+goto out;
 }
 }
 
 
 static void usb_console_write(struct console *co, const char *buf, unsigned count)
 static void usb_console_write(struct console *co, const char *buf, unsigned count)

+ 10 - 1
drivers/usb/serial/cp2101.c

@@ -59,6 +59,7 @@ static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
 	{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
+	{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
 	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
@@ -76,8 +77,13 @@ static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
 	{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+	{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
+	{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
+	{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
+	{ USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
 	{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
 	{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
 	{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
 	{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
+	{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
 	{ } /* Terminating Entry */
 	{ } /* Terminating Entry */
 };
 };
@@ -342,7 +348,10 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
 	usb_kill_urb(port->write_urb);
 	usb_kill_urb(port->write_urb);
 	usb_kill_urb(port->read_urb);
 	usb_kill_urb(port->read_urb);
 
 
-	cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
+	mutex_lock(&port->serial->disc_mutex);
+	if (!port->serial->disconnected)
+		cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
+	mutex_unlock(&port->serial->disc_mutex);
 }
 }
 
 
 /*
 /*

+ 0 - 1
drivers/usb/serial/cyberjack.c

@@ -319,7 +319,6 @@ static void cyberjack_read_int_callback( struct urb *urb )
 	/* React only to interrupts signaling a bulk_in transfer */
 	/* React only to interrupts signaling a bulk_in transfer */
 	if( (urb->actual_length==4) && (data[0]==0x01) ) {
 	if( (urb->actual_length==4) && (data[0]==0x01) ) {
 		short old_rdtodo;
 		short old_rdtodo;
-		int result;
 
 
 		/* This is a announcement of coming bulk_ins. */
 		/* This is a announcement of coming bulk_ins. */
 		unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
 		unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;

+ 16 - 9
drivers/usb/serial/cypress_m8.c

@@ -682,7 +682,6 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 {
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned int c_cflag;
 	unsigned int c_cflag;
-	unsigned long flags;
 	int bps;
 	int bps;
 	long timeout;
 	long timeout;
 	wait_queue_t wait;
 	wait_queue_t wait;
@@ -690,7 +689,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 
 	/* wait for data to drain from buffer */
 	/* wait for data to drain from buffer */
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irq(&priv->lock);
 	timeout = CYPRESS_CLOSING_WAIT;
 	timeout = CYPRESS_CLOSING_WAIT;
 	init_waitqueue_entry(&wait, current);
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&port->tty->write_wait, &wait);
 	add_wait_queue(&port->tty->write_wait, &wait);
@@ -698,18 +697,25 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 		set_current_state(TASK_INTERRUPTIBLE);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (cypress_buf_data_avail(priv->buf) == 0
 		if (cypress_buf_data_avail(priv->buf) == 0
 		|| timeout == 0 || signal_pending(current)
 		|| timeout == 0 || signal_pending(current)
-		|| !usb_get_intfdata(port->serial->interface))
+		/* without mutex, allowed due to harmless failure mode */
+		|| port->serial->disconnected)
 			break;
 			break;
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock_irq(&priv->lock);
 		timeout = schedule_timeout(timeout);
 		timeout = schedule_timeout(timeout);
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock_irq(&priv->lock);
 	}
 	}
 	set_current_state(TASK_RUNNING);
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->tty->write_wait, &wait);
 	remove_wait_queue(&port->tty->write_wait, &wait);
 	/* clear out any remaining data in the buffer */
 	/* clear out any remaining data in the buffer */
 	cypress_buf_clear(priv->buf);
 	cypress_buf_clear(priv->buf);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	
+	spin_unlock_irq(&priv->lock);
+
+	/* writing is potentially harmful, lock must be taken */
+	mutex_lock(&port->serial->disc_mutex);
+	if (port->serial->disconnected) {
+		mutex_unlock(&port->serial->disc_mutex);
+		return;
+	}
 	/* wait for characters to drain from device */
 	/* wait for characters to drain from device */
 	bps = tty_get_baud_rate(port->tty);
 	bps = tty_get_baud_rate(port->tty);
 	if (bps > 1200)
 	if (bps > 1200)
@@ -727,10 +733,10 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 		if (c_cflag & HUPCL) {
 		if (c_cflag & HUPCL) {
 			/* drop dtr and rts */
 			/* drop dtr and rts */
 			priv = usb_get_serial_port_data(port);
 			priv = usb_get_serial_port_data(port);
-			spin_lock_irqsave(&priv->lock, flags);
+			spin_lock_irq(&priv->lock);
 			priv->line_control = 0;
 			priv->line_control = 0;
 			priv->cmd_ctrl = 1;
 			priv->cmd_ctrl = 1;
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_unlock_irq(&priv->lock);
 			cypress_write(port, NULL, 0);
 			cypress_write(port, NULL, 0);
 		}
 		}
 	}
 	}
@@ -738,6 +744,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 	if (stats)
 	if (stats)
 		dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
 		dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
 		          priv->bytes_in, priv->bytes_out, priv->cmd_count);
 		          priv->bytes_in, priv->bytes_out, priv->cmd_count);
+	mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */
 } /* cypress_close */
 
 
 
 

+ 7 - 6
drivers/usb/serial/digi_acceleport.c

@@ -1405,19 +1405,19 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
 	unsigned char buf[32];
 	unsigned char buf[32];
 	struct tty_struct *tty = port->tty;
 	struct tty_struct *tty = port->tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	unsigned long flags = 0;
 
 
 	dbg("digi_close: TOP: port=%d, open_count=%d",
 	dbg("digi_close: TOP: port=%d, open_count=%d",
 		priv->dp_port_num, port->open_count);
 		priv->dp_port_num, port->open_count);
 
 
+	mutex_lock(&port->serial->disc_mutex);
 	/* if disconnected, just clear flags */
 	/* if disconnected, just clear flags */
-	if (!usb_get_intfdata(port->serial->interface))
+	if (port->serial->disconnected)
 		goto exit;
 		goto exit;
 
 
 	/* do cleanup only after final close on this port */
 	/* do cleanup only after final close on this port */
-	spin_lock_irqsave(&priv->dp_port_lock, flags);
+	spin_lock_irq(&priv->dp_port_lock);
 	priv->dp_in_close = 1;
 	priv->dp_in_close = 1;
-	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+	spin_unlock_irq(&priv->dp_port_lock);
 
 
 	/* tell line discipline to process only XON/XOFF */
 	/* tell line discipline to process only XON/XOFF */
 	tty->closing = 1;
 	tty->closing = 1;
@@ -1482,11 +1482,12 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
 	}
 	}
 	tty->closing = 0;
 	tty->closing = 0;
 exit:
 exit:
-	spin_lock_irqsave(&priv->dp_port_lock, flags);
+	spin_lock_irq(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
 	priv->dp_in_close = 0;
 	wake_up_interruptible(&priv->dp_close_wait);
 	wake_up_interruptible(&priv->dp_close_wait);
-	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+	spin_unlock_irq(&priv->dp_port_lock);
+	mutex_unlock(&port->serial->disc_mutex);
 	dbg("digi_close: done");
 	dbg("digi_close: done");
 }
 }
 
 

部分文件因为文件数量过多而无法显示