aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb33
-rw-r--r--Documentation/feature-removal-schedule.txt16
-rw-r--r--Documentation/pci.txt37
-rw-r--r--Documentation/usb/gadget_printer.txt510
-rw-r--r--Documentation/usb/iuu_phoenix.txt84
-rw-r--r--arch/alpha/Kconfig5
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/mach-pxa/tosa.c9
-rw-r--r--arch/frv/Kconfig5
-rw-r--r--arch/m32r/Kconfig5
-rw-r--r--arch/m68k/Kconfig5
-rw-r--r--arch/mips/Kconfig5
-rw-r--r--arch/sh/drivers/pci/Kconfig5
-rw-r--r--arch/sparc64/Kconfig5
-rw-r--r--arch/x86/Kconfig5
-rw-r--r--arch/x86/kernel/quirks.c43
-rw-r--r--arch/x86/pci/fixup.c22
-rw-r--r--arch/xtensa/Kconfig5
-rw-r--r--drivers/ata/pata_cs5520.c2
-rw-r--r--drivers/block/ub.c23
-rw-r--r--drivers/i2c/busses/scx200_acb.c2
-rw-r--r--drivers/ide/pci/cs5520.c10
-rw-r--r--drivers/ide/setup-pci.c6
-rw-r--r--drivers/pci/bus.c18
-rw-r--r--drivers/pci/dmar.c20
-rw-r--r--drivers/pci/hotplug/Kconfig4
-rw-r--r--drivers/pci/hotplug/Makefile4
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c5
-rw-r--r--drivers/pci/hotplug/fakephp.c39
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c11
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c4
-rw-r--r--drivers/pci/hotplug/pciehp.h9
-rw-r--r--drivers/pci/hotplug/pciehp_core.c33
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c27
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c314
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c43
-rw-r--r--drivers/pci/hotplug/rpaphp.h1
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c14
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c47
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c2
-rw-r--r--drivers/pci/intel-iommu.c2
-rw-r--r--drivers/pci/msi.c94
-rw-r--r--drivers/pci/pci-acpi.c7
-rw-r--r--drivers/pci/pci-driver.c4
-rw-r--r--drivers/pci/pci-sysfs.c11
-rw-r--r--drivers/pci/pci.c93
-rw-r--r--drivers/pci/pci.h16
-rw-r--r--drivers/pci/pcie/Kconfig20
-rw-r--r--drivers/pci/pcie/Makefile3
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c24
-rw-r--r--drivers/pci/pcie/aspm.c802
-rw-r--r--drivers/pci/pcie/portdrv_core.c5
-rw-r--r--drivers/pci/probe.c80
-rw-r--r--drivers/pci/proc.c17
-rw-r--r--drivers/pci/quirks.c483
-rw-r--r--drivers/pci/remove.c10
-rw-r--r--drivers/pci/rom.c6
-rw-r--r--drivers/pci/setup-bus.c64
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pci/syscall.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c21
-rw-r--r--drivers/usb/Kconfig5
-rw-r--r--drivers/usb/atm/Kconfig9
-rw-r--r--drivers/usb/atm/ueagle-atm.c6
-rw-r--r--drivers/usb/class/cdc-acm.c94
-rw-r--r--drivers/usb/class/cdc-acm.h2
-rw-r--r--drivers/usb/core/Kconfig15
-rw-r--r--drivers/usb/core/buffer.c20
-rw-r--r--drivers/usb/core/config.c14
-rw-r--r--drivers/usb/core/devices.c154
-rw-r--r--drivers/usb/core/devio.c359
-rw-r--r--drivers/usb/core/driver.c44
-rw-r--r--drivers/usb/core/file.c4
-rw-r--r--drivers/usb/core/hcd-pci.c145
-rw-r--r--drivers/usb/core/hcd.c216
-rw-r--r--drivers/usb/core/hcd.h92
-rw-r--r--drivers/usb/core/hub.c88
-rw-r--r--drivers/usb/core/hub.h18
-rw-r--r--drivers/usb/core/inode.c42
-rw-r--r--drivers/usb/core/message.c430
-rw-r--r--drivers/usb/core/notify.c2
-rw-r--r--drivers/usb/core/otg_whitelist.h6
-rw-r--r--drivers/usb/core/sysfs.c69
-rw-r--r--drivers/usb/core/urb.c37
-rw-r--r--drivers/usb/core/usb.c117
-rw-r--r--drivers/usb/core/usb.h21
-rw-r--r--drivers/usb/gadget/Kconfig33
-rw-r--r--drivers/usb/gadget/Makefile3
-rw-r--r--drivers/usb/gadget/amd5536udc.c3
-rw-r--r--drivers/usb/gadget/at91_udc.c87
-rw-r--r--drivers/usb/gadget/at91_udc.h17
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c11
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.h7
-rw-r--r--drivers/usb/gadget/dummy_hcd.c38
-rw-r--r--drivers/usb/gadget/ether.c6
-rw-r--r--drivers/usb/gadget/file_storage.c14
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c4
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h6
-rw-r--r--drivers/usb/gadget/gmidi.c6
-rw-r--r--drivers/usb/gadget/goku_udc.c1
-rw-r--r--drivers/usb/gadget/inode.c2
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c1
-rw-r--r--drivers/usb/gadget/m66592-udc.c104
-rw-r--r--drivers/usb/gadget/m66592-udc.h54
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c73
-rw-r--r--drivers/usb/gadget/omap_udc.h13
-rw-r--r--drivers/usb/gadget/printer.c1592
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c141
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h25
-rw-r--r--drivers/usb/gadget/rndis.c20
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c4
-rw-r--r--drivers/usb/gadget/serial.c153
-rw-r--r--drivers/usb/gadget/zero.c4
-rw-r--r--drivers/usb/host/Kconfig22
-rw-r--r--drivers/usb/host/ehci-au1xxx.c1
-rw-r--r--drivers/usb/host/ehci-dbg.c231
-rw-r--r--drivers/usb/host/ehci-fsl.c3
-rw-r--r--drivers/usb/host/ehci-hcd.c159
-rw-r--r--drivers/usb/host/ehci-hub.c98
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c152
-rw-r--r--drivers/usb/host/ehci-orion.c272
-rw-r--r--drivers/usb/host/ehci-pci.c3
-rw-r--r--drivers/usb/host/ehci-ppc-of.c238
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ehci-ps3.c1
-rw-r--r--drivers/usb/host/ehci-q.c25
-rw-r--r--drivers/usb/host/ehci-sched.c152
-rw-r--r--drivers/usb/host/ehci.h40
-rw-r--r--drivers/usb/host/isp116x-hcd.c1
-rw-r--r--drivers/usb/host/ohci-at91.c31
-rw-r--r--drivers/usb/host/ohci-dbg.c213
-rw-r--r--drivers/usb/host/ohci-hcd.c34
-rw-r--r--drivers/usb/host/ohci-sh.c143
-rw-r--r--drivers/usb/host/ohci-sm501.c264
-rw-r--r--drivers/usb/host/ohci.h7
-rw-r--r--drivers/usb/host/pci-quirks.c22
-rw-r--r--drivers/usb/host/r8a66597.h2
-rw-r--r--drivers/usb/image/mdc800.c2
-rw-r--r--drivers/usb/misc/cypress_cy7c63.c7
-rw-r--r--drivers/usb/misc/iowarrior.c2
-rw-r--r--drivers/usb/misc/legousbtower.c30
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c29
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h3
-rw-r--r--drivers/usb/misc/usbtest.c20
-rw-r--r--drivers/usb/mon/mon_bin.c22
-rw-r--r--drivers/usb/serial/Kconfig37
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/airprime.c5
-rw-r--r--drivers/usb/serial/ark3116.c4
-rw-r--r--drivers/usb/serial/belkin_sa.c37
-rw-r--r--drivers/usb/serial/console.c90
-rw-r--r--drivers/usb/serial/cp2101.c11
-rw-r--r--drivers/usb/serial/cyberjack.c1
-rw-r--r--drivers/usb/serial/cypress_m8.c25
-rw-r--r--drivers/usb/serial/digi_acceleport.c13
-rw-r--r--drivers/usb/serial/ezusb.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c293
-rw-r--r--drivers/usb/serial/ftdi_sio.h15
-rw-r--r--drivers/usb/serial/garmin_gps.c17
-rw-r--r--drivers/usb/serial/generic.c8
-rw-r--r--drivers/usb/serial/io_edgeport.c8
-rw-r--r--drivers/usb/serial/io_ti.c47
-rw-r--r--drivers/usb/serial/iuu_phoenix.c1217
-rw-r--r--drivers/usb/serial/iuu_phoenix.h122
-rw-r--r--drivers/usb/serial/keyspan.c2
-rw-r--r--drivers/usb/serial/keyspan_pda.c38
-rw-r--r--drivers/usb/serial/kl5kusb105.c26
-rw-r--r--drivers/usb/serial/kobil_sct.c1
-rw-r--r--drivers/usb/serial/mct_u232.c43
-rw-r--r--drivers/usb/serial/mct_u232.h2
-rw-r--r--drivers/usb/serial/mos7720.c61
-rw-r--r--drivers/usb/serial/mos7840.c8
-rw-r--r--drivers/usb/serial/option.c6
-rw-r--r--drivers/usb/serial/oti6858.c131
-rw-r--r--drivers/usb/serial/pl2303.c112
-rw-r--r--drivers/usb/serial/pl2303.h13
-rw-r--r--drivers/usb/serial/sierra.c227
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c75
-rw-r--r--drivers/usb/serial/usb-serial.c42
-rw-r--r--drivers/usb/serial/visor.c22
-rw-r--r--drivers/usb/serial/whiteheat.c10
-rw-r--r--drivers/usb/storage/initializers.c3
-rw-r--r--drivers/usb/storage/isd200.c29
-rw-r--r--drivers/usb/storage/unusual_devs.h8
-rw-r--r--drivers/video/sis/sis.h8
-rw-r--r--drivers/video/sis/sis_main.c48
-rw-r--r--include/asm-arm/arch-at91/board.h3
-rw-r--r--include/asm-arm/mach/udc_pxa2xx.h2
-rw-r--r--include/linux/aspm.h44
-rw-r--r--include/linux/pci-acpi.h11
-rw-r--r--include/linux/pci.h367
-rw-r--r--include/linux/pci_regs.h8
-rw-r--r--include/linux/usb.h209
-rw-r--r--include/linux/usb/Kbuild11
-rw-r--r--include/linux/usb/audio.h14
-rw-r--r--include/linux/usb/cdc.h16
-rw-r--r--include/linux/usb/g_printer.h31
-rw-r--r--include/linux/usb/gadget.h123
-rw-r--r--include/linux/usb/gadgetfs.h27
-rw-r--r--include/linux/usb/iowarrior.h25
-rw-r--r--include/linux/usb/isp116x.h2
-rw-r--r--include/linux/usb/midi.h26
-rw-r--r--include/linux/usb/net2280.h32
-rw-r--r--include/linux/usb/otg.h2
-rw-r--r--include/linux/usb/serial.h160
-rw-r--r--include/linux/usb/sl811.h6
-rw-r--r--include/linux/usb_usual.h5
-rw-r--r--include/linux/usbdevice_fs.h2
-rw-r--r--kernel/softlockup.c30
-rw-r--r--scripts/mod/file2alias.c2
214 files changed, 10321 insertions, 3591 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 9734577d171..11a3c1682ce 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -52,3 +52,36 @@ Description:
facility is inherently dangerous, it is disabled by default
for all devices except hubs. For more information, see
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/
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 181bff00516..a7d9d179131 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/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
When: Soon, provided in-kernel callers have been converted
Why: This interface is replaced by vm_ops.fault, but it has been around
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 7754f5aea4e..72b20c63959 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -274,8 +274,6 @@ the PCI device by calling pci_enable_device(). This will:
o allocate an IRQ (if BIOS did not).
NOTE: pci_enable_device() can fail! Check the return value.
-NOTE2: Also see pci_enable_device_bars() below. Drivers can
- attempt to enable only a subset of BARs they need.
[ OS BUG: we don't check resource allocations before enabling those
resources. The sequence would make more sense if we called
@@ -605,40 +603,7 @@ device lists. This is still possible but discouraged.
-10. pci_enable_device_bars() and Legacy I/O Port space
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Large servers may not be able to provide I/O port resources to all PCI
-devices. I/O Port space is only 64KB on Intel Architecture[1] and is
-likely also fragmented since the I/O base register of PCI-to-PCI
-bridge will usually be aligned to a 4KB boundary[2]. On such systems,
-pci_enable_device() and pci_request_region() will fail when
-attempting to enable I/O Port regions that don't have I/O Port
-resources assigned.
-
-Fortunately, many PCI devices which request I/O Port resources also
-provide access to the same registers via MMIO BARs. These devices can
-be handled without using I/O port space and the drivers typically
-offer a CONFIG_ option to only use MMIO regions
-(e.g. CONFIG_TULIP_MMIO). PCI devices typically provide I/O port
-interface for legacy OSes and will work when I/O port resources are not
-assigned. The "PCI Local Bus Specification Revision 3.0" discusses
-this on p.44, "IMPLEMENTATION NOTE".
-
-If your PCI device driver doesn't need I/O port resources assigned to
-I/O Port BARs, you should use pci_enable_device_bars() instead of
-pci_enable_device() in order not to enable I/O port regions for the
-corresponding devices. In addition, you should use
-pci_request_selected_regions() and pci_release_selected_regions()
-instead of pci_request_regions()/pci_release_regions() in order not to
-request/release I/O port regions for the corresponding devices.
-
-[1] Some systems support 64KB I/O port space per PCI segment.
-[2] Some PCI-to-PCI bridges support optional 1KB aligned I/O base.
-
-
-
-11. MMIO Space and "Write Posting"
+10. MMIO Space and "Write Posting"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Converting a driver from using I/O Port space to using MMIO space
diff --git a/Documentation/usb/gadget_printer.txt b/Documentation/usb/gadget_printer.txt
new file mode 100644
index 00000000000..ad995bf0db4
--- /dev/null
+++ b/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);
+}
diff --git a/Documentation/usb/iuu_phoenix.txt b/Documentation/usb/iuu_phoenix.txt
new file mode 100644
index 00000000000..e5f048067da
--- /dev/null
+++ b/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
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 4c002ba37e5..c613d5fb0da 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -318,11 +318,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config PCI_DOMAINS
bool
default y
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a00d8b97c30..4b1a8e3d292 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -577,11 +577,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config PCI_SYSCALL
def_bool PCI
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 1919756900f..1a9c844ac7e 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/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 = {
.udc_command = tosa_udc_command,
- .udc_is_connected = tosa_udc_is_connected,
+ .gpio_vbus = TOSA_GPIO_USB_IN,
+ .gpio_vbus_inverted = 1,
};
/*
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 2e25b95a494..e3f965c91e2 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -322,11 +322,6 @@ config PCI
onboard. If you have one of these boards and you wish to use the PCI
facilities, say Y here.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config RESERVE_DMA_COHERENT
bool "Reserve DMA coherent memory"
depends on PCI && !MMU
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index f7237c5f531..49326e9d441 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -359,11 +359,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
choice
prompt "PCI access mode"
depends on PCI
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 01dee84f840..24e6bc09e7a 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -145,11 +145,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config MAC
bool "Macintosh support"
depends on !MMU_SUN3
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e387f3ab5f8..36a4018f71d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1961,11 +1961,6 @@ config PCI
your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config PCI_DOMAINS
bool
diff --git a/arch/sh/drivers/pci/Kconfig b/arch/sh/drivers/pci/Kconfig
index fbc6f2c8649..7e816ededed 100644
--- a/arch/sh/drivers/pci/Kconfig
+++ b/arch/sh/drivers/pci/Kconfig
@@ -6,11 +6,6 @@ config PCI
bus system, i.e. the way the CPU talks to the other stuff inside
your box. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config SH_PCIDMA_NONCOHERENT
bool "Cache and PCI noncoherent"
depends on PCI
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 73fc05d0bfa..158522f51d3 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -351,11 +351,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
config PCI_DOMAINS
def_bool PCI
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 34401f45ade..7109037bdf7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1377,11 +1377,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
-
choice
prompt "PCI access mode"
depends on X86_32 && PCI && !X86_VISWS
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 150ba29a0d3..3cd7a2dcd4f 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -30,8 +30,8 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
if (!(word & (1 << 13))) {
- printk(KERN_INFO "Intel E7520/7320/7525 detected. "
- "Disabling irq balancing and affinity\n");
+ dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
+ "disabling irq balancing and affinity\n");
#ifdef CONFIG_IRQBALANCE
irqbalance_disable("");
#endif
@@ -104,14 +104,16 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
pci_read_config_dword(dev, 0xF0, &rcba);
rcba &= 0xFFFFC000;
if (rcba == 0) {
- printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n");
+ dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
+ "cannot force enable HPET\n");
return;
}
/* use bits 31:14, 16 kB aligned */
rcba_base = ioremap_nocache(rcba, 0x4000);
if (rcba_base == NULL) {
- printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n");
+ dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
+ "cannot force enable HPET\n");
return;
}
@@ -122,8 +124,8 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
/* HPET is enabled in HPTC. Just not reported by BIOS */
val = val & 0x3;
force_hpet_address = 0xFED00000 | (val << 12);
- printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+ "0x%lx\n", force_hpet_address);
iounmap(rcba_base);
return;
}
@@ -142,11 +144,12 @@ static void ich_force_enable_hpet(struct pci_dev *dev)
if (err) {
force_hpet_address = 0;
iounmap(rcba_base);
- printk(KERN_DEBUG "Failed to force enable HPET\n");
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "Failed to force enable HPET\n");
} else {
force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
- printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+ "0x%lx\n", force_hpet_address);
}
}
@@ -208,8 +211,8 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
if (val & 0x4) {
val &= 0x3;
force_hpet_address = 0xFED00000 | (val << 12);
- printk(KERN_DEBUG "HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+ force_hpet_address);
return;
}
@@ -229,14 +232,14 @@ static void old_ich_force_enable_hpet(struct pci_dev *dev)
/* HPET is enabled in HPTC. Just not reported by BIOS */
val &= 0x3;
force_hpet_address = 0xFED00000 | (val << 12);
- printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+ "0x%lx\n", force_hpet_address);
cached_dev = dev;
force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
return;
}
- printk(KERN_DEBUG "Failed to force enable HPET\n");
+ dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
}
/*
@@ -294,8 +297,8 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
*/
if (val & 0x80) {
force_hpet_address = (val & ~0x3ff);
- printk(KERN_DEBUG "HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
+ force_hpet_address);
return;
}
@@ -309,14 +312,14 @@ static void vt8237_force_enable_hpet(struct pci_dev *dev)
pci_read_config_dword(dev, 0x68, &val);
if (val & 0x80) {
force_hpet_address = (val & ~0x3ff);
- printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
- force_hpet_address);
+ dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
+ "0x%lx\n", force_hpet_address);
cached_dev = dev;
force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
return;
}
- printk(KERN_DEBUG "Failed to force enable HPET\n");
+ dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
@@ -344,7 +347,7 @@ static void nvidia_force_enable_hpet(struct pci_dev *dev)
pci_read_config_dword(dev, 0x44, &val);
force_hpet_address = val & 0xfffffffe;
force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
- printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n",
+ dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
force_hpet_address);
cached_dev = dev;
return;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index cb63007e20b..74d30ff33c4 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -17,7 +17,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
int pxb, reg;
u8 busno, suba, subb;
- printk(KERN_WARNING "PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
+ dev_warn(&d->dev, "Searching for i450NX host bridges\n");
reg = 0xd0;
for(pxb = 0; pxb < 2; pxb++) {
pci_read_config_byte(d, reg++, &busno);
@@ -41,7 +41,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
*/
u8 busno;
pci_read_config_byte(d, 0x4a, &busno);
- printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
+ dev_info(&d->dev, "i440KX/GX host bridge; secondary bus %02x\n", busno);
pci_scan_bus_with_sysdata(busno);
pcibios_last_bus = -1;
}
@@ -55,7 +55,7 @@ static void __devinit pci_fixup_umc_ide(struct pci_dev *d)
*/
int i;
- printk(KERN_WARNING "PCI: Fixing base address flags for device %s\n", pci_name(d));
+ dev_warn(&d->dev, "Fixing base address flags\n");
for(i = 0; i < 4; i++)
d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
}
@@ -68,7 +68,7 @@ static void __devinit pci_fixup_ncr53c810(struct pci_dev *d)
* Fix class to be PCI_CLASS_STORAGE_SCSI
*/
if (!d->class) {
- printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", pci_name(d));
+ dev_warn(&d->dev, "Fixing NCR 53C810 class code\n");
d->class = PCI_CLASS_STORAGE_SCSI << 8;
}
}
@@ -80,7 +80,7 @@ static void __devinit pci_fixup_latency(struct pci_dev *d)
* SiS 5597 and 5598 chipsets require latency timer set to
* at most 32 to avoid lockups.
*/
- DBG("PCI: Setting max latency to 32\n");
+ dev_dbg(&d->dev, "Setting max latency to 32\n");
pcibios_max_latency = 32;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
@@ -138,7 +138,7 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
pci_read_config_byte(d, where, &v);
if (v & ~mask) {
- printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
+ dev_warn(&d->dev, "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
d->device, d->revision, where, v, mask, v & mask);
v &= mask;
pci_write_config_byte(d, where, v);
@@ -200,7 +200,7 @@ static void pci_fixup_nforce2(struct pci_dev *dev)
* Apply fixup if needed, but don't touch disconnect state
*/
if ((val & 0x00FF0000) != 0x00010000) {
- printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+ dev_warn(&dev->dev, "nForce2 C1 Halt Disconnect fixup\n");
pci_write_config_dword(dev, 0x6c, (val & 0xFF00FFFF) | 0x00010000);
}
}
@@ -348,7 +348,7 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
pci_read_config_word(pdev, PCI_COMMAND, &config);
if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
- printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+ dev_printk(KERN_DEBUG, &pdev->dev, "Boot video device\n");
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
@@ -388,11 +388,11 @@ static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
/* verify the change for status output */
pci_read_config_byte(dev, 0x50, &val);
if (val & 0x40)
- printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
+ dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
"can't enable onboard soundcard!\n");
else
- printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
- "enabled onboard soundcard.\n");
+ dev_info(&dev->dev, "Detected MSI K8T Neo2-FIR; "
+ "enabled onboard soundcard\n");
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index d3cb3d6af4c..844721e8e3d 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -174,11 +174,6 @@ config PCI
your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
VESA. If you have PCI, say Y, otherwise N.
- The PCI-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't
-
source "drivers/pci/Kconfig"
config HOTPLUG
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index d4590f546c4..7ed279b0a12 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
return -ENOMEM;
/* Perform set up for DMA */
- if (pci_enable_device_bars(pdev, 1<<2)) {
+ if (pci_enable_device_io(pdev)) {
printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
return -ENODEV;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c6179d6ac6e..a70c1c29a7a 100644
--- a/drivers/block/ub.c
+++ b/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,
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) {
/* XXX Clear stalls */
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;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
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) {
/* 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;
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_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) {
/* 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,
(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) {
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,
(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) {
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,
(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)
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,
(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) {
printk(KERN_WARNING
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index e6c4a2b762e..f5e7a70da83 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
iface->pdev = pdev;
iface->bar = bar;
- rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+ rc = pci_enable_device_io(iface->pdev);
if (rc)
goto errout_free;
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 9e01c6dc758..eb68a9ad0c9 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -156,8 +156,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
ide_setup_pci_noise(dev, d);
/* We must not grab the entire device, it has 'ISA' space in its
- BARS too and we will freak out other bits of the kernel */
- if (pci_enable_device_bars(dev, 1<<2)) {
+ * BARS too and we will freak out other bits of the kernel
+ *
+ * pci_enable_device_bars() is going away. I replaced it with
+ * IO only enable for now but I'll need confirmation this is
+ * allright for that device. If not, it will need some kind of
+ * quirk. --BenH.
+ */
+ if (pci_enable_device_io(dev)) {
printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
return -ENODEV;
}
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 8ff5a0ef10a..05db429a7da 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -228,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
* @d: IDE port info
*
* Enable the IDE PCI device. We attempt to enable the device in full
- * but if that fails then we only need BAR4 so we will enable that.
+ * but if that fails then we only need IO space. The PCI code should
+ * have setup the proper resources for us already for controllers in
+ * legacy mode.
*
* Returns zero on success or an error code
*/
@@ -238,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
int ret;
if (pci_enable_device(dev)) {
- ret = pci_enable_device_bars(dev, 1 << 4);
+ ret = pci_enable_device_io(dev);
if (ret < 0) {
printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
"Could not enable device.\n", d->name);
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 9e5ea074ad2..ef5a6a245f5 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -108,6 +108,7 @@ int pci_bus_add_device(struct pci_dev *dev)
void pci_bus_add_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
+ struct pci_bus *child_bus;
int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -138,11 +139,19 @@ void pci_bus_add_devices(struct pci_bus *bus)
up_write(&pci_bus_sem);
}
pci_bus_add_devices(dev->subordinate);
- retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
- &dev->dev.kobj, "bridge");
+
+ /* register the bus with sysfs as the parent is now
+ * properly registered. */
+ child_bus = dev->subordinate;
+ child_bus->dev.parent = child_bus->bridge;
+ retval = device_register(&child_bus->dev);
+ if (!retval)
+ retval = device_create_file(&child_bus->dev,
+ &dev_attr_cpuaffinity);
if (retval)
- dev_err(&dev->dev, "Error creating sysfs "
- "bridge symlink, continuing...\n");
+ dev_err(&dev->dev, "Error registering pci_bus"
+ " device bridge symlink,"
+ " continuing...\n");
}
}
}
@@ -204,7 +213,6 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
}
up_read(&pci_bus_sem);
}
-EXPORT_SYMBOL_GPL(pci_walk_bus);
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 5dfdfdac92e..91b2dc956be 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/dmar.h>
+#include "iova.h"
#undef PREFIX
#define PREFIX "DMAR:"
@@ -263,8 +264,8 @@ parse_dmar_table(void)
if (!dmar)
return -ENODEV;
- if (!dmar->width) {
- printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+ if (dmar->width < PAGE_SHIFT_4K - 1) {
+ printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
return -EINVAL;
}
@@ -301,11 +302,24 @@ parse_dmar_table(void)
int __init dmar_table_init(void)
{
- parse_dmar_table();
+ int ret;
+
+ ret = parse_dmar_table();
+ if (ret) {
+ printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+ return ret;
+ }
+
if (list_empty(&dmar_drhd_units)) {
printk(KERN_INFO PREFIX "No DMAR devices found\n");
return -ENODEV;
}
+
+ if (list_empty(&dmar_rmrr_units)) {
+ printk(KERN_INFO PREFIX "No RMRR found\n");
+ return -ENODEV;
+ }
+
return 0;
}
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index a64449d489d..2cdd8326f13 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -3,8 +3,8 @@
#
menuconfig HOTPLUG_PCI
- tristate "Support for PCI Hotplug (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL && HOTPLUG
+ tristate "Support for PCI Hotplug"
+ depends on PCI && HOTPLUG
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 34a1891191f..9bdbe1a6688 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -3,7 +3,6 @@
#
obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
@@ -16,6 +15,9 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
+# Link this last so it doesn't claim devices that have a real hotplug driver
+obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
+
pci_hotplug-objs := pci_hotplug_core.o
ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 1ef417cca2d..7a29164d4b3 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -113,7 +113,6 @@ struct acpiphp_slot {
u8 device; /* pci device# */
u32 sun; /* ACPI _SUN (slot unique number) */
- u32 slotno; /* slot number relative to bridge */
u32 flags; /* see below */
};
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ff1b1c71291..cf22f9e01e0 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -102,7 +102,7 @@ static int is_ejectable(acpi_handle handle)
}
-/* callback routine to check the existence of ejectable slots */
+/* callback routine to check for the existence of ejectable slots */
static acpi_status
is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
{
@@ -117,7 +117,7 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
}
}
-/* callback routine to check for the existance of a pci dock device */
+/* callback routine to check for the existence of a pci dock device */
static acpi_status
is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
{
@@ -1528,7 +1528,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
dbg("%s: re-enumerating slots under %s\n",
__FUNCTION__, objname);
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
acpiphp_check_bridge(bridge);
}
return AE_OK ;
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index d7a293e3faf..94b640146d4 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include "../pci.h"
#if !defined(MODULE)
@@ -63,10 +64,16 @@ struct dummy_slot {
struct list_head node;
struct hotplug_slot *slot;
struct pci_dev *dev;
+ struct work_struct remove_work;
+ unsigned long removed;
};
static int debug;
static LIST_HEAD(slot_list);
+static struct workqueue_struct *dummyphp_wq;
+
+static void pci_rescan_worker(struct work_struct *work);
+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
static int enable_slot (struct hotplug_slot *slot);
static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
slot->name = &dev->dev.bus_id[0];
dbg("slot->name = %s\n", slot->name);
- dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+ dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
if (!dslot)
goto error_info;
@@ -164,6 +171,14 @@ static void remove_slot(struct dummy_slot *dslot)
err("Problem unregistering a slot %s\n", dslot->slot->name);
}
+/* called from the single-threaded workqueue handler to remove a slot */
+static void remove_slot_worker(struct work_struct *work)
+{
+ struct dummy_slot *dslot =
+ container_of(work, struct dummy_slot, remove_work);
+ remove_slot(dslot);
+}
+
/**
* pci_rescan_slot - Rescan slot
* @temp: Device template. Should be set: bus and devfn.
@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
pci_rescan_buses(&pci_root_buses);
}
+/* called from the single-threaded workqueue handler to rescan all pci buses */
+static void pci_rescan_worker(struct work_struct *work)
+{
+ pci_rescan();
+}
static int enable_slot(struct hotplug_slot *hotplug_slot)
{
/* mis-use enable_slot for rescanning of the pci bus */
- pci_rescan();
+ cancel_work_sync(&pci_rescan_work);
+ queue_work(dummyphp_wq, &pci_rescan_work);
return -ENODEV;
}
@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_slot *slot)
err("Can't remove PCI devices with other PCI devices behind it yet.\n");
return -ENODEV;
}
+ if (test_and_set_bit(0, &dslot->removed)) {
+ dbg("Slot already scheduled for removal\n");
+ return -ENODEV;
+ }
/* search for subfunctions and disable them first */
if (!(dslot->dev->devfn & 7)) {
for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_slot *slot)
/* remove the device from the pci core */
pci_remove_bus_device(dslot->dev);
- /* blow away this sysfs entry and other parts. */
- remove_slot(dslot);
+ /* queue work item to blow away this sysfs entry and other parts. */
+ INIT_WORK(&dslot->remove_work, remove_slot_worker);
+ queue_work(dummyphp_wq, &dslot->remove_work);
return 0;
}
@@ -340,6 +366,7 @@ static void cleanup_slots (void)
struct list_head *next;
struct dummy_slot *dslot;
+ destroy_workqueue(dummyphp_wq);
list_for_each_safe (tmp, next, &slot_list) {
dslot = list_entry (tmp, struct dummy_slot, node);
remove_slot(dslot);
@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
{
info(DRIVER_DESC "\n");
+ dummyphp_wq = create_singlethread_workqueue(MY_NAME);
+ if (!dummyphp_wq)
+ return -ENOMEM;
+
return pci_scan_buses();
}
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index a90c28d0c69..87b6b8b280e 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func)
debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);
for (j = 0; j < 0x08; j++) {
- temp = pci_find_slot(func->busno, (func->device << 3) | j);
- if (temp)
+ temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
+ if (temp) {
pci_remove_bus_device(temp);
+ pci_dev_put(temp);
+ }
}
+ pci_dev_put(func->dev);
}
/*
@@ -823,7 +826,7 @@ static int ibm_configure_device(struct pci_func *func)
if (!(bus_structure_fixup(func->busno)))
flag = 1;
if (func->dev == NULL)
- func->dev = pci_find_slot(func->busno,
+ func->dev = pci_get_bus_and_slot(func->busno,
PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
@@ -836,7 +839,7 @@ static int ibm_configure_device(struct pci_func *func)
if (num)
pci_bus_add_devices(bus);
- func->dev = pci_find_slot(func->busno,
+ func->dev = pci_get_bus_and_slot(func->busno,
PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
err("ERROR... : pci_dev still NULL\n");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 47bb0e1ff3f..dd59a050260 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -137,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
int retval = 0; \
if (try_module_get(ops->owner)) { \
if (ops->get_##name) \
- retval = ops->get_##name (slot, value); \
+ retval = ops->get_##name(slot, value); \
else \
*value = slot->info->name; \
module_put(ops->owner); \
@@ -625,7 +625,7 @@ int pci_hp_register (struct hotplug_slot *slot)
if ((slot->info == NULL) || (slot->ops == NULL))
return -EINVAL;
if (slot->release == NULL) {
- dbg("Why are you trying to register a hotplug slot"
+ dbg("Why are you trying to register a hotplug slot "
"without a proper release function?\n");
return -EINVAL;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 7959c222dc2..ca656b27a50 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -82,24 +82,18 @@ struct event_info {
};
struct controller {
- struct controller *next;
struct mutex crit_sect; /* critical section mutex */
struct mutex ctrl_lock; /* controller lock */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev;
struct list_head slot_list;
- struct slot *slot;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
- u8 bus;
- u8 device;
- u8 function;
u8 slot_device_offset;
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 ctrlcap;
- u16 vendor_id;
u8 cap_base;
struct timer_list poll_timer;
volatile int cmd_busy;
@@ -161,6 +155,9 @@ extern int pciehp_configure_device(struct slot *p_slot);
extern int pciehp_unconfigure_device(struct slot *p_slot);
extern void pciehp_queue_pushbutton_work(struct work_struct *work);
int pcie_init(struct controller *ctrl, struct pcie_device *dev);
+int pciehp_enable_slot(struct slot *p_slot);
+int pciehp_disable_slot(struct slot *p_slot);
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 6462ac3b405..7f4836b8e71 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
pci_set_drvdata(pdev, ctrl);
- ctrl->bus = pdev->bus->number; /* ctrl bus */
- ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */
-
- ctrl->device = PCI_SLOT(pdev->devfn);
- ctrl->function = PCI_FUNC(pdev->devfn);
- dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
- ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+ dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+ __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
/* Setup the slot information structures */
rc = init_slots(ctrl);
@@ -471,6 +467,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+ if (value) {
+ rc = pciehp_enable_slot(t_slot);
+ if (rc) /* -ENODEV: shouldn't happen, but deal with it */
+ value = 0;
+ }
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
if (rc)
@@ -509,6 +510,24 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
static int pciehp_resume (struct pcie_device *dev)
{
printk("%s ENTRY\n", __FUNCTION__);
+ if (pciehp_force) {
+ struct pci_dev *pdev = dev->port;
+ struct controller *ctrl = pci_get_drvdata(pdev);
+ struct slot *t_slot;
+ u8 status;
+
+ /* reinitialize the chipset's event detection logic */
+ pcie_init_hardware_part2(ctrl, dev);
+
+ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+
+ /* Check if slot is occupied */
+ t_slot->hpc_ops->get_adapter_status(t_slot, &status);
+ if (status)
+ pciehp_enable_slot(t_slot);
+ else
+ pciehp_disable_slot(t_slot);
+ }
return 0;
}
#endif
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f1e0966cee9..b23061c5611 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -37,8 +37,6 @@
#include "pciehp.h"
static void interrupt_event_handler(struct work_struct *work);
-static int pciehp_enable_slot(struct slot *p_slot);
-static int pciehp_disable_slot(struct slot *p_slot);
static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
{
@@ -197,12 +195,6 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
__FUNCTION__);
return;
}
- /*
- * After turning power off, we must wait for at least
- * 1 second before taking any action that relies on
- * power having been removed from the slot/adapter.
- */
- msleep(1000);
}
}
@@ -215,15 +207,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
*/
static int board_added(struct slot *p_slot)
{
- u8 hp_slot;
int retval = 0;
struct controller *ctrl = p_slot->ctrl;
- hp_slot = p_slot->device - ctrl->slot_device_offset;
-
dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
__FUNCTION__, p_slot->device,
- ctrl->slot_device_offset, hp_slot);
+ ctrl->slot_device_offset, p_slot->hp_slot);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* Power on slot */
@@ -281,8 +270,6 @@ err_exit:
*/
static int remove_board(struct slot *p_slot)
{
- u8 device;
- u8 hp_slot;
int retval = 0;
struct controller *ctrl = p_slot->ctrl;
@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
if (retval)
return retval;
- device = p_slot->device;
- hp_slot = p_slot->device - ctrl->slot_device_offset;
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
- dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+ dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* power off slot */
@@ -621,12 +604,6 @@ int pciehp_disable_slot(struct slot *p_slot)
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
- /*
- * After turning power off, we must wait for at least
- * 1 second before taking any action that relies on
- * power having been removed from the slot/adapter.
- */
- msleep(1000);
}
ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 06d025b8b13..6eba9b2cfb9 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
return retval;
}
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+ struct pci_dev *dev = ctrl->pci_dev;
+ int pos;
+ u32 reg;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return 0;
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+ if (reg & PCI_ERR_COR_BAD_DLLP)
+ return 0;
+ reg |= PCI_ERR_COR_BAD_DLLP;
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+ return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+ struct pci_dev *dev = ctrl->pci_dev;
+ u32 reg;
+ int pos;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return;
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+ if (!(reg & PCI_ERR_COR_BAD_DLLP))
+ return;
+ reg &= ~PCI_ERR_COR_BAD_DLLP;
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
static int hpc_power_off_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
u16 cmd_mask;
int retval = 0;
+ int changed;
dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+ /*
+ * Set Bad DLLP Mask bit in Correctable Error Mask
+ * Register. This is the workaround against Bad DLLP error
+ * that sometimes happens during turning power off the slot
+ * which conforms to PCI Express 1.0a spec.
+ */
+ changed = pcie_mask_bad_dllp(ctrl);
+
slot_cmd = POWER_OFF;
cmd_mask = PWR_CTRL;
/*
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot)
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
+
+ if (changed)
+ pcie_unmask_bad_dllp(ctrl);
+
return retval;
}
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
}
#endif
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+static int pcie_init_hardware_part1(struct controller *ctrl,
+ struct pcie_device *dev)
+{
+ int rc;
+ u16 temp_word;
+ u32 slot_cap;
+ u16 slot_status;
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+ err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Mask Hot-plug Interrupt Enable */
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+ return -1;
+ }
+
+ dbg("%s: SLOTCTRL %x value read %x\n",
+ __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+ 0x00;
+
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+ return -1;
+ }
+
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+ return -1;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
{
int rc;
u16 temp_word;
- u16 cap_reg;
u16 intr_enable = 0;
u32 slot_cap;
+ u16 slot_status;
+
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+ goto abort;
+ }
+
+ intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+ err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+ goto abort;
+ }
+
+ if (ATTN_BUTTN(slot_cap))
+ intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+
+ if (POWER_CTRL(slot_cap))
+ intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+
+ if (MRL_SENS(slot_cap))
+ intr_enable = intr_enable | MRL_DETECT_ENABLE;
+
+ temp_word = (temp_word & ~intr_enable) | intr_enable;
+
+ if (pciehp_poll_mode) {
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+ } else {
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+ }
+
+ /*
+ * Unmask Hot-plug Interrupt Enable for the interrupt
+ * notification mechanism case.
+ */
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+ goto abort;
+ }
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+ goto abort_disable_intr;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+ goto abort_disable_intr;
+ }
+
+ if (pciehp_force) {
+ dbg("Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(ctrl->pci_dev));
+ } else {
+ rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+ if (rc)
+ goto abort_disable_intr;
+ }
+
+ return 0;
+
+ /* We end up here for the many possible ways to fail this API. */
+abort_disable_intr:
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (!rc) {
+ temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ }
+ if (rc)
+ err("%s : disabling interrupts failed\n", __FUNCTION__);
+abort:
+ return -1;
+}
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+ int rc;
+ u16 cap_reg;
+ u32 slot_cap;
int cap_base;
u16 slot_status, slot_ctrl;
struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
__FUNCTION__, pdev->vendor, pdev->device);
- if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+ cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (cap_base == 0) {
dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
if (rc) {
err("%s: Cannot read CAPREG register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: CAPREG offset %x cap_reg %x\n",
__FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
dbg("%s : This is not a root port or the port is not "
"connected to a slot\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
if (rc) {
err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTCAP offset %x slot_cap %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
if (!(slot_cap & HP_CAP)) {
dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
/* For debugging purpose */
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
__FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (rc) {
err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
ctrl->first_slot = slot_cap >> 19;
ctrl->ctrlcap = slot_cap & 0x0000007f;
- /* Mask Hot-plug Interrupt Enable */
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- dbg("%s: SLOTCTRL %x value read %x\n",
- __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
- temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
- 0x00;
-
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- temp_word = 0x1F; /* Clear all events */
- rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
+ rc = pcie_init_hardware_part1(ctrl, dev);
+ if (rc)
+ goto abort;
if (pciehp_poll_mode) {
/* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
if (rc) {
err("Can't get irq %d for the hotplug controller\n",
ctrl->pci_dev->irq);
- goto abort_free_ctlr;
+ goto abort;
}
}
dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
}
}
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_irq;
+ rc = pcie_init_hardware_part2(ctrl, dev);
+ if (rc == 0) {
+ ctrl->hpc_ops = &pciehp_hpc_ops;
+ return 0;
}
-
- intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
- if (ATTN_BUTTN(slot_cap))
- intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
- if (POWER_CTRL(slot_cap))
- intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
- if (MRL_SENS(slot_cap))
- intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
- temp_word = (temp_word & ~intr_enable) | intr_enable;
-
- if (pciehp_poll_mode) {
- temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
- } else {
- temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
- }
-
- /*
- * Unmask Hot-plug Interrupt Enable for the interrupt
- * notification mechanism case.
- */
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_irq;
- }
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_disable_intr;
- }
-
- temp_word = 0x1F; /* Clear all events */
- rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
- goto abort_disable_intr;
- }
-
- if (pciehp_force) {
- dbg("Bypassing BIOS check for pciehp use on %s\n",
- pci_name(ctrl->pci_dev));
- } else {
- rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
- if (rc)
- goto abort_disable_intr;
- }
-
- ctrl->hpc_ops = &pciehp_hpc_ops;
-
- return 0;
-
- /* We end up here for the many possible ways to fail this API. */
-abort_disable_intr:
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (!rc) {
- temp_word &= ~(intr_enable | HP_INTR_ENABLE);
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- }
- if (rc)
- err("%s : disabling interrupts failed\n", __FUNCTION__);
-
abort_free_irq:
if (pciehp_poll_mode)
del_timer_sync(&ctrl->poll_timer);
else
free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
return -1;
}
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index c424aded13f..dd50713966d 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
}
/* Find Advanced Error Reporting Enhanced Capability */
- pos = 256;
- do {
- pci_read_config_dword(dev, pos, &reg32);
- if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
- break;
- } while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return;
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
u8 bctl = 0;
u8 presence = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ u16 command;
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
p_slot->device);
+ ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+ if (ret)
+ presence = 0;
- for (j=0; j<8 ; j++) {
+ for (j = 0; j < 8; j++) {
struct pci_dev* temp = pci_get_slot(parent,
(p_slot->device << 3) | j);
if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
pci_dev_put(temp);
continue;
}
- if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- ret = p_slot->hpc_ops->get_adapter_status(p_slot,
- &presence);
- if (!ret && presence) {
- pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
- &bctl);
- if (bctl & PCI_BRIDGE_CTL_VGA) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
- pci_dev_put(temp);
- continue;
- }
+ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ if (bctl & PCI_BRIDGE_CTL_VGA) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ pci_dev_put(temp);
+ continue;
}
}
pci_remove_bus_device(temp);
+ /*
+ * Ensure that no new Requests will be generated from
+ * the device.
+ */
+ if (presence) {
+ pci_read_config_word(temp, PCI_COMMAND, &command);
+ command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+ command |= PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(temp, PCI_COMMAND, command);
+ }
pci_dev_put(temp);
}
/*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
return rc;
}
-
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index c822a779653..7d5921b1ee7 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -74,7 +74,6 @@ struct slot {
u32 type;
u32 power_domain;
char *name;
- char *location;
struct device_node *dn;
struct pci_bus *bus;
struct list_head *pci_devs;
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 0de84533cd8..6571e9b4c2e 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,19 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
return rc;
}
-static void set_slot_name(struct slot *slot)
-{
- struct pci_bus *bus = slot->bus;
- struct pci_dev *bridge;
-
- bridge = bus->self;
- if (bridge)
- strcpy(slot->name, pci_name(bridge));
- else
- sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
- bus->number);
-}
-
/**
* rpaphp_enable_slot - record slot state, config pci device
* @slot: target &slot
@@ -115,7 +102,6 @@ int rpaphp_enable_slot(struct slot *slot)
info->adapter_status = EMPTY;
slot->bus = bus;
slot->pci_devs = &bus->devices;
- set_slot_name(slot);
/* if there's an adapter in the slot, go add the pci devices */
if (state == PRESENT) {
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index d4ee8723fcb..8ad3debb379 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -33,23 +33,31 @@
#include <asm/rtas.h>
#include "rpaphp.h"
-static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
+static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
{
- char *value;
- int retval = -ENOENT;
+ int retval;
struct slot *slot = (struct slot *)php_slot->private;
+ struct pci_bus *bus;
if (!slot)
- return retval;
+ return -ENOENT;
+
+ bus = slot->bus;
+ if (!bus)
+ return -ENOENT;
+
+ if (bus->self)
+ retval = sprintf(buf, pci_name(bus->self));
+ else
+ retval = sprintf(buf, "%04x:%02x:00.0",
+ pci_domain_nr(bus), bus->number);
- value = slot->location;
- retval = sprintf (buf, "%s\n", value);
return retval;
}
-static struct hotplug_slot_attribute php_attr_location = {
- .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
- .show = location_read_file,
+static struct hotplug_slot_attribute php_attr_address = {
+ .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
+ .show = address_read_file,
};
/* free up the memory used by a slot */
@@ -64,7 +72,6 @@ void dealloc_slot_struct(struct slot *slot)
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
- kfree(slot->location);
kfree(slot);
}
@@ -83,16 +90,13 @@ struct slot *alloc_slot_struct(struct device_node *dn,
GFP_KERNEL);
if (!slot->hotplug_slot->info)
goto error_hpslot;
- slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
+ slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
if (!slot->hotplug_slot->name)
goto error_info;
- slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
- if (!slot->location)
- goto error_name;
slot->name = slot->hotplug_slot->name;
+ strcpy(slot->name, drc_name);
slot->dn = dn;
slot->index = drc_index;
- strcpy(slot->location, drc_name);
slot->power_domain = power_domain;
slot->hotplug_slot->private = slot;
slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
return (slot);
-error_name:
- kfree(slot->hotplug_slot->name);
error_info:
kfree(slot->hotplug_slot->info);
error_hpslot:
@@ -133,8 +135,8 @@ int rpaphp_deregister_slot(struct slot *slot)
list_del(&slot->rpaphp_slot_list);
- /* remove "phy_location" file */
- sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
+ /* remove "address" file */
+ sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
retval = pci_hp_deregister(php_slot);
if (retval)
@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
return retval;
}
- /* create "phy_location" file */
- retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+ /* create "address" file */
+ retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
if (retval) {
err("sysfs_create_file failed with error %d\n", retval);
goto sysfs_fail;
@@ -175,8 +177,7 @@ int rpaphp_register_slot(struct slot *slot)
/* add slot to our internal list */
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
- info("Slot [%s](PCI location=%s) registered\n", slot->name,
- slot->location);
+ info("Slot [%s] registered\n", slot->name);
return 0;
sysfs_fail:
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 5183a45d45b..e8aa138128c 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
cleanup_slots(ctrl);
/*
- * Mask SERR and System Interrut generation
+ * Mask SERR and System Interrupt generation
*/
serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index e079a5237c9..4e01df99681 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1781,7 +1781,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
/*
* First try to allocate an io virtual address in
* DMA_32BIT_MASK and if that fails then try allocating
- * from higer range
+ * from higher range
*/
iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
if (!iova)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 07c9f09c856..26938da8f43 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -25,6 +25,51 @@
static int pci_msi_enable = 1;
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+ return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+ return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ struct msi_desc *entry;
+ int ret;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ ret = arch_setup_msi_irq(dev, entry);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+ return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+ struct msi_desc *entry;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (entry->irq != 0)
+ arch_teardown_msi_irq(entry->irq);
+ }
+}
+
static void msi_set_enable(struct pci_dev *dev, int enable)
{
int pos;
@@ -230,7 +275,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable)
pci_intx(dev, enable);
}
-#ifdef CONFIG_PM
static void __pci_restore_msi_state(struct pci_dev *dev)
{
int pos;
@@ -288,7 +332,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
__pci_restore_msi_state(dev);
__pci_restore_msix_state(dev);
}
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
/**
* msi_capability_init - configure device's MSI capability structure
@@ -683,49 +727,3 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
{
INIT_LIST_HEAD(&dev->msi_list);
}
-
-
-/* Arch hooks */
-
-int __attribute__ ((weak))
-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
-{
- return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
-{
- return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
- struct msi_desc *entry;
- int ret;
-
- list_for_each_entry(entry, &dev->msi_list, list) {
- ret = arch_setup_msi_irq(dev, entry);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
-{
- return;
-}
-
-void __attribute__ ((weak))
-arch_teardown_msi_irqs(struct pci_dev *dev)
-{
- struct msi_desc *entry;
-
- list_for_each_entry(entry, &dev->msi_list, list) {
- if (entry->irq != 0)
- arch_teardown_msi_irq(entry->irq);
- }
-}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 5c6a5d04300..e569645d59e 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -156,13 +156,13 @@ run_osc_out:
}
/**
- * pci_osc_support_set - register OS support to Firmware
+ * __pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
*
* Update OS support fields and doing a _OSC Query to obtain an update
* from Firmware on supported control bits.
**/
-acpi_status pci_osc_support_set(u32 flags)
+acpi_status __pci_osc_support_set(u32 flags, const char *hid)
{
u32 temp;
acpi_status retval;
@@ -176,7 +176,7 @@ acpi_status pci_osc_support_set(u32 flags)
temp = ctrlset_buf[OSC_CONTROL_TYPE];
ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
- acpi_get_devices ( PCI_ROOT_HID_STRING,
+ acpi_get_devices(hid,
acpi_query_osc,
ctrlset_buf,
(void **) &retval );
@@ -188,7 +188,6 @@ acpi_status pci_osc_support_set(u32 flags)
}
return AE_OK;
}
-EXPORT_SYMBOL(pci_osc_support_set);
/**
* pci_osc_control_set - commit requested control to Firmware
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index c4fa35d1dd7..e571c72e675 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -186,13 +186,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
set_cpus_allowed(current, node_to_cpumask(node));
/* And set default memory allocation policy */
oldpol = current->mempolicy;
- current->mempolicy = &default_policy;
- mpol_get(current->mempolicy);
+ current->mempolicy = NULL; /* fall back to system default policy */
#endif
error = drv->probe(dev, id);
#ifdef CONFIG_NUMA
set_cpus_allowed(current, oldmask);
- mpol_free(current->mempolicy);
current->mempolicy = oldpol;
#endif
return error;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7d1877341aa..abf4203304e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -21,6 +21,7 @@
#include <linux/topology.h>
#include <linux/mm.h>
#include <linux/capability.h>
+#include <linux/aspm.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
@@ -358,7 +359,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
/* Only support 1, 2 or 4 byte accesses */
@@ -383,7 +384,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
/* Only support 1, 2 or 4 byte accesses */
if (count != 1 && count != 2 && count != 4)
@@ -407,7 +408,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
return pci_mmap_legacy_page_range(bus, vma);
@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
if (pcibios_add_platform_entries(pdev))
goto err_rom_file;
+ pcie_aspm_create_sysfs_dev_files(pdev);
+
return 0;
err_rom_file:
@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
if (!sysfs_initialized)
return;
+ pcie_aspm_remove_sysfs_dev_files(pdev);
+
if (pdev->cfg_size < 4096)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7d4ce906d20..b3e9294e4a0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/log2.h>
+#include <linux/aspm.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
}
EXPORT_SYMBOL_GPL(pci_find_ht_capability);
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+ int pos;
+ u16 reg16;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ while (1) {
+ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+ if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+ break;
+ cpu_relax();
+ }
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
/**
* pci_find_parent_resource - return resource region of parent bus of given region
* @dev: PCI device structure contains resources to be searched
@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
* Restore the BAR values for a given device, so as to make it
* accessible by its driver.
*/
-void
+static void
pci_restore_bars(struct pci_dev *dev)
{
int i, numres;
@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if (need_restore)
pci_restore_bars(dev);
+ if (dev->bus->self)
+ pcie_aspm_pm_state_change(dev->bus->self);
+
return 0;
}
@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (pos <= 0)
@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
if (!save_state)
save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+ else
+ found = 1;
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
- pci_add_saved_cap(dev, save_state);
+ save_state->cap_nr = PCI_CAP_ID_EXP;
+ if (!found)
+ pci_add_saved_cap(dev, save_state);
return 0;
}
@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (pos <= 0)
return 0;
- save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
if (!save_state)
save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+ else
+ found = 1;
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
cap = (u16 *)&save_state->data[0];
pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
- pci_add_saved_cap(dev, save_state);
+ save_state->cap_nr = PCI_CAP_ID_PCIX;
+ if (!found)
+ pci_add_saved_cap(dev, save_state);
return 0;
}
@@ -713,23 +745,19 @@ int pci_reenable_device(struct pci_dev *dev)
return 0;
}
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- * Initialize device before it's used by a driver. Ask low-level code
- * to enable selected I/O and memory resources. Wake up the device if it
- * was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+ resource_size_t flags)
{
int err;
+ int i, bars = 0;
if (atomic_add_return(1, &dev->enable_cnt) > 1)
return 0; /* already enabled */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ if (dev->resource[i].flags & flags)
+ bars |= (1 << i);
+
err = do_pci_enable_device(dev, bars);
if (err < 0)
atomic_dec(&dev->enable_cnt);
@@ -737,6 +765,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
}
/**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable I/O resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+ return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable Memory resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+ return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
+/**
* pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
*
@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
*/
int pci_enable_device(struct pci_dev *dev)
{
- return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+ return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
/*
@@ -885,6 +939,9 @@ pci_disable_device(struct pci_dev *dev)
if (atomic_sub_return(1, &dev->enable_cnt) != 0)
return;
+ /* Wait for all transactions are finished before disabling the device */
+ pcie_wait_pending_transaction(dev);
+
pci_read_config_word(dev, PCI_COMMAND, &pci_command);
if (pci_command & PCI_COMMAND_MASTER) {
pci_command &= ~PCI_COMMAND_MASTER;
@@ -1619,9 +1676,9 @@ early_param("pci", pci_setup);
device_initcall(pci_init);
-EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pcim_enable_device);
EXPORT_SYMBOL(pcim_pin_device);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fc87e14b50d..eabeb1f2ec9 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -6,8 +6,10 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
/* Firmware callbacks */
-extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
-extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
+ pm_message_t state);
+extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
+ pci_power_t state);
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -45,12 +47,6 @@ static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
#endif
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
#ifdef CONFIG_PCIEAER
void pci_no_aer(void);
#else
@@ -68,14 +64,14 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
}
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
-extern struct class_device_attribute class_device_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpuaffinity;
/**
* pci_match_one_device - Tell if a PCI device structure has a matching
* PCI device id structure
* @id: single PCI device id structure to match
* @dev: the PCI device structure to match against
- *
+ *
* Returns the matching pci_device_id structure or %NULL if there is no match.
*/
static inline const struct pci_device_id *
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 287a9311716..60104cf9879 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
When in doubt, say N.
source "drivers/pci/pcie/aer/Kconfig"
+
+#
+# PCI Express ASPM
+#
+config PCIEASPM
+ bool "PCI Express ASPM support(Experimental)"
+ depends on PCI && EXPERIMENTAL
+ default y
+ help
+ This enables PCI Express ASPM (Active State Power Management) and
+ Clock Power Management. ASPM supports state L0/L0s/L1.
+
+ When in doubt, say N.
+config PCIEASPM_DEBUG
+ bool "Debug PCI Express ASPM"
+ depends on PCIEASPM
+ default n
+ help
+ This enables PCI Express ASPM debug support. It will add per-device
+ interface to control ASPM.
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index e00fb99acf4..11f6bb1eae2 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -2,6 +2,9 @@
# Makefile for PCI-Express PORT Driver
#
+# Build PCI Express ASPM if needed
+obj-$(CONFIG_PCIEASPM) += aspm.o
+
pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 1a1eb45a779..8c199ae84f6 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -31,26 +31,16 @@ int aer_osc_setup(struct pcie_device *pciedev)
{
acpi_status status = AE_NOT_FOUND;
struct pci_dev *pdev = pciedev->port;
- acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
- struct pci_bus *parent;
+ acpi_handle handle = 0;
- while (!handle) {
- if (!pdev || !pdev->bus->parent)
- break;
- parent = pdev->bus->parent;
- if (!parent->self)
- /* Parent must be a host bridge */
- handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(parent),
- parent->number);
- else
- handle = DEVICE_ACPI_HANDLE(
- &(parent->self->dev));
- pdev = parent->self;
- }
+ /* Find root host bridge */
+ while (pdev->bus && pdev->bus->self)
+ pdev = pdev->bus->self;
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(pdev->bus), pdev->bus->number);
if (handle) {
- pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+ pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
status = pci_osc_control_set(handle,
OSC_PCI_EXPRESS_AER_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
new file mode 100644
index 00000000000..1a5adeb10c9
--- /dev/null
+++ b/drivers/pci/pcie/aspm.c
@@ -0,0 +1,802 @@
+/*
+ * File: drivers/pci/pcie/aspm.c
+ * Enabling PCIE link L0s/L1 state and Clock Power Management
+ *
+ * Copyright (C) 2007 Intel
+ * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
+ * Copyright (C) Shaohua Li (shaohua.li@intel.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/aspm.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci-acpi.h>
+#include "../pci.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "pcie_aspm."
+
+struct endpoint_state {
+ unsigned int l0s_acceptable_latency;
+ unsigned int l1_acceptable_latency;
+};
+
+struct pcie_link_state {
+ struct list_head sibiling;
+ struct pci_dev *pdev;
+
+ /* ASPM state */
+ unsigned int support_state;
+ unsigned int enabled_state;
+ unsigned int bios_aspm_state;
+ /* upstream component */
+ unsigned int l0s_upper_latency;
+ unsigned int l1_upper_latency;
+ /* downstream component */
+ unsigned int l0s_down_latency;
+ unsigned int l1_down_latency;
+ /* Clock PM state*/
+ unsigned int clk_pm_capable;
+ unsigned int clk_pm_enabled;
+ unsigned int bios_clk_state;
+
+ /*
+ * A pcie downstream port only has one slot under it, so at most there
+ * are 8 functions
+ */
+ struct endpoint_state endpoints[8];
+};
+
+static int aspm_disabled;
+static DEFINE_MUTEX(aspm_lock);
+static LIST_HEAD(link_list);
+
+#define POLICY_DEFAULT 0 /* BIOS default setting */
+#define POLICY_PERFORMANCE 1 /* high performance */
+#define POLICY_POWERSAVE 2 /* high power saving */
+static int aspm_policy;
+static const char *policy_str[] = {
+ [POLICY_DEFAULT] = "default",
+ [POLICY_PERFORMANCE] = "performance",
+ [POLICY_POWERSAVE] = "powersave"
+};
+
+static int policy_to_aspm_state(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ switch (aspm_policy) {
+ case POLICY_PERFORMANCE:
+ /* Disable ASPM and Clock PM */
+ return 0;
+ case POLICY_POWERSAVE:
+ /* Enable ASPM L0s/L1 */
+ return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+ case POLICY_DEFAULT:
+ return link_state->bios_aspm_state;
+ }
+ return 0;
+}
+
+static int policy_to_clkpm_state(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ switch (aspm_policy) {
+ case POLICY_PERFORMANCE:
+ /* Disable ASPM and Clock PM */
+ return 0;
+ case POLICY_POWERSAVE:
+ /* Disable Clock PM */
+ return 1;
+ case POLICY_DEFAULT:
+ return link_state->bios_clk_state;
+ }
+ return 0;
+}
+
+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+{
+ struct pci_dev *child_dev;
+ int pos;
+ u16 reg16;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (enable)
+ reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+ }
+ link_state->clk_pm_enabled = !!enable;
+}
+
+static void pcie_check_clock_pm(struct pci_dev *pdev)
+{
+ int pos;
+ u32 reg32;
+ u16 reg16;
+ int capable = 1, enabled = 1;
+ struct pci_dev *child_dev;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /* All functions should have the same cap and state, take the worst */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+ if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
+ capable = 0;
+ enabled = 0;
+ break;
+ }
+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
+ enabled = 0;
+ }
+ link_state->clk_pm_capable = capable;
+ link_state->clk_pm_enabled = enabled;
+ link_state->bios_clk_state = enabled;
+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+}
+
+/*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ * could use common clock. If they are, configure them to use the
+ * common clock. That will reduce the ASPM state exit latency.
+ */
+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+{
+ int pos, child_pos;
+ u16 reg16 = 0;
+ struct pci_dev *child_dev;
+ int same_clock = 1;
+
+ /*
+ * all functions of a slot should have the same Slot Clock
+ * Configuration, so just check one function
+ * */
+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+ bus_list);
+ BUG_ON(!child_dev->is_pcie);
+
+ /* Check downstream component if bit Slot Clock Configuration is 1 */
+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+ same_clock = 0;
+
+ /* Check upstream component if bit Slot Clock Configuration is 1 */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+ same_clock = 0;
+
+ /* Configure downstream component, all functions */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+ &reg16);
+ if (same_clock)
+ reg16 |= PCI_EXP_LNKCTL_CCC;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
+ pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+ reg16);
+ }
+
+ /* Configure upstream component */
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (same_clock)
+ reg16 |= PCI_EXP_LNKCTL_CCC;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+ /* retrain link */
+ reg16 |= PCI_EXP_LNKCTL_RL;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+ /* Wait for link training end */
+ while (1) {
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_LT))
+ break;
+ cpu_relax();
+ }
+}
+
+/*
+ * calc_L0S_latency: Convert L0s latency encoding to ns
+ */
+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+{
+ unsigned int ns = 64;
+
+ if (latency_encoding == 0x7) {
+ if (ac)
+ ns = -1U;
+ else
+ ns = 5*1000; /* > 4us */
+ } else
+ ns *= (1 << latency_encoding);
+ return ns;
+}
+
+/*
+ * calc_L1_latency: Convert L1 latency encoding to ns
+ */
+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+{
+ unsigned int ns = 1000;
+
+ if (latency_encoding == 0x7) {
+ if (ac)
+ ns = -1U;
+ else
+ ns = 65*1000; /* > 64us */
+ } else
+ ns *= (1 << latency_encoding);
+ return ns;
+}
+
+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
+ unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+{
+ int pos;
+ u16 reg16;
+ u32 reg32;
+ unsigned int latency;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+ *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
+ if (*state != PCIE_LINK_STATE_L0S &&
+ *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+ * state = 0;
+ if (*state == 0)
+ return;
+
+ latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+ *l0s = calc_L0S_latency(latency, 0);
+ if (*state & PCIE_LINK_STATE_L1) {
+ latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+ *l1 = calc_L1_latency(latency, 0);
+ }
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+}
+
+static void pcie_aspm_cap_init(struct pci_dev *pdev)
+{
+ struct pci_dev *child_dev;
+ u32 state, tmp;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /* upstream component states */
+ pcie_aspm_get_cap_device(pdev, &link_state->support_state,
+ &link_state->l0s_upper_latency,
+ &link_state->l1_upper_latency,
+ &link_state->enabled_state);
+ /* downstream component states, all functions have the same setting */
+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+ bus_list);
+ pcie_aspm_get_cap_device(child_dev, &state,
+ &link_state->l0s_down_latency,
+ &link_state->l1_down_latency,
+ &tmp);
+ link_state->support_state &= state;
+ if (!link_state->support_state)
+ return;
+ link_state->enabled_state &= link_state->support_state;
+ link_state->bios_aspm_state = link_state->enabled_state;
+
+ /* ENDPOINT states*/
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ int pos;
+ u32 reg32;
+ unsigned int latency;
+ struct endpoint_state *ep_state =
+ &link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+
+ if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+ continue;
+
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
+ latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+ latency = calc_L0S_latency(latency, 1);
+ ep_state->l0s_acceptable_latency = latency;
+ if (link_state->support_state & PCIE_LINK_STATE_L1) {
+ latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+ latency = calc_L1_latency(latency, 1);
+ ep_state->l1_acceptable_latency = latency;
+ }
+ }
+}
+
+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pci_dev *parent_dev, *tmp_dev;
+ unsigned int latency, l1_latency = 0;
+ struct pcie_link_state *link_state;
+ struct endpoint_state *ep_state;
+
+ parent_dev = pdev->bus->self;
+ link_state = parent_dev->link_state;
+ state &= link_state->support_state;
+ if (state == 0)
+ return 0;
+ ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
+
+ /*
+ * Check latency for endpoint device.
+ * TBD: The latency from the endpoint to root complex vary per
+ * switch's upstream link state above the device. Here we just do a
+ * simple check which assumes all links above the device can be in L1
+ * state, that is we just consider the worst case. If switch's upstream
+ * link can't be put into L0S/L1, then our check is too strictly.
+ */
+ tmp_dev = pdev;
+ while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+ parent_dev = tmp_dev->bus->self;
+ link_state = parent_dev->link_state;
+ if (state & PCIE_LINK_STATE_L0S) {
+ latency = max_t(unsigned int,
+ link_state->l0s_upper_latency,
+ link_state->l0s_down_latency);
+ if (latency > ep_state->l0s_acceptable_latency)
+ state &= ~PCIE_LINK_STATE_L0S;
+ }
+ if (state & PCIE_LINK_STATE_L1) {
+ latency = max_t(unsigned int,
+ link_state->l1_upper_latency,
+ link_state->l1_down_latency);
+ if (latency + l1_latency >
+ ep_state->l1_acceptable_latency)
+ state &= ~PCIE_LINK_STATE_L1;
+ }
+ if (!parent_dev->bus->self) /* parent_dev is a root port */
+ break;
+ else {
+ /*
+ * parent_dev is the downstream port of a switch, make
+ * tmp_dev the upstream port of the switch
+ */
+ tmp_dev = parent_dev->bus->self;
+ /*
+ * every switch on the path to root complex need 1 more
+ * microsecond for L1. Spec doesn't mention L0S.
+ */
+ if (state & PCIE_LINK_STATE_L1)
+ l1_latency += 1000;
+ }
+ }
+ return state;
+}
+
+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pci_dev *child_dev;
+
+ /* If no child, disable the link */
+ if (list_empty(&pdev->subordinate->devices))
+ return 0;
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+ /*
+ * If downstream component of a link is pci bridge, we
+ * disable ASPM for now for the link
+ * */
+ state = 0;
+ break;
+ }
+ if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+ continue;
+ /* Device not in D0 doesn't need check latency */
+ if (child_dev->current_state == PCI_D1 ||
+ child_dev->current_state == PCI_D2 ||
+ child_dev->current_state == PCI_D3hot ||
+ child_dev->current_state == PCI_D3cold)
+ continue;
+ state = __pcie_aspm_check_state_one(child_dev, state);
+ }
+ return state;
+}
+
+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
+{
+ u16 reg16;
+ int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ reg16 &= ~0x3;
+ reg16 |= state;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+}
+
+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+{
+ struct pci_dev *child_dev;
+ int valid = 1;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /*
+ * if the downstream component has pci bridge function, don't do ASPM
+ * now
+ */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+ valid = 0;
+ break;
+ }
+ }
+ if (!valid)
+ return;
+
+ /*
+ * spec 2.0 suggests all functions should be configured the same
+ * setting for ASPM. Enabling ASPM L1 should be done in upstream
+ * component first and then downstream, and vice versa for disabling
+ * ASPM L1. Spec doesn't mention L0S.
+ */
+ if (state & PCIE_LINK_STATE_L1)
+ __pcie_aspm_config_one_dev(pdev, state);
+
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
+ __pcie_aspm_config_one_dev(child_dev, state);
+
+ if (!(state & PCIE_LINK_STATE_L1))
+ __pcie_aspm_config_one_dev(pdev, state);
+
+ link_state->enabled_state = state;
+}
+
+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (link_state->support_state == 0)
+ return;
+ state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+
+ /* state 0 means disabling aspm */
+ state = pcie_aspm_check_state(pdev, state);
+ if (link_state->enabled_state == state)
+ return;
+ __pcie_aspm_config_link(pdev, state);
+}
+
+/*
+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
+ * @pdev: the root port or switch downstream port
+ */
+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ __pcie_aspm_configure_link_state(pdev, state);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+
+static void free_link_state(struct pci_dev *pdev)
+{
+ kfree(pdev->link_state);
+ pdev->link_state = NULL;
+}
+
+/*
+ * pcie_aspm_init_link_state: Initiate PCI express link state.
+ * It is called after the pcie and its children devices are scaned.
+ * @pdev: the root port or switch downstream port
+ */
+void pcie_aspm_init_link_state(struct pci_dev *pdev)
+{
+ unsigned int state;
+ struct pcie_link_state *link_state;
+ int error = 0;
+
+ if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+ return;
+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ down_read(&pci_bus_sem);
+ if (list_empty(&pdev->subordinate->devices))
+ goto out;
+
+ mutex_lock(&aspm_lock);
+
+ link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
+ if (!link_state)
+ goto unlock_out;
+ pdev->link_state = link_state;
+
+ pcie_aspm_configure_common_clock(pdev);
+
+ pcie_aspm_cap_init(pdev);
+
+ /* config link state to avoid BIOS error */
+ state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
+ __pcie_aspm_config_link(pdev, state);
+
+ pcie_check_clock_pm(pdev);
+
+ link_state->pdev = pdev;
+ list_add(&link_state->sibiling, &link_list);
+
+unlock_out:
+ if (error)
+ free_link_state(pdev);
+ mutex_unlock(&aspm_lock);
+out:
+ up_read(&pci_bus_sem);
+}
+
+/* @pdev: the endpoint device */
+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
+{
+ struct pci_dev *parent = pdev->bus->self;
+ struct pcie_link_state *link_state = parent->link_state;
+
+ if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
+ return;
+ if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+
+ /*
+ * All PCIe functions are in one slot, remove one function will remove
+ * the the whole slot, so just wait
+ */
+ if (!list_empty(&parent->subordinate->devices))
+ goto out;
+
+ /* All functions are removed, so just disable ASPM for the link */
+ __pcie_aspm_config_one_dev(parent, 0);
+ list_del(&link_state->sibiling);
+ /* Clock PM is for endpoint device */
+
+ free_link_state(parent);
+out:
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
+ return;
+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ /*
+ * devices changed PM state, we should recheck if latency meets all
+ * functions' requirement
+ */
+ pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+}
+
+/*
+ * pci_disable_link_state - disable pci device's link state, so the link will
+ * never enter specific states
+ */
+void pci_disable_link_state(struct pci_dev *pdev, int state)
+{
+ struct pci_dev *parent = pdev->bus->self;
+ struct pcie_link_state *link_state;
+
+ if (aspm_disabled || !pdev->is_pcie)
+ return;
+ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+ pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+ parent = pdev;
+ if (!parent)
+ return;
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ link_state = parent->link_state;
+ link_state->support_state &=
+ ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
+ if (state & PCIE_LINK_STATE_CLKPM)
+ link_state->clk_pm_capable = 0;
+
+ __pcie_aspm_configure_link_state(parent, link_state->enabled_state);
+ if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
+ pcie_set_clock_pm(parent, 0);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL(pci_disable_link_state);
+
+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
+{
+ int i;
+ struct pci_dev *pdev;
+ struct pcie_link_state *link_state;
+
+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+ if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
+ break;
+ if (i >= ARRAY_SIZE(policy_str))
+ return -EINVAL;
+ if (i == aspm_policy)
+ return 0;
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ aspm_policy = i;
+ list_for_each_entry(link_state, &link_list, sibiling) {
+ pdev = link_state->pdev;
+ __pcie_aspm_configure_link_state(pdev,
+ policy_to_aspm_state(pdev));
+ if (link_state->clk_pm_capable &&
+ link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+
+ }
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+ return 0;
+}
+
+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
+{
+ int i, cnt = 0;
+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+ if (i == aspm_policy)
+ cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
+ else
+ cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+ return cnt;
+}
+
+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
+ NULL, 0644);
+
+#ifdef CONFIG_PCIEASPM_DEBUG
+static ssize_t link_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ struct pcie_link_state *link_state = pci_device->link_state;
+
+ return sprintf(buf, "%d\n", link_state->enabled_state);
+}
+
+static ssize_t link_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ int state;
+
+ if (n < 1)
+ return -EINVAL;
+ state = buf[0]-'0';
+ if (state >= 0 && state <= 3) {
+ /* setup link aspm state */
+ pcie_aspm_configure_link_state(pci_device, state);
+ return n;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t clk_ctl_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ struct pcie_link_state *link_state = pci_device->link_state;
+
+ return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+}
+
+static ssize_t clk_ctl_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ int state;
+
+ if (n < 1)
+ return -EINVAL;
+ state = buf[0]-'0';
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ pcie_set_clock_pm(pci_device, !!state);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+
+ return n;
+}
+
+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
+
+static char power_group[] = "power";
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+ return;
+
+ if (link_state->support_state)
+ sysfs_add_file_to_group(&pdev->dev.kobj,
+ &dev_attr_link_state.attr, power_group);
+ if (link_state->clk_pm_capable)
+ sysfs_add_file_to_group(&pdev->dev.kobj,
+ &dev_attr_clk_ctl.attr, power_group);
+}
+
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+ return;
+
+ if (link_state->support_state)
+ sysfs_remove_file_from_group(&pdev->dev.kobj,
+ &dev_attr_link_state.attr, power_group);
+ if (link_state->clk_pm_capable)
+ sysfs_remove_file_from_group(&pdev->dev.kobj,
+ &dev_attr_clk_ctl.attr, power_group);
+}
+#endif
+
+static int __init pcie_aspm_disable(char *str)
+{
+ aspm_disabled = 1;
+ return 1;
+}
+
+__setup("pcie_noaspm", pcie_aspm_disable);
+
+static int __init pcie_aspm_init(void)
+{
+ if (aspm_disabled)
+ return 0;
+ pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
+ return 0;
+}
+
+fs_initcall(pcie_aspm_init);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index b20a9b81dae..23d9eb07329 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -192,9 +192,8 @@ static int get_port_device_capability(struct pci_dev *dev)
if (reg32 & SLOT_HP_CAPABLE_MASK)
services |= PCIE_PORT_SERVICE_HP;
}
- /* PME Capable */
- pos = pci_find_capability(dev, PCI_CAP_ID_PME);
- if (pos)
+ /* PME Capable - root port capability */
+ if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
services |= PCIE_PORT_SERVICE_PME;
pos = PCI_CFG_SPACE_SIZE;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 5fd585293e7..8b505bd925a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -9,6 +9,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/cpumask.h>
+#include <linux/aspm.h>
#include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
@@ -53,7 +54,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
- class_device_create_bin_file(&b->class_dev, b->legacy_io);
+ device_create_bin_file(&b->dev, b->legacy_io);
/* Allocated above after the legacy_io struct */
b->legacy_mem = b->legacy_io + 1;
@@ -61,15 +62,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
- class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+ device_create_bin_file(&b->dev, b->legacy_mem);
}
}
void pci_remove_legacy_files(struct pci_bus *b)
{
if (b->legacy_io) {
- class_device_remove_bin_file(&b->class_dev, b->legacy_io);
- class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+ device_remove_bin_file(&b->dev, b->legacy_io);
+ device_remove_bin_file(&b->dev, b->legacy_mem);
kfree(b->legacy_io); /* both are allocated here */
}
}
@@ -81,26 +82,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/*
* PCI Bus Class Devices
*/
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
int ret;
cpumask_t cpumask;
- cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
+ cpumask = pcibus_to_cpumask(to_pci_bus(dev));
ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
if (ret < PAGE_SIZE)
buf[ret++] = '\n';
return ret;
}
-CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
/*
* PCI Bus Class
*/
-static void release_pcibus_dev(struct class_device *class_dev)
+static void release_pcibus_dev(struct device *dev)
{
- struct pci_bus *pci_bus = to_pci_bus(class_dev);
+ struct pci_bus *pci_bus = to_pci_bus(dev);
if (pci_bus->bridge)
put_device(pci_bus->bridge);
@@ -109,7 +111,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
static struct class pcibus_class = {
.name = "pci_bus",
- .release = &release_pcibus_dev,
+ .dev_release = &release_pcibus_dev,
};
static int __init pcibus_class_init(void)
@@ -392,7 +394,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
{
struct pci_bus *child;
int i;
- int retval;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -408,15 +409,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
child->bus_flags = parent->bus_flags;
child->bridge = get_device(&bridge->dev);
- child->class_dev.class = &pcibus_class;
- sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
- retval = class_device_register(&child->class_dev);
- if (retval)
- goto error_register;
- retval = class_device_create_file(&child->class_dev,
- &class_device_attr_cpuaffinity);
- if (retval)
- goto error_file_create;
+ /* initialize some portions of the bus device, but don't register it
+ * now as the parent is not properly set up yet. This device will get
+ * registered later in pci_bus_add_devices()
+ */
+ child->dev.class = &pcibus_class;
+ sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
/*
* Set up the primary, secondary and subordinate
@@ -434,12 +432,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
bridge->subordinate = child;
return child;
-
-error_file_create:
- class_device_unregister(&child->class_dev);
-error_register:
- kfree(child);
- return NULL;
}
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
@@ -471,8 +463,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
}
}
-unsigned int pci_scan_child_bus(struct pci_bus *bus);
-
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
@@ -641,13 +631,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
(child->number > bus->subordinate) ||
(child->number < bus->number) ||
(child->subordinate < bus->number)) {
- pr_debug("PCI: Bus #%02x (-#%02x) is %s"
+ pr_debug("PCI: Bus #%02x (-#%02x) is %s "
"hidden behind%s bridge #%02x (-#%02x)\n",
child->number, child->subordinate,
(bus->number > child->subordinate &&
bus->subordinate < child->number) ?
- "wholly " : " partially",
- bus->self->transparent ? " transparent" : " ",
+ "wholly" : "partially",
+ bus->self->transparent ? " transparent" : "",
bus->number, bus->subordinate);
}
bus = bus->parent;
@@ -971,6 +961,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
return dev;
}
+EXPORT_SYMBOL(pci_scan_single_device);
/**
* pci_scan_slot - scan a PCI slot on a bus for devices.
@@ -1011,6 +1002,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
break;
}
}
+
+ if (bus->self)
+ pcie_aspm_init_link_state(bus->self);
+
return nr;
}
@@ -1103,32 +1098,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
goto dev_reg_err;
b->bridge = get_device(dev);
- b->class_dev.class = &pcibus_class;
- sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
- error = class_device_register(&b->class_dev);
+ b->dev.class = &pcibus_class;
+ b->dev.parent = b->bridge;
+ sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+ error = device_register(&b->dev);
if (error)
goto class_dev_reg_err;
- error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
+ error = device_create_file(&b->dev, &dev_attr_cpuaffinity);
if (error)
- goto class_dev_create_file_err;
+ goto dev_create_file_err;
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(b);
- error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
- if (error)
- goto sys_create_link_err;
-
b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
return b;
-sys_create_link_err:
- class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity);
-class_dev_create_file_err:
- class_device_unregister(&b->class_dev);
+dev_create_file_err:
+ device_unregister(&b->dev);
class_dev_reg_err:
device_unregister(dev);
dev_reg_err:
@@ -1140,7 +1130,6 @@ err_out:
kfree(b);
return NULL;
}
-EXPORT_SYMBOL_GPL(pci_create_bus);
struct pci_bus *pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
@@ -1159,7 +1148,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge);
-EXPORT_SYMBOL(pci_scan_single_device);
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
#endif
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 716439e25dd..68aeeb7206d 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/smp_lock.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -202,15 +203,18 @@ struct pci_filp_private {
int write_combine;
};
-static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
- const struct proc_dir_entry *dp = PDE(inode);
+ const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
struct pci_dev *dev = dp->data;
#ifdef HAVE_PCI_MMAP
struct pci_filp_private *fpriv = file->private_data;
#endif /* HAVE_PCI_MMAP */
int ret = 0;
+ lock_kernel();
+
switch (cmd) {
case PCIIOC_CONTROLLER:
ret = pci_domain_nr(dev->bus);
@@ -239,6 +243,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
break;
};
+ unlock_kernel();
return ret;
}
@@ -291,7 +296,7 @@ static const struct file_operations proc_bus_pci_operations = {
.llseek = proc_bus_pci_lseek,
.read = proc_bus_pci_read,
.write = proc_bus_pci_write,
- .ioctl = proc_bus_pci_ioctl,
+ .unlocked_ioctl = proc_bus_pci_ioctl,
#ifdef HAVE_PCI_MMAP
.open = proc_bus_pci_open,
.release = proc_bus_pci_release,
@@ -370,7 +375,7 @@ static int show_device(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations proc_bus_pci_devices_op = {
+static const struct seq_operations proc_bus_pci_devices_op = {
.start = pci_seq_start,
.next = pci_seq_next,
.stop = pci_seq_stop,
@@ -480,7 +485,3 @@ static int __init pci_proc_init(void)
__initcall(pci_proc_init);
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_detach_bus);
-#endif
-
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 72e0bd5d80a..0a953d43b9a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/acpi.h>
+#include <linux/kallsyms.h>
#include "pci.h"
/* The Mellanox Tavor device gives false positive parity errors
@@ -46,14 +47,14 @@ static void quirk_passive_release(struct pci_dev *dev)
while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1)) {
- printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d));
+ dev_err(&d->dev, "PIIX3: Enabling Passive Release\n");
dlc |= 1<<1;
pci_write_config_byte(d, 0x82, dlc);
}
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release);
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -68,20 +69,20 @@ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{
if (!isa_dma_bridge_buggy) {
isa_dma_bridge_buggy=1;
- printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+ dev_info(&dev->dev, "Activating ISA DMA hang workarounds\n");
}
}
/*
* Its not totally clear which chipsets are the problematic ones
* We know 82C586 and 82C596 variants are affected.
*/
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
int pci_pci_problems;
EXPORT_SYMBOL(pci_pci_problems);
@@ -92,12 +93,12 @@ EXPORT_SYMBOL(pci_pci_problems);
static void __devinit quirk_nopcipci(struct pci_dev *dev)
{
if ((pci_pci_problems & PCIPCI_FAIL)==0) {
- printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_FAIL;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci);
static void __devinit quirk_nopciamd(struct pci_dev *dev)
{
@@ -105,11 +106,11 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev)
pci_read_config_byte(dev, 0x08, &rev);
if (rev == 0x13) {
/* Erratum 24 */
- printk(KERN_INFO "Chipset erratum: Disabling direct PCI/AGP transfers.\n");
+ dev_info(&dev->dev, "Chipset erratum: Disabling direct PCI/AGP transfers\n");
pci_pci_problems |= PCIAGP_FAIL;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd);
/*
* Triton requires workarounds to be used by the drivers
@@ -117,14 +118,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopci
static void __devinit quirk_triton(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_TRITON)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_TRITON;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton);
/*
* VIA Apollo KT133 needs PCI latency patch
@@ -139,25 +140,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quir
static void quirk_vialatency(struct pci_dev *dev)
{
struct pci_dev *p;
- u8 rev;
u8 busarb;
/* Ok we have a potential problem chipset here. Now see if we have
a buggy southbridge */
p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
if (p!=NULL) {
- pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
/* Check for buggy part revisions */
- if (rev < 0x40 || rev > 0x42)
+ if (p->revision < 0x40 || p->revision > 0x42)
goto exit;
} else {
p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
if (p==NULL) /* No problem parts */
goto exit;
- pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* Check for buggy part revisions */
- if (rev < 0x10 || rev > 0x12)
+ if (p->revision < 0x10 || p->revision > 0x12)
goto exit;
}
@@ -180,17 +178,17 @@ static void quirk_vialatency(struct pci_dev *dev)
busarb &= ~(1<<5);
busarb |= (1<<4);
pci_write_config_byte(dev, 0x76, busarb);
- printk(KERN_INFO "Applying VIA southbridge workaround.\n");
+ dev_info(&dev->dev, "Applying VIA southbridge workaround\n");
exit:
pci_dev_put(p);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency);
/* Must restore this on a resume from RAM */
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency);
/*
* VIA Apollo VP3 needs ETBF on BT848/878
@@ -198,20 +196,20 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_viala
static void __devinit quirk_viaetbf(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_VIAETBF;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf);
static void __devinit quirk_vsfx(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VSFX)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_VSFX;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx);
/*
* Ali Magik requires workarounds to be used by the drivers
@@ -222,12 +220,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx
static void __init quirk_alimagik(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik);
/*
* Natoma has some interesting boundary conditions with Zoran stuff
@@ -236,16 +234,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimag
static void __devinit quirk_natoma(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_NATOMA;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma);
/*
* This chip can cause PCI parity errors if config register 0xA0 is read
@@ -255,7 +253,7 @@ static void __devinit quirk_citrine(struct pci_dev *dev)
{
dev->cfg_size = 0xA0;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine);
/*
* S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
@@ -270,8 +268,8 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
r->end = 0x3ffffff;
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
unsigned size, int nr, const char *name)
@@ -292,7 +290,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
pcibios_bus_to_resource(dev, res, &bus_region);
pci_claim_resource(dev, nr);
- printk("PCI quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
+ dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
}
}
@@ -302,12 +300,12 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
*/
static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
{
- printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
+ dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
request_region(0x3b0, 0x0C, "RadeonIGP");
request_region(0x3d3, 0x01, "RadeonIGP");
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce);
/*
* Let's make the southbridge information explicit instead
@@ -329,7 +327,7 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0xE2, &region);
quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi);
static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
{
@@ -354,7 +352,7 @@ static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int p
* let's get enough confirmation reports first.
*/
base &= -size;
- printk("%s PIO at %04x-%04x\n", name, base, base + size - 1);
+ dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base + size - 1);
}
static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
@@ -379,7 +377,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
* reserve it, but let's get enough confirmation reports first.
*/
base &= -size;
- printk("%s MMIO at %04x-%04x\n", name, base, base + size - 1);
+ dev_info(&dev->dev, "%s MMIO at %04x-%04x\n", name, base, base + size - 1);
}
/*
@@ -418,8 +416,8 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
piix4_io_quirk(dev, "PIIX4 devres I", 0x78, 1 << 20);
piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi);
/*
* ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -436,16 +434,16 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x58, &region);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi);
static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
{
@@ -457,20 +455,20 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x48, &region);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi);
/*
* VIA ACPI: One IO region pointed to by longword at
@@ -486,7 +484,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi);
/*
* VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
@@ -509,7 +507,7 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
smb &= PCI_BASE_ADDRESS_IO_MASK;
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi);
/*
* VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
@@ -551,14 +549,14 @@ static void quirk_via_ioapic(struct pci_dev *dev)
else
tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
- printk(KERN_INFO "PCI: %sbling Via external APIC routing\n",
+ dev_info(&dev->dev, "%sbling VIA external APIC routing\n",
tmp == 0 ? "Disa" : "Ena");
/* Offset 0x58: External APIC IRQ output control */
pci_write_config_byte (dev, 0x58, tmp);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic);
/*
* VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
@@ -573,7 +571,7 @@ static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
pci_read_config_byte(dev, 0x5B, &misc_control2);
if (!(misc_control2 & BYPASS_APIC_DEASSERT)) {
- printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n");
+ dev_info(&dev->dev, "Bypassing VIA 8237 APIC De-Assert Message\n");
pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT);
}
}
@@ -592,18 +590,18 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_v
static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{
if (dev->revision >= 0x02) {
- printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
- printk(KERN_WARNING " : booting with the \"noapic\" option.\n");
+ dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
+ dev_warn(&dev->dev, " : booting with the \"noapic\" option\n");
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic);
static void __init quirk_ioapic_rmw(struct pci_dev *dev)
{
if (dev->devfn == 0 && dev->bus->number == 0)
sis_apic_bug = 1;
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw);
#define AMD8131_revA0 0x01
#define AMD8131_revB0 0x11
@@ -617,7 +615,7 @@ static void quirk_amd_8131_ioapic(struct pci_dev *dev)
return;
if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
- printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n");
+ dev_info(&dev->dev, "Fixing up AMD8131 IOAPIC mode\n");
pci_read_config_byte( dev, AMD8131_MISC, &tmp);
tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
pci_write_config_byte( dev, AMD8131_MISC, tmp);
@@ -634,8 +632,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk
static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
{
if (dev->subordinate && dev->revision <= 0x12) {
- printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
- "MMRBC\n", dev->revision);
+ dev_info(&dev->dev, "AMD8131 rev %x detected; "
+ "disabling PCI-X MMRBC\n", dev->revision);
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
}
}
@@ -660,8 +658,8 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
if (irq && (irq != 2))
d->irq = irq;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi);
/*
@@ -742,8 +740,8 @@ static void quirk_via_vlink(struct pci_dev *dev)
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",
- pci_name(dev), irq, new_irq);
+ dev_info(&dev->dev, "VIA VLink IRQ fixup, from %d to %d\n",
+ irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
@@ -761,7 +759,7 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id);
/*
* CardBus controllers have a legacy base address that enables them
@@ -791,15 +789,15 @@ static void quirk_amd_ordering(struct pci_dev *dev)
pci_read_config_dword(dev, 0x4C, &pcic);
if ((pcic&6)!=6) {
pcic |= 6;
- printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");
+ dev_warn(&dev->dev, "BIOS failed to enable PCI standards compliance; fixing this error\n");
pci_write_config_dword(dev, 0x4C, pcic);
pci_read_config_dword(dev, 0x84, &pcic);
pcic |= (1<<23); /* Required in this mode */
pci_write_config_dword(dev, 0x84, pcic);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
/*
* DreamWorks provided workaround for Dunord I-3000 problem
@@ -814,7 +812,7 @@ static void __devinit quirk_dunord ( struct pci_dev * dev )
r->start = 0;
r->end = 0xffffff;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord);
/*
* i82380FB mobile docking controller: its PCI-to-PCI bridge
@@ -826,8 +824,8 @@ static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
{
dev->transparent = 1;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge);
/*
* Common misconfiguration of the MediaGX/Geode PCI master that will
@@ -841,12 +839,12 @@ static void quirk_mediagx_master(struct pci_dev *dev)
pci_read_config_byte(dev, 0x41, &reg);
if (reg & 2) {
reg &= ~2;
- printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
+ dev_info(&dev->dev, "Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
pci_write_config_byte(dev, 0x41, reg);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
/*
* Ensure C0 rev restreaming is off. This is normally done by
@@ -863,11 +861,11 @@ static void quirk_disable_pxb(struct pci_dev *pdev)
if (config & (1<<6)) {
config &= ~(1<<6);
pci_write_config_word(pdev, 0x40, config);
- printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
+ dev_info(&pdev->dev, "C0 revision 450NX. Disabling PCI restreaming\n");
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
@@ -902,7 +900,7 @@ static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
/* PCI layer will sort out resources */
}
}
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide);
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
@@ -914,7 +912,7 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev)
pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
if (((prog & 1) && !(prog & 4)) || ((prog & 4) && !(prog & 1))) {
- printk(KERN_INFO "PCI: IDE mode mismatch; forcing legacy mode\n");
+ dev_info(&pdev->dev, "IDE mode mismatch; forcing legacy mode\n");
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
@@ -929,7 +927,7 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge);
/*
@@ -1022,6 +1020,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x12bd: /* HP D530 */
asus_hides_smbus = 1;
}
+ else if (dev->device == PCI_DEVICE_ID_INTEL_82875_HB)
+ switch (dev->subsystem_device) {
+ case 0x12bf: /* HP xw4100 */
+ asus_hides_smbus = 1;
+ }
else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
switch (dev->subsystem_device) {
case 0x099c: /* HP Compaq nx6110 */
@@ -1049,17 +1052,18 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
}
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge);
static void asus_hides_smbus_lpc(struct pci_dev *dev)
{
@@ -1073,25 +1077,25 @@ static void asus_hides_smbus_lpc(struct pci_dev *dev)
pci_write_config_word(dev, 0xF2, val & (~0x8));
pci_read_config_word(dev, 0xF2, &val);
if (val & 0x8)
- printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
+ dev_info(&dev->dev, "i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
else
- printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");
+ dev_info(&dev->dev, "Enabled i801 SMBus device\n");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc);
static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
{
@@ -1106,10 +1110,10 @@ static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
iounmap(base);
- printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+ dev_info(&dev->dev, "Enabled ICH6/i801 SMBus device\n");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6);
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
@@ -1119,18 +1123,18 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev)
u8 val = 0;
pci_read_config_byte(dev, 0x77, &val);
if (val & 0x10) {
- printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
+ dev_info(&dev->dev, "Enabling SiS 96x SMBus\n");
pci_write_config_byte(dev, 0x77, val & ~0x10);
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus);
/*
* ... This is further complicated by the fact that some SiS96x south
@@ -1163,8 +1167,8 @@ static void quirk_sis_503(struct pci_dev *dev)
dev->device = devid;
quirk_sis_96x_smbus(dev);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503);
/*
@@ -1191,13 +1195,13 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev)
pci_write_config_byte(dev, 0x50, val & (~0xc0));
pci_read_config_byte(dev, 0x50, &val);
if (val & 0xc0)
- printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
+ dev_info(&dev->dev, "Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
else
- printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");
+ dev_info(&dev->dev, "Enabled onboard AC97/MC97 devices\n");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
@@ -1292,7 +1296,7 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
#endif
int pcie_mch_quirk;
@@ -1302,9 +1306,9 @@ static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
{
pcie_mch_quirk = 1;
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch);
/*
@@ -1314,11 +1318,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quir
static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
{
pci_msi_off(dev);
-
dev->no_msi = 1;
-
- printk(KERN_WARNING "PCI: PXH quirk detected, "
- "disabling MSI for SHPC device\n");
+ dev_warn(&dev->dev, "PXH quirk detected; SHPC device MSI disabled\n");
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_0, quirk_pcie_pxh);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_1, quirk_pcie_pxh);
@@ -1399,7 +1400,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
case PCI_DEVICE_ID_NETMOS_9855:
if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL &&
num_parallel) {
- printk(KERN_INFO "PCI: Netmos %04x (%u parallel, "
+ dev_info(&dev->dev, "Netmos %04x (%u parallel, "
"%u serial); changing class SERIAL to OTHER "
"(use parport_serial)\n",
dev->device, num_parallel, num_serial);
@@ -1412,9 +1413,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
{
- u16 command;
+ u16 command, pmcsr;
u8 __iomem *csr;
u8 cmd_hi;
+ int pm;
switch (dev->device) {
/* PCI IDs taken from drivers/net/e100.c */
@@ -1448,18 +1450,28 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0))
return;
+ /*
+ * Check that the device is in the D0 power state. If it's not,
+ * there is no point to look any further.
+ */
+ pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+ if (pm) {
+ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0)
+ return;
+ }
+
/* Convert from PCI bus to resource space. */
csr = ioremap(pci_resource_start(dev, 0), 8);
if (!csr) {
- printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "Can't map e100 registers\n");
return;
}
cmd_hi = readb(csr + 3);
if (cmd_hi == 0) {
- printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts "
- "enabled, disabling\n", pci_name(dev));
+ dev_warn(&dev->dev, "Firmware left e100 interrupts enabled; "
+ "disabling\n");
writeb(1, csr + 3);
}
@@ -1474,7 +1486,7 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
*/
if (dev->class == PCI_CLASS_NOT_DEFINED) {
- printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n");
+ dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
dev->class = PCI_CLASS_STORAGE_SCSI;
}
}
@@ -1485,7 +1497,11 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
while (f < end) {
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
- pr_debug("PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
+#ifdef DEBUG
+ dev_dbg(&dev->dev, "calling quirk 0x%p", f->hook);
+ print_fn_descriptor_symbol(": %s()\n",
+ (unsigned long) f->hook);
+#endif
f->hook(dev);
}
f++;
@@ -1553,7 +1569,7 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
pci_read_config_word(dev, 0x40, &en1k);
if (en1k & 0x200) {
- printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n");
+ dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
@@ -1585,7 +1601,7 @@ static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
if (iobl_adr != iobl_adr_1k) {
- printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n",
+ dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
iobl_adr,iobl_adr_1k);
pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
}
@@ -1603,9 +1619,8 @@ static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
if (!(b & 0x20)) {
pci_write_config_byte(dev, 0xf41, b | 0x20);
- printk(KERN_INFO
- "PCI: Linking AER extended capability on %s\n",
- pci_name(dev));
+ dev_info(&dev->dev,
+ "Linking AER extended capability\n");
}
}
}
@@ -1614,6 +1629,34 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap);
+static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+{
+ /*
+ * Disable PCI Bus Parking and PCI Master read caching on CX700
+ * which causes unspecified timing errors with a VT6212L on the PCI
+ * bus leading to USB2.0 packet loss. The defaults are that these
+ * features are turned off but some BIOSes turn them on.
+ */
+
+ uint8_t b;
+ if (pci_read_config_byte(dev, 0x76, &b) == 0) {
+ if (b & 0x40) {
+ /* Turn off PCI Bus Parking */
+ pci_write_config_byte(dev, 0x76, b ^ 0x40);
+
+ /* Turn off PCI Master read caching */
+ pci_write_config_byte(dev, 0x72, 0x0);
+ pci_write_config_byte(dev, 0x75, 0x1);
+ pci_write_config_byte(dev, 0x77, 0x0);
+
+ printk(KERN_INFO
+ "PCI: VIA CX700 PCI parking/caching fixup on %s\n",
+ pci_name(dev));
+ }
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
+
#ifdef CONFIG_PCI_MSI
/* Some chipsets do not support MSI. We cannot easily rely on setting
* PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
@@ -1624,7 +1667,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
static void __init quirk_disable_all_msi(struct pci_dev *dev)
{
pci_no_msi();
- printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
+ dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
@@ -1635,9 +1678,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disab
static void __devinit quirk_disable_msi(struct pci_dev *dev)
{
if (dev->subordinate) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
}
@@ -1656,9 +1698,9 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
&flags) == 0)
{
- printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
+ dev_info(&dev->dev, "Found %s HT MSI Mapping\n",
flags & HT_MSI_FLAGS_ENABLE ?
- "enabled" : "disabled", pci_name(dev));
+ "enabled" : "disabled");
return (flags & HT_MSI_FLAGS_ENABLE) != 0;
}
@@ -1672,17 +1714,40 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
{
if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "MSI disabled on chipset %s.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
quirk_msi_ht_cap);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS,
- PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
- quirk_msi_ht_cap);
+
+
+/*
+ * Force enable MSI mapping capability on HT bridges
+ */
+static void __devinit quirk_msi_ht_cap_enable(struct pci_dev *dev)
+{
+ int pos, ttl = 48;
+
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+ while (pos && ttl--) {
+ u8 flags;
+
+ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) {
+ printk(KERN_INFO "PCI: Enabling HT MSI Mapping on %s\n",
+ pci_name(dev));
+
+ pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+ flags | HT_MSI_FLAGS_ENABLE);
+ }
+ pos = pci_find_next_ht_capability(dev, pos,
+ HT_CAPTYPE_MSI_MAPPING);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
+ quirk_msi_ht_cap_enable);
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
* MSI are supported if the MSI capability set in any of these mappings.
@@ -1701,9 +1766,8 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
if (!pdev)
return;
if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "MSI disabled on chipset %s.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
pci_dev_put(pdev);
@@ -1715,6 +1779,23 @@ static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
{
dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
}
+static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+{
+ struct pci_dev *p;
+
+ /* SB700 MSI issue will be fixed at HW level from revision A21,
+ * we need check PCI REVISION ID of SMBus controller to get SB700
+ * revision.
+ */
+ p = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+ NULL);
+ if (!p)
+ return;
+
+ if ((p->revision < 0x3B) && (p->revision >= 0x30))
+ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+ pci_dev_put(p);
+}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
PCI_DEVICE_ID_TIGON3_5780,
quirk_msi_intx_disable_bug);
@@ -1735,17 +1816,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
quirk_msi_intx_disable_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390,
- quirk_msi_intx_disable_bug);
+ quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391,
- quirk_msi_intx_disable_bug);
+ quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392,
- quirk_msi_intx_disable_bug);
+ quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393,
- quirk_msi_intx_disable_bug);
+ quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394,
- quirk_msi_intx_disable_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4395,
- quirk_msi_intx_disable_bug);
+ quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
quirk_msi_intx_disable_bug);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 430281b2e92..ec4a82ba29a 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,5 +1,6 @@
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/aspm.h>
#include "pci.h"
static void pci_free_resources(struct pci_dev *dev)
@@ -30,6 +31,9 @@ static void pci_stop_dev(struct pci_dev *dev)
dev->global_list.next = dev->global_list.prev = NULL;
up_write(&pci_bus_sem);
}
+
+ if (dev->bus->self)
+ pcie_aspm_exit_link_state(dev);
}
static void pci_destroy_dev(struct pci_dev *dev)
@@ -74,10 +78,8 @@ void pci_remove_bus(struct pci_bus *pci_bus)
list_del(&pci_bus->node);
up_write(&pci_bus_sem);
pci_remove_legacy_files(pci_bus);
- class_device_remove_file(&pci_bus->class_dev,
- &class_device_attr_cpuaffinity);
- sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
- class_device_unregister(&pci_bus->class_dev);
+ device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
+ device_unregister(&pci_bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index dbbcc04abd1..a98b2470b9e 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -162,6 +162,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
return rom;
}
+#if 0
/**
* pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
* @pdev: pointer to pci device struct
@@ -196,6 +197,7 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
return (void __iomem *)(unsigned long)res->start;
}
+#endif /* 0 */
/**
* pci_unmap_rom - unmap the ROM from kernel space
@@ -218,6 +220,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
pci_disable_rom(pdev);
}
+#if 0
/**
* pci_remove_rom - disable the ROM and remove its sysfs attribute
* @pdev: pointer to pci device struct
@@ -236,6 +239,7 @@ void pci_remove_rom(struct pci_dev *pdev)
IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev);
}
+#endif /* 0 */
/**
* pci_cleanup_rom - internal routine for freeing the ROM copy created
@@ -256,6 +260,4 @@ void pci_cleanup_rom(struct pci_dev *pdev)
}
EXPORT_SYMBOL(pci_map_rom);
-EXPORT_SYMBOL(pci_map_rom_copy);
EXPORT_SYMBOL(pci_unmap_rom);
-EXPORT_SYMBOL(pci_remove_rom);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 401e03c920b..8a7232feb55 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
* The IO resource is allocated a range twice as large as it
* would normally need. This allows us to set both IO regs.
*/
- printk(" IO window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
if (bus->resource[1]->flags & IORESOURCE_IO) {
- printk(" IO window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_MEM) {
- printk(" PREFETCH window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
if (bus->resource[3]->flags & IORESOURCE_MEM) {
- printk(" MEM window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
struct pci_bus_region region;
- u32 l, io_upper16;
+ u32 l, bu, lu, io_upper16;
DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus)
/* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
DBG(KERN_INFO " IO window: %04lx-%04lx\n",
- region.start, region.end);
+ (unsigned long)region.start,
+ (unsigned long)region.end);
}
else {
/* Clear upper 16 bits of I/O base/limit. */
@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus)
if (bus->resource[1]->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- DBG(KERN_INFO " MEM window: %08lx-%08lx\n",
- region.start, region.end);
+ DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
}
else {
l = 0x0000fff0;
@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */
+ bu = lu = 0;
pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- DBG(KERN_INFO " PREFETCH window: %08lx-%08lx\n",
- region.start, region.end);
+#ifdef CONFIG_RESOURCES_64BIT
+ bu = region.start >> 32;
+ lu = region.end >> 32;
+#endif
+ DBG(KERN_INFO " PREFETCH window: 0x%016llx-0x%016llx\n",
+ (unsigned long long)region.start,
+ (unsigned long long)region.end);
}
else {
l = 0x0000fff0;
@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus)
}
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
- /* Clear out the upper 32 bits of PREF base. */
- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+ /* Set the upper 32 bits of PREF base & limit. */
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+ pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}
@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
{
struct pci_dev *dev;
- unsigned long min_align, align, size;
- unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */
+ resource_size_t min_align, align, size;
+ resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type);
@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- unsigned long r_size;
+ resource_size_t r_size;
if (r->parent || (r->flags & mask) != type)
continue;
@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
order = __ffs(align) - 20;
if (order > 11) {
printk(KERN_WARNING "PCI: region %s/%d "
- "too large: %llx-%llx\n",
+ "too large: 0x%016llx-0x%016llx\n",
pci_name(dev), i,
- (unsigned long long)r->start,
- (unsigned long long)r->end);
+ (unsigned long long)r->start,
+ (unsigned long long)r->end);
r->flags = 0;
continue;
}
@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
align = 0;
min_align = 0;
for (order = 0; order <= max_order; order++) {
- unsigned long align1 = 1UL << (order + 20);
-
+#ifdef CONFIG_RESOURCES_64BIT
+ resource_size_t align1 = 1ULL << (order + 20);
+#else
+ resource_size_t align1 = 1U << (order + 20);
+#endif
if (!align)
min_align = align1;
else if (ALIGN(align + min_align, min_align) < align1)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 6dfd86167e3..4be7ccf7e3a 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -51,10 +51,12 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
pcibios_resource_to_bus(dev, &region, res);
- pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
+ pr_debug(" got res [%llx:%llx] bus [%llx:%llx] flags %lx for "
"BAR %d of %s\n", (unsigned long long)res->start,
(unsigned long long)res->end,
- region.start, region.end, res->flags, resno, pci_name(dev));
+ (unsigned long long)region.start,
+ (unsigned long long)region.end,
+ (unsigned long)res->flags, resno, pci_name(dev));
new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
if (res->flags & IORESOURCE_IO)
@@ -125,7 +127,6 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
return err;
}
-EXPORT_SYMBOL_GPL(pci_claim_resource);
int pci_assign_resource(struct pci_dev *dev, int resno)
{
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 2ac050d7f8c..645d7a60e41 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -34,7 +34,6 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
if (!dev)
goto error;
- lock_kernel();
switch (len) {
case 1:
cfg_ret = pci_user_read_config_byte(dev, off, &byte);
@@ -47,10 +46,8 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
break;
default:
err = -EINVAL;
- unlock_kernel();
goto error;
};
- unlock_kernel();
err = -EIO;
if (cfg_ret != PCIBIOS_SUCCESSFUL)
@@ -107,7 +104,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
if (!dev)
return -ENODEV;
- lock_kernel();
switch(len) {
case 1:
err = get_user(byte, (u8 __user *)buf);
@@ -140,7 +136,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = -EINVAL;
break;
}
- unlock_kernel();
pci_dev_put(dev);
return err;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 3205f7488d1..29b4cf9e059 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2296,10 +2296,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
struct lpfc_sli *psli = &phba->sli;
- int bars = pci_select_bars(pdev, IORESOURCE_MEM);
dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
- if (pci_enable_device_bars(pdev, bars)) {
+ if (pci_enable_device_mem(pdev)) {
printk(KERN_ERR "lpfc: Cannot re-enable "
"PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6f129da3758..b72c7f17085 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2268,6 +2268,7 @@ typedef struct scsi_qla_host {
spinlock_t hardware_lock ____cacheline_aligned;
int bars;
+ int mem_only;
device_reg_t __iomem *iobase; /* Base I/O address */
resource_size_t pio_address;
#define MIN_IOBASE_LEN 0x100
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3954ed2d7b5..8f69caf8327 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1564,7 +1564,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
char pci_info[30];
char fw_str[30];
struct scsi_host_template *sht;
- int bars;
+ int bars, mem_only = 0;
bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
sht = &qla2x00_driver_template;
@@ -1575,10 +1575,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
sht = &qla24xx_driver_template;
+ mem_only = 1;
}
- if (pci_enable_device_bars(pdev, bars))
- goto probe_out;
+ if (mem_only) {
+ if (pci_enable_device_mem(pdev))
+ goto probe_out;
+ } else {
+ if (pci_enable_device(pdev))
+ goto probe_out;
+ }
if (pci_find_aer_capability(pdev))
if (pci_enable_pcie_error_reporting(pdev))
@@ -1601,6 +1607,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
ha->parent = NULL;
ha->bars = bars;
+ ha->mem_only = mem_only;
/* Set ISP-type information. */
qla2x00_set_isp_flags(ha);
@@ -2875,8 +2882,14 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
{
pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;
scsi_qla_host_t *ha = pci_get_drvdata(pdev);
+ int rc;
+
+ if (ha->mem_only)
+ rc = pci_enable_device_mem(pdev);
+ else
+ rc = pci_enable_device(pdev);
- if (pci_enable_device_bars(pdev, ha->bars)) {
+ if (rc) {
qla_printk(KERN_WARNING, ha,
"Can't re-enable PCI device after reset.\n");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 7a6499008b8..755823cdf62 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -42,6 +42,10 @@ config USB_ARCH_HAS_OHCI
default y if PPC_MPC52xx
# MIPS:
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:
default PCI
@@ -50,6 +54,7 @@ config USB_ARCH_HAS_EHCI
boolean
default y if PPC_83xx
default y if SOC_AU1200
+ default y if ARCH_IXP4XX
default PCI
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index b450cbaa3a0..86e64035edb 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -2,10 +2,7 @@
# USB/ATM DSL configuration
#
-menu "USB DSL modem support"
- depends on USB
-
-config USB_ATM
+menuconfig USB_ATM
tristate "USB DSL modem support"
depends on USB && ATM
select CRC32
@@ -18,6 +15,8 @@ config USB_ATM
To compile this driver as a module, choose M here: the
module will be called usbatm.
+if USB_ATM
+
config USB_SPEEDTOUCH
tristate "Speedtouch USB support"
depends on USB_ATM
@@ -70,4 +69,4 @@ config USB_XUSBATM
To compile this driver as a module, choose M here: the
module will be called xusbatm.
-endmenu
+endif # USB_ATM
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 389c5b164eb..c5ec1a55eee 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/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);
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));
/* 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;
bad2:
- uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+ uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
"Function : %d, Subfunction : %d\n",
E1_FUNCTION_TYPE(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;
bad2:
- uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+ uea_err(INS_TO_USBDEV(sc), "unexpected cmv received, "
"Function : %d, Subfunction : %d\n",
E4_FUNCTION_TYPE(cmv->wFunction),
E4_FUNCTION_SUBTYPE(cmv->wFunction));
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 912d97aaf9b..bcc42136c93 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/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. */
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++) {
+ usb_autopm_put_interface(acm->control);
goto done;
}
+
acm->ctrlurb->dev = acm->dev;
if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
dbg("usb_submit_urb(ctrl irq) failed");
@@ -526,14 +535,15 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
done:
err_out:
- mutex_unlock(&open_mutex);
+ mutex_unlock(&acm->mutex);
return rv;
full_bailout:
usb_kill_urb(acm->ctrlurb);
bail_out:
+ usb_autopm_put_interface(acm->control);
acm->used--;
- mutex_unlock(&open_mutex);
+ mutex_unlock(&acm->mutex);
return -EIO;
}
@@ -570,6 +580,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
usb_kill_urb(acm->writeurb);
for (i = 0; i < nr; i++)
usb_kill_urb(acm->ru[i].urb);
+ usb_autopm_put_interface(acm->control);
} else
acm_tty_unregister(acm);
}
@@ -904,7 +915,7 @@ next_desc:
}
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:
@@ -980,6 +991,7 @@ skip_normal_probe:
spin_lock_init(&acm->throttle_lock);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
+ mutex_init(&acm->mutex);
acm->write_ready = 1;
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
@@ -1096,6 +1108,25 @@ alloc_fail:
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)
{
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->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);
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);
}
+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.
*/
@@ -1208,7 +1267,10 @@ static struct usb_driver acm_driver = {
.name = "cdc_acm",
.probe = acm_probe,
.disconnect = acm_disconnect,
+ .suspend = acm_suspend,
+ .resume = acm_resume,
.id_table = acm_ids,
+ .supports_autosuspend = 1,
};
/*
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 09f7765dbf8..8df6a57dcf9 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -107,6 +107,7 @@ struct acm {
int write_used; /* number of non-empty write buffers */
int write_ready; /* write urb is not running */
spinlock_t write_lock;
+ struct mutex mutex;
struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
struct tasklet_struct urb_task; /* rx processing */
@@ -120,6 +121,7 @@ struct acm {
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
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
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 97b09f28270..5c33cdb9cac 100644
--- a/drivers/usb/core/Kconfig
+++ b/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
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"
depends on USB
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 28d4972f7ad..cadb2dc1d28 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -53,11 +53,13 @@ int hcd_buffer_create(struct usb_hcd *hcd)
char name[16];
int i, size;
- if (!hcd->self.controller->dma_mask)
+ if (!hcd->self.controller->dma_mask &&
+ !(hcd->driver->flags & HCD_LOCAL_MEM))
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;
snprintf(name, sizeof name, "buffer-%d", size);
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)
{
- 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) {
dma_pool_destroy(pool);
hcd->pool[i] = NULL;
@@ -107,7 +109,8 @@ void *hcd_buffer_alloc(
int i;
/* 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;
return kmalloc(size, mem_flags);
}
@@ -132,7 +135,8 @@ void hcd_buffer_free(
if (!addr)
return;
- if (!bus->controller->dma_mask) {
+ if (!bus->controller->dma_mask &&
+ !(hcd->driver->flags & HCD_LOCAL_MEM)) {
kfree(addr);
return;
}
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 1a8edcee7f3..a92122a216b 100644
--- a/drivers/usb/core/config.c
+++ b/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 */
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) {
dev_warn(ddev, "too many endpoints for config %d interface %d "
"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;
}
- 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;
alt->endpoint = kzalloc(len, GFP_KERNEL);
if (!alt->endpoint)
@@ -475,8 +476,9 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
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)
{
int c, i;
@@ -498,7 +500,7 @@ void usb_destroy_configuration(struct usb_device *dev)
kfree(cf->string);
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
if (cf->intf_cache[i])
- kref_put(&cf->intf_cache[i]->ref,
+ kref_put(&cf->intf_cache[i]->ref,
usb_release_interface_cache);
}
}
@@ -525,7 +527,7 @@ int usb_get_configuration(struct usb_device *dev)
unsigned int cfgno, length;
unsigned char *buffer;
unsigned char *bigbuffer;
- struct usb_config_descriptor *desc;
+ struct usb_config_descriptor *desc;
cfgno = 0;
if (dev->authorized == 0) /* Not really an error */
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 87c794d60aa..83d9dc379d9 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -89,7 +89,7 @@ static const char *format_string_serialnumber =
static const char *format_bandwidth =
/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
"B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-
+
static const char *format_device1 =
/* 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";
@@ -101,7 +101,7 @@ static const char *format_device2 =
static const char *format_config =
/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
"C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-
+
static const char *format_iad =
/* 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";
@@ -122,7 +122,7 @@ static const char *format_endpt =
*/
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 */
struct usb_device_status {
@@ -172,12 +172,8 @@ static const char *class_decode(const int class)
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;
unsigned interval, bandwidth = 1;
@@ -235,22 +231,24 @@ static char *usb_dump_endpoint_descriptor(
start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
desc->bmAttributes, type,
- (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * bandwidth,
+ (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) *
+ bandwidth,
interval, unit);
return start;
}
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 = "";
int active = 0;
if (start > end)
return start;
+ desc = &intfc->altsetting[setno].desc;
if (iface) {
driver_name = (iface->dev.driver
? iface->dev.driver->name
@@ -270,14 +268,10 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
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];
int i;
@@ -292,7 +286,7 @@ static char *usb_dump_interface(
}
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)
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
* 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)
return start;
start += sprintf(start, format_config,
- active ? '*' : ' ', /* mark active/actual/current cfg. */
+ /* mark active/actual/current cfg. */
+ active ? '*' : ' ',
desc->bNumInterfaces,
desc->bConfigurationValue,
desc->bmAttributes,
@@ -325,13 +321,8 @@ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb
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;
struct usb_interface_cache *intfc;
@@ -339,7 +330,8 @@ static char *usb_dump_config (
if (start > end)
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");
start = usb_dump_config_descriptor(start, end, &config->desc, active);
for (i = 0; i < USB_MAXIADS; i++) {
@@ -364,7 +356,8 @@ static char *usb_dump_config (
/*
* 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 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,
bcdUSB >> 8, bcdUSB & 0xff,
desc->bDeviceClass,
- class_decode (desc->bDeviceClass),
+ class_decode(desc->bDeviceClass),
desc->bDeviceSubClass,
desc->bDeviceProtocol,
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.
*/
-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)
return start;
if (dev->manufacturer)
- start += sprintf(start, format_string_manufacturer, dev->manufacturer);
+ start += sprintf(start, format_string_manufacturer,
+ dev->manufacturer);
if (start > end)
goto out;
if (dev->product)
@@ -405,7 +400,8 @@ static char *usb_dump_device_strings(char *start, char *end, struct usb_device *
goto out;
#ifdef ALLOW_SERIAL_NUMBER
if (dev->serial)
- start += sprintf(start, format_string_serialnumber, dev->serial);
+ start += sprintf(start, format_string_serialnumber,
+ dev->serial);
#endif
out:
return start;
@@ -417,12 +413,12 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
if (start > end)
return start;
-
+
start = usb_dump_device_descriptor(start, end, &dev->descriptor);
if (start > end)
return start;
-
+
start = usb_dump_device_strings(start, end, dev);
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 */
-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;
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;
}
-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)
return start;
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;
}
@@ -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
* 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 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;
unsigned int length;
ssize_t total_written = 0;
-
+
/* don't bother with anything else if we're not writing any data */
if (*nbytes <= 0)
return 0;
-
+
if (level > MAX_TOPO_LEVEL)
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)
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,
(100 * bus->bandwidth_allocated + max / 2)
/ 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))
data_end += sprintf(data_end, "(truncated)\n");
-
+
length = data_end - pages_start;
/* if we can start copying some data to the user */
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;
} else
*skip_bytes -= length;
-
+
free_pages((unsigned long)pages_start, 1);
-
+
/* Now look at all of this device's children. */
for (chix = 0; chix < usbdev->maxchild; chix++) {
struct usb_device *childdev = usbdev->children[chix];
if (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);
if (ret == -EFAULT)
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;
}
-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;
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)
continue;
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);
if (ret < 0) {
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 */
-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;
unsigned int mask = 0;
@@ -629,7 +638,8 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
if (!st) {
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) {
kfree(st);
st = file->private_data;
@@ -652,7 +662,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
}
lost_race:
if (file->f_mode & FMODE_READ)
- poll_wait(file, &deviceconndiscwq, wait);
+ poll_wait(file, &deviceconndiscwq, wait);
if (st->lastev != conndiscevcnt)
mask |= POLLIN;
st->lastev = conndiscevcnt;
@@ -662,18 +672,18 @@ lost_race:
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)
{
kfree(file->private_data);
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;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 1f4f6d02fe2..ae94176c64e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -75,14 +75,14 @@ struct async {
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...) \
do { \
if (usbfs_snoop) \
- dev_info( dev , format , ## arg); \
+ dev_info(dev , format , ## arg); \
} while (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
-static inline int connected (struct dev_state *ps)
+static inline int connected(struct dev_state *ps)
{
return (!list_empty(&ps->list) &&
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;
}
-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 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)) {
- 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));
le16_to_cpus(&temp_desc.bcdUSB);
@@ -210,17 +212,17 @@ err:
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);
if (!as->urb) {
kfree(as);
return NULL;
}
- return as;
+ return 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)
{
- 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)
{
- 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)
{
- 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)
if (as->userurb == userurb) {
list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
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)
@@ -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, "data: ");
for (j = 0; j < urb->transfer_buffer_length; ++j)
- printk ("%02x ", data[j]);
+ printk("%02x ", data[j]);
printk("\n");
}
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;
- 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;
if (as->signr) {
sinfo.si_signo = as->signr;
@@ -325,7 +329,7 @@ static void async_completed(struct urb *urb)
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;
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;
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)
{
- 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.
*/
-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;
}
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;
if (!ps)
@@ -396,16 +401,31 @@ static void driver_disconnect(struct usb_interface *intf)
else
warn("interface number %u out of range", ifnum);
- usb_set_intfdata (intf, NULL);
+ usb_set_intfdata(intf, NULL);
/* force async requests to complete */
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 = {
.name = "usbfs",
.probe = driver_probe,
.disconnect = driver_disconnect,
+ .suspend = driver_suspend,
+ .resume = driver_resume,
};
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))
return 0;
/* 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);
}
static int findintfep(struct usb_device *dev, unsigned int ep)
{
unsigned int i, j, e;
- struct usb_interface *intf;
+ struct usb_interface *intf;
struct usb_host_interface *alts;
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++) {
intf = dev->actconfig->interface[i];
for (j = 0; j < intf->num_altsetting; j++) {
- alts = &intf->altsetting[j];
+ alts = &intf->altsetting[j];
for (e = 0; e < alts->desc.bNumEndpoints; e++) {
endpt = &alts->endpoint[e].desc;
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;
@@ -502,7 +524,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig
index &= 0xff;
switch (requesttype & USB_RECIP_MASK) {
case USB_RECIP_ENDPOINT:
- if ((ret = findintfep(ps->dev, index)) >= 0)
+ ret = findintfep(ps->dev, index);
+ if (ret >= 0)
ret = checkintf(ps, ret);
break;
@@ -546,7 +569,8 @@ static int usbdev_open(struct inode *inode, struct file *file)
mutex_lock(&usbfs_mutex);
ret = -ENOMEM;
- if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+ ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL);
+ if (!ps)
goto out;
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)))
return -EFAULT;
- if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
+ ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+ if (ret)
return ret;
if (ctrl.wLength > PAGE_SIZE)
return -EINVAL;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!tbuf)
return -ENOMEM;
tmo = ctrl.timeout;
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);
return -EINVAL;
}
@@ -646,14 +673,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
ctrl.wIndex, ctrl.wLength);
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);
if ((i > 0) && ctrl.wLength) {
if (usbfs_snoop) {
dev_info(&dev->dev, "control read: data ");
for (j = 0; j < i; ++j)
- printk("%02x ", (unsigned char)(tbuf)[j]);
+ printk("%02x ", (u8)(tbuf)[j]);
printk("\n");
}
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");
}
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);
}
free_page((unsigned long)tbuf);
- if (i<0 && i != -EPIPE) {
+ if (i < 0 && i != -EPIPE) {
dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
"failed cmd %s rqt %u rq %u len %u ret %d\n",
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)))
return -EFAULT;
- if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+ ret = findintfep(ps->dev, bulk.ep);
+ if (ret < 0)
return ret;
- if ((ret = checkintf(ps, ret)))
+ ret = checkintf(ps, ret);
+ if (ret)
return ret;
if (bulk.ep & USB_DIR_IN)
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) {
dev_info(&dev->dev, "bulk read: data ");
for (j = 0; j < len2; ++j)
- printk("%02x ", (unsigned char)(tbuf)[j]);
+ printk("%02x ", (u8)(tbuf)[j]);
printk("\n");
}
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))
return -EFAULT;
- if ((ret = findintfep(ps->dev, ep)) < 0)
+ ret = findintfep(ps->dev, ep);
+ if (ret < 0)
return ret;
- if ((ret = checkintf(ps, ret)))
+ ret = checkintf(ps, ret);
+ if (ret)
return ret;
usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 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))
return -EFAULT;
- if ((ret = findintfep(ps->dev, ep)) < 0)
+ ret = findintfep(ps->dev, ep);
+ if (ret < 0)
return ret;
- if ((ret = checkintf(ps, ret)))
+ ret = checkintf(ps, ret);
+ if (ret)
return ret;
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);
}
-
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 status = 0;
- struct usb_host_config *actconfig;
+ struct usb_host_config *actconfig;
if (get_user(u, (int __user *)arg))
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.
*/
- 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 "
"while '%s' sets config #%d\n",
actconfig->interface[i]
@@ -881,11 +915,11 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
actconfig->interface[i]
->dev.driver->name,
current->comm, u);
- status = -EBUSY;
+ status = -EBUSY;
break;
}
- }
- }
+ }
+ }
/* SET_CONFIGURATION is often abused as a "cheap" driver reset,
* 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,
- 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 usb_host_endpoint *ep;
@@ -917,12 +951,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
return -EINVAL;
if (!uurb->buffer)
return -EINVAL;
- if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || uurb->signr > SIGRTMAX))
+ if (uurb->signr != 0 && (uurb->signr < SIGRTMIN ||
+ uurb->signr > SIGRTMAX))
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;
- if ((ret = checkintf(ps, ifnum)))
+ ret = checkintf(ps, ifnum);
+ if (ret)
return ret;
}
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:
if (!usb_endpoint_xfer_control(&ep->desc))
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;
- if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
+ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+ if (!dr)
return -ENOMEM;
if (copy_from_user(dr, uurb->buffer, 8)) {
kfree(dr);
@@ -951,7 +992,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
kfree(dr);
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);
return ret;
}
@@ -997,11 +1040,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
case USBDEVFS_URB_TYPE_ISO:
/* 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;
if (!usb_endpoint_xfer_isoc(&ep->desc))
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)))
return -ENOMEM;
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;
}
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) {
kfree(isopkt);
return -EINVAL;
@@ -1039,25 +1085,27 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
default:
return -EINVAL;
}
- if (!(as = alloc_async(uurb->number_of_packets))) {
+ as = alloc_async(uurb->number_of_packets);
+ if (!as) {
kfree(isopkt);
kfree(dr);
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(dr);
free_async(as);
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) |
(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);
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->number_of_packets = uurb->number_of_packets;
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);
else
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++) {
as->urb->iso_frame_desc[u].offset = totlen;
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);
as->ps = ps;
- as->userurb = arg;
+ as->userurb = arg;
if (uurb->endpoint & USB_DIR_IN)
as->userbuffer = uurb->buffer;
else
@@ -1093,14 +1141,15 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
}
}
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)
@@ -1110,7 +1159,9 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
if (copy_from_user(&uurb, arg, sizeof(uurb)))
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)
@@ -1132,7 +1183,8 @@ static int processcompl(struct async *as, void __user * __user *arg)
unsigned int i;
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;
if (put_user(as->status, &userurb->status))
return -EFAULT;
@@ -1159,16 +1211,17 @@ static int processcompl(struct async *as, void __user * __user *arg)
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 usb_device *dev = ps->dev;
add_wait_queue(&ps->wait, &wait);
for (;;) {
__set_current_state(TASK_INTERRUPTIBLE);
- if ((as = async_getcompleted(ps)))
+ as = async_getcompleted(ps);
+ if (as)
break;
if (signal_pending(current))
break;
@@ -1232,10 +1285,12 @@ static int proc_submiturb_compat(struct dev_state *ps, void __user *arg)
{
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 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)
@@ -1246,7 +1301,8 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
unsigned int i;
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;
if (put_user(as->status, &userurb->status))
return -EFAULT;
@@ -1337,16 +1393,16 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
struct usb_driver *driver = NULL;
/* 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;
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);
return -EFAULT;
}
} 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)
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) {
/* disconnect kernel driver from interface */
case USBDEVFS_DISCONNECT:
if (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);
} else
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 */
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;
/* 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) {
retval = -ENOTTY;
} else {
- retval = driver->ioctl (intf, ctl->ioctl_code, buf);
+ retval = driver->ioctl(intf, ctl->ioctl_code, buf);
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
}
@@ -1393,9 +1450,9 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* cleanup and return */
if (retval >= 0
- && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
+ && (_IOC_DIR(ctl->ioctl_code) & _IOC_READ) != 0
&& size > 0
- && copy_to_user (ctl->data, buf, size) != 0)
+ && copy_to_user(ctl->data, buf, size) != 0)
retval = -EFAULT;
kfree(buf);
@@ -1406,7 +1463,7 @@ static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
{
struct usbdevfs_ioctl ctrl;
- if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
+ if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
return -EFAULT;
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
* 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 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 */
-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;
unsigned int mask = 0;
@@ -1648,7 +1707,7 @@ int __init usb_devio_init(void)
int retval;
retval = register_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX,
- "usb_device");
+ "usb_device");
if (retval) {
err("unable to register minors for usb_device");
goto out;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7c3aaa9c540..801b6f142fa 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -202,10 +202,10 @@ static int usb_probe_interface(struct device *dev)
intf = to_usb_interface(dev);
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);
if (!id)
@@ -299,7 +299,7 @@ static int usb_unbind_interface(struct device *dev)
* lock.
*/
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 usb_device *udev = interface_to_usbdev(iface);
@@ -325,7 +325,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
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
@@ -370,7 +370,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
iface->needs_remote_wakeup = 0;
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 */
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;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
- (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+ (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
return 0;
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
indicates that the driver want to examine every
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))
return id;
}
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)
{
@@ -586,7 +586,7 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
struct usb_device *usb_dev;
/* 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))
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) {
- pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+ pr_debug("usb %s: already deleted?\n", dev->bus_id);
return -ENODEV;
}
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;
}
@@ -745,7 +745,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
return retval;
}
-EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
+EXPORT_SYMBOL_GPL(usb_register_driver);
/**
* usb_deregister - unregister a USB interface driver
@@ -769,7 +769,7 @@ void usb_deregister(struct usb_driver *driver)
usbfs_update_special();
}
-EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+EXPORT_SYMBOL_GPL(usb_deregister);
#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",
"suspend", status);
} 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",
driver->name);
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",
"reset_resume", status);
} else {
- // status = -EOPNOTSUPP;
+ /* status = -EOPNOTSUPP; */
dev_warn(&intf->dev, "no %s for driver %s?\n",
"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",
"resume", status);
} else {
- // status = -EOPNOTSUPP;
+ /* status = -EOPNOTSUPP; */
dev_warn(&intf->dev, "no %s for driver %s?\n",
"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
* then we're stuck. */
status = usb_resume_device(udev);
- }
+ }
} else {
/* Needed for setting udev->dev.power.power_state.event,
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 5d860bc9b42..8133c99c6c5 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -204,7 +204,7 @@ int usb_register_dev(struct usb_interface *intf,
exit:
return retval;
}
-EXPORT_SYMBOL(usb_register_dev);
+EXPORT_SYMBOL_GPL(usb_register_dev);
/**
* 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;
destroy_usb_class();
}
-EXPORT_SYMBOL(usb_deregister_dev);
+EXPORT_SYMBOL_GPL(usb_deregister_dev);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 3fb9af80cbf..84760ddbc33 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -1,6 +1,6 @@
/*
* (C) Copyright David Brownell 2000-2002
- *
+ *
* 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
@@ -55,7 +55,7 @@
*
* 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 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())
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;
- if (pci_enable_device (dev) < 0)
+ if (pci_enable_device(dev) < 0)
return -ENODEV;
dev->current_state = PCI_D0;
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",
pci_name(dev));
- retval = -ENODEV;
+ retval = -ENODEV;
goto err1;
- }
+ }
- hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
+ hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
if (!hcd) {
retval = -ENOMEM;
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)) {
- dev_dbg (&dev->dev, "controller already in use\n");
+ dev_dbg(&dev->dev, "controller already in use\n");
retval = -EBUSY;
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) {
- dev_dbg (&dev->dev, "error mapping memory\n");
+ dev_dbg(&dev->dev, "error mapping memory\n");
retval = -EFAULT;
goto err3;
}
- } else { // UHCI
+ } else {
+ /* UHCI */
int region;
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
- if (!(pci_resource_flags (dev, region) &
+ if (!(pci_resource_flags(dev, region) &
IORESOURCE_IO))
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))
break;
}
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;
goto err1;
}
}
- pci_set_master (dev);
+ pci_set_master(dev);
retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
@@ -132,19 +137,19 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
err4:
if (driver->flags & HCD_MEMORY) {
- iounmap (hcd->regs);
+ iounmap(hcd->regs);
err3:
- release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
} else
- release_region (hcd->rsrc_start, hcd->rsrc_len);
+ release_region(hcd->rsrc_start, hcd->rsrc_len);
err2:
- usb_put_hcd (hcd);
+ usb_put_hcd(hcd);
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;
-}
-EXPORT_SYMBOL (usb_hcd_pci_probe);
+}
+EXPORT_SYMBOL_GPL(usb_hcd_pci_probe);
/* 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().
*/
-void usb_hcd_pci_remove (struct pci_dev *dev)
+void usb_hcd_pci_remove(struct pci_dev *dev)
{
struct usb_hcd *hcd;
@@ -169,17 +174,17 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
if (!hcd)
return;
- usb_remove_hcd (hcd);
+ usb_remove_hcd(hcd);
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 {
- 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);
}
-EXPORT_SYMBOL (usb_hcd_pci_remove);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
#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().
*/
-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;
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 */
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) {
- dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
+ dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n");
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
* 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);
if (retval == 0) {
int wake = device_can_wakeup(&hcd->self.root_hub->dev);
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" : "");
/* Ignore these return values. We rely on pci code to
* reject requests the hardware can't implement, rather
* 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 {
- dev_dbg (&dev->dev, "PCI D3 suspend fail, %d\n",
+ dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
retval);
- (void) usb_hcd_pci_resume (dev);
+ (void) usb_hcd_pci_resume(dev);
}
} 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);
WARN_ON(1);
retval = -EINVAL;
@@ -298,7 +309,7 @@ done:
if (machine_is(powermac)) {
struct device_node *of_node;
- of_node = pci_device_to_OF_node (dev);
+ of_node = pci_device_to_OF_node(dev);
if (of_node)
pmac_call_feature(PMAC_FTR_USB_ENABLE,
of_node, 0, 0);
@@ -308,7 +319,7 @@ done:
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
@@ -316,14 +327,14 @@ EXPORT_SYMBOL (usb_hcd_pci_suspend);
*
* 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;
int retval;
hcd = pci_get_drvdata(dev);
if (hcd->state != HC_STATE_SUSPENDED) {
- dev_dbg (hcd->self.controller,
+ dev_dbg(hcd->self.controller,
"can't resume, not suspended!\n");
return 0;
}
@@ -333,9 +344,9 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
if (machine_is(powermac)) {
struct device_node *of_node;
- of_node = pci_device_to_OF_node (dev);
+ of_node = pci_device_to_OF_node(dev);
if (of_node)
- pmac_call_feature (PMAC_FTR_USB_ENABLE,
+ pmac_call_feature(PMAC_FTR_USB_ENABLE,
of_node, 0, 1);
}
#endif
@@ -374,8 +385,8 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
}
#endif
/* 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 {
/* Same basic cases: clean (powered/not), dirty */
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()
* explicitly disables bus mastering...
*/
- retval = pci_enable_device (dev);
+ retval = pci_enable_device(dev);
if (retval < 0) {
- dev_err (hcd->self.controller,
+ dev_err(hcd->self.controller,
"can't re-enable after resume, %d!\n", 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;
@@ -402,15 +413,15 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
if (hcd->driver->resume) {
retval = hcd->driver->resume(hcd);
if (retval) {
- dev_err (hcd->self.controller,
+ dev_err(hcd->self.controller,
"PCI post-resume error %d!\n", retval);
- usb_hc_died (hcd);
+ usb_hc_died(hcd);
}
}
return retval;
}
-EXPORT_SYMBOL (usb_hcd_pci_resume);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
#endif /* CONFIG_PM */
@@ -418,7 +429,7 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
* usb_hcd_pci_shutdown - shutdown host controller
* @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;
@@ -429,5 +440,5 @@ void usb_hcd_pci_shutdown (struct pci_dev *dev)
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
-EXPORT_SYMBOL (usb_hcd_pci_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d5ed3fa9e30..e52ed1663b3 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -35,6 +35,7 @@
#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
#include <linux/platform_device.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 ]*/
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 */
0x03, /* __u8 iManufacturer; */
@@ -154,8 +155,8 @@ static const u8 usb11_rh_dev_descriptor [18] = {
0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */
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 */
0x03, /* __u8 iManufacturer; */
@@ -807,13 +808,13 @@ static int usb_register_bus(struct usb_bus *bus)
}
set_bit (busnum, busmap.busmap);
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;
- class_set_devdata(bus->class_dev, bus);
+ dev_set_drvdata(bus->dev, bus);
/* Add it to the local list of buses */
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);
- 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;
}
}
-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);
-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.
* Lower level HCD code should use *_dma exclusively,
* 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,
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);
- 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 (
hcd->self.controller,
urb->transfer_buffer,
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)
{
- 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,
sizeof(struct usb_ctrlrequest),
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,
urb->transfer_dma,
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
* 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))
status = rh_urb_enqueue(hcd, urb);
else
@@ -1194,6 +1329,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
if (unlikely(status)) {
usbmon_urb_submit_error(&hcd->self, urb, status);
unmap_urb_for_dma(hcd, urb);
+ error:
urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list);
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);
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));
return status;
}
-EXPORT_SYMBOL (usb_bus_start_enum);
+EXPORT_SYMBOL_GPL(usb_bus_start_enum);
#endif
@@ -1638,7 +1774,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
"USB Host Controller";
return hcd;
}
-EXPORT_SYMBOL (usb_create_hcd);
+EXPORT_SYMBOL_GPL(usb_create_hcd);
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);
return hcd;
}
-EXPORT_SYMBOL (usb_get_hcd);
+EXPORT_SYMBOL_GPL(usb_get_hcd);
void usb_put_hcd (struct usb_hcd *hcd)
{
if (hcd)
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
@@ -1786,7 +1922,7 @@ err_register_bus:
hcd_buffer_destroy(hcd);
return retval;
}
-EXPORT_SYMBOL (usb_add_hcd);
+EXPORT_SYMBOL_GPL(usb_add_hcd);
/**
* 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);
hcd_buffer_destroy(hcd);
}
-EXPORT_SYMBOL (usb_remove_hcd);
+EXPORT_SYMBOL_GPL(usb_remove_hcd);
void
usb_hcd_platform_shutdown(struct platform_device* dev)
@@ -1838,7 +1974,7 @@ usb_hcd_platform_shutdown(struct platform_device* dev)
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
-EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown);
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 98e24194a4a..2d1c3d5e47b 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -125,7 +125,7 @@ struct usb_hcd {
/* more shared queuing code would be good; it should support
* 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).
*/
@@ -133,16 +133,16 @@ struct usb_hcd {
* this structure.
*/
unsigned long hcd_priv[0]
- __attribute__ ((aligned (sizeof(unsigned long))));
+ __attribute__ ((aligned(sizeof(unsigned long))));
};
/* 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;
}
-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);
}
@@ -165,6 +165,7 @@ struct hc_driver {
int flags;
#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_USB2 0x0020 /* USB 2.0 */
@@ -201,15 +202,18 @@ struct hc_driver {
struct usb_host_endpoint *ep);
/* 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,
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 */
+
+ /* 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);
@@ -217,56 +221,56 @@ extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
int status);
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,
int status);
extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
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);
-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,
unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd);
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
struct pci_dev;
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);
-extern void usb_hcd_pci_remove (struct pci_dev *dev);
+extern void usb_hcd_pci_remove(struct pci_dev *dev);
#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 */
-extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
#endif /* CONFIG_PCI */
/* 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);
-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);
/* 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);
/* -------------------------------------------------------------------------- */
@@ -319,9 +323,9 @@ extern void usb_destroy_configuration(struct usb_device *dev);
* Generic bandwidth allocation constants/support
*/
#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
- of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+ * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
/* bytecount = data payload byte count */
#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_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_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
@@ -345,16 +349,16 @@ extern void usb_destroy_configuration(struct usb_device *dev);
* to preallocate bandwidth)
*/
#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 \
+ USB2_HOST_DELAY)
-#define HS_NSECS_ISO(bytes) ( ((38 * 8 * 2083) \
+#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
+ (2083UL * (3 + BitTime(bytes))))/1000 \
+ USB2_HOST_DELAY)
#define HS_USECS(bytes) NS_TO_US (HS_NSECS(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);
/*-------------------------------------------------------------------------*/
@@ -370,16 +374,16 @@ extern struct list_head usb_bus_list;
extern struct mutex usb_bus_list_lock;
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);
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
#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_resume(struct usb_device *rhdev);
#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
* with the kernel lock held
*/
-extern void usbfs_update_special (void);
+extern void usbfs_update_special(void);
extern int usbfs_init(void);
extern void usbfs_cleanup(void);
#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 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 */
-// bleech -- resurfaced in 2.4.11 or 2.4.12
+/* bleech -- resurfaced in 2.4.11 or 2.4.12 */
#define bitmap DeviceRemovable
@@ -468,8 +472,8 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
/* 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.
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b04d232d4c6..68fc5219ca1 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -37,6 +37,13 @@
#define USB_PERSIST 0
#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 device *intfdev; /* the "interface" device */
struct usb_device *hdev;
@@ -487,6 +494,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
schedule_work (&tt->kevent);
spin_unlock_irqrestore (&tt->lock, flags);
}
+EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
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])
recursively_mark_NOTATTACHED(udev->children[i]);
}
- if (udev->state == USB_STATE_SUSPENDED)
+ if (udev->state == USB_STATE_SUSPENDED) {
udev->discon_suspended = 1;
+ udev->active_duration -= jiffies;
+ }
udev->state = USB_STATE_NOTATTACHED;
}
@@ -1077,6 +1087,12 @@ void usb_set_device_state(struct usb_device *udev,
else
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;
} else
recursively_mark_NOTATTACHED(udev);
@@ -1207,7 +1223,7 @@ void usb_disconnect(struct usb_device **pdev)
put_device(&udev->dev);
}
-#ifdef DEBUG
+#ifdef CONFIG_USB_ANNOUNCE_NEW_DEVICES
static void show_string(struct usb_device *udev, char *id, char *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);
}
+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
-static inline void show_string(struct usb_device *udev, char *id, char *string)
-{}
+static inline void announce_device(struct usb_device *udev) { }
#endif
-
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
#endif
@@ -1390,14 +1418,7 @@ int usb_new_device(struct usb_device *udev)
}
/* 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;
fail:
@@ -2482,6 +2503,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
{
struct usb_device *hdev = hub->hdev;
struct device *hub_dev = hub->intfdev;
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
int status, i;
@@ -2645,6 +2667,8 @@ loop:
done:
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)
@@ -2946,7 +2970,7 @@ static int config_descriptors_changed(struct usb_device *udev)
if (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) {
dev_err(&udev->dev, "no mem to re-read configs after reset\n");
/* assume the worst */
@@ -3093,7 +3117,7 @@ re_enumerate:
hub_port_logical_disconnect(parent_hub, port1);
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
@@ -3110,16 +3134,12 @@ EXPORT_SYMBOL(usb_reset_device);
* this from a driver probe() routine after downloading new firmware.
* For calls that might not occur during probe(), drivers should lock
* 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,
struct usb_interface *iface)
{
int ret;
+ int i;
struct usb_host_config *config = udev->actconfig;
if (udev->state == USB_STATE_NOTATTACHED ||
@@ -3136,16 +3156,11 @@ int usb_reset_composite_device(struct usb_device *udev,
iface = NULL;
if (config) {
- int i;
- struct usb_interface *cintf;
- struct usb_driver *drv;
-
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);
if (drv->pre_reset)
(drv->pre_reset)(cintf);
@@ -3157,25 +3172,20 @@ int usb_reset_composite_device(struct usb_device *udev,
ret = usb_reset_device(udev);
if (config) {
- int i;
- struct usb_interface *cintf;
- struct usb_driver *drv;
-
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);
if (drv->post_reset)
(drv->post_reset)(cintf);
/* FIXME: Unbind if post_reset returns an error or isn't defined */
}
- if (cintf != iface)
- up(&cintf->dev.sem);
}
}
usb_autosuspend_device(udev);
return ret;
}
-EXPORT_SYMBOL(usb_reset_composite_device);
+EXPORT_SYMBOL_GPL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index cf9559c6c9b..1551aed65e0 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -55,16 +55,16 @@
#define USB_PORT_FEAT_TEST 21
#define USB_PORT_FEAT_INDICATOR 22
-/*
+/*
* Hub Status and Hub Change results
* See USB 2.0 spec Table 11-19 and Table 11-20
*/
struct usb_port_status {
__le16 wPortStatus;
- __le16 wPortChange;
+ __le16 wPortChange;
} __attribute__ ((packed));
-/*
+/*
* wPortStatus bit field
* See USB 2.0 spec Table 11-21
*/
@@ -81,7 +81,7 @@ struct usb_port_status {
#define USB_PORT_STAT_INDICATOR 0x1000
/* bits 13 to 15 are reserved */
-/*
+/*
* wPortChange bit field
* See USB 2.0 spec Table 11-22
* 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
/*
- * wHubCharacteristics (masks)
+ * wHubCharacteristics (masks)
* See USB 2.0 spec Table 11-13, offset 3
*/
#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
@@ -119,8 +119,8 @@ struct usb_hub_status {
#define HUB_CHANGE_OVERCURRENT 0x0002
-/*
- * Hub descriptor
+/*
+ * Hub descriptor
* See USB 2.0 spec Table 11-13
*/
@@ -134,7 +134,7 @@ struct usb_hub_descriptor {
__le16 wHubCharacteristics;
__u8 bPwrOn2PwrGood;
__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 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
} __attribute__ ((packed));
@@ -190,6 +190,6 @@ struct usb_tt_clear {
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 */
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index cd4f1115728..83a373e9cc3 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -38,10 +38,15 @@
#include <linux/usbdevice_fs.h>
#include <linux/parser.h>
#include <linux/notifier.h>
+#include <linux/seq_file.h>
#include <asm/byteorder.h>
#include "usb.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 const struct file_operations default_file_operations;
static struct vfsmount *usbfs_mount;
@@ -57,9 +62,33 @@ static uid_t listuid; /* = 0 */
static gid_t devgid; /* = 0 */
static gid_t busgid; /* = 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 {
Opt_devuid, Opt_devgid, Opt_devmode,
@@ -93,9 +122,9 @@ static int parse_options(struct super_block *s, char *data)
devgid = 0;
busgid = 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) {
substring_t args[MAX_OPT_ARGS];
@@ -418,6 +447,7 @@ static struct super_operations usbfs_ops = {
.statfs = simple_statfs,
.drop_inode = generic_delete_inode,
.remount_fs = remount,
+ .show_options = usbfs_show_options,
};
static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fcd40ecbeec..fefb92296e8 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -39,7 +39,7 @@ static void usb_api_blocking_completion(struct urb *urb)
* own interruptible routines.
*/
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
-{
+{
struct api_context ctx;
unsigned long expire;
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,
- unsigned int pipe,
+ unsigned int pipe,
struct usb_ctrlrequest *cmd,
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);
if (!urb)
return -ENOMEM;
-
+
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
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;
-
+
+ dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
if (!dr)
return -ENOMEM;
- dr->bRequestType= requesttype;
+ dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16p(&value);
dr->wIndex = cpu_to_le16p(&index);
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);
@@ -147,7 +151,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
return ret;
}
-
+EXPORT_SYMBOL_GPL(usb_control_msg);
/**
* 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
* @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
+ * @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 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);
/**
- * 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 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);
}
+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) {
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;
}
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;
}
-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;
- spin_lock (&io->lock);
+ spin_lock(&io->lock);
/* In 2.5 we require hcds' endpoint queues not to progress after fault
* reports, until the completion callback (this!) returns. That lets
@@ -276,13 +283,13 @@ static void sg_complete (struct urb *urb)
&& (io->status != -ECONNRESET
|| status != -ECONNRESET)
&& 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",
io->dev->devpath,
usb_endpoint_num(&urb->ep->desc),
usb_urb_dir_in(urb) ? "in" : "out",
status, io->status);
- // BUG ();
+ /* BUG (); */
}
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.
* careful: unlink can sometimes be synchronous...
*/
- spin_unlock (&io->lock);
+ spin_unlock(&io->lock);
for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i] || !io->urbs [i]->dev)
continue;
if (found) {
- retval = usb_unlink_urb (io->urbs [i]);
+ retval = usb_unlink_urb(io->urbs [i]);
if (retval != -EINPROGRESS &&
retval != -ENODEV &&
retval != -EBUSY)
- dev_err (&io->dev->dev,
+ dev_err(&io->dev->dev,
"%s, unlink --> %d\n",
__FUNCTION__, retval);
} else if (urb == io->urbs [i])
found = 1;
}
- spin_lock (&io->lock);
+ spin_lock(&io->lock);
}
urb->dev = NULL;
@@ -317,9 +324,9 @@ static void sg_complete (struct urb *urb)
io->bytes += urb->actual_length;
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
* 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
- || usb_pipecontrol (pipe)
- || usb_pipeisoc (pipe)
+ || usb_pipecontrol(pipe)
+ || usb_pipeisoc(pipe)
|| nents <= 0)
return -EINVAL;
- spin_lock_init (&io->lock);
+ spin_lock_init(&io->lock);
io->dev = dev;
io->pipe = pipe;
io->sg = sg;
@@ -381,7 +381,7 @@ int usb_sg_init (
dma = (dev->dev.dma_mask != NULL);
if (dma)
io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
- sg, nents);
+ sg, nents);
else
io->entries = nents;
@@ -390,30 +390,30 @@ int usb_sg_init (
return 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)
goto nomem;
urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
- if (usb_pipein (pipe))
+ if (usb_pipein(pipe))
urb_flags |= URB_SHORT_NOT_OK;
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;
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
@@ -432,8 +432,8 @@ int usb_sg_init (
* to prevent stale pointers and to help spot bugs.
*/
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)
io->urbs[i]->transfer_buffer = NULL;
#else
@@ -441,31 +441,31 @@ int usb_sg_init (
#endif
} else {
/* 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) {
- len = min_t (unsigned, len, length);
+ len = min_t(unsigned, len, length);
length -= len;
if (length == 0)
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 */
io->status = 0;
io->bytes = 0;
- init_completion (&io->complete);
+ init_completion(&io->complete);
return 0;
nomem:
- sg_clean (io);
+ sg_clean(io);
return -ENOMEM;
}
-
+EXPORT_SYMBOL_GPL(usb_sg_init);
/**
* usb_sg_wait - synchronously execute scatter/gather request
@@ -506,31 +506,32 @@ nomem:
* speed interrupt endpoints, which allow at most one packet per millisecond,
* 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. */
- spin_lock_irq (&io->lock);
+ spin_lock_irq(&io->lock);
i = 0;
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;
* we handshake using io->status.
*/
- spin_unlock_irq (&io->lock);
+ spin_unlock_irq(&io->lock);
switch (retval) {
/* maybe we retrying will recover */
- case -ENXIO: // hc didn't queue this one
+ case -ENXIO: /* hc didn't queue this one */
case -EAGAIN:
case -ENOMEM:
io->urbs[i]->dev = NULL;
retval = 0;
- yield ();
+ yield();
break;
/* no error? continue immediately.
@@ -541,34 +542,35 @@ void usb_sg_wait (struct usb_sg_request *io)
*/
case 0:
++i;
- cpu_relax ();
+ cpu_relax();
break;
/* fail any uncompleted urbs */
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);
- 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))
io->status = retval;
}
io->count -= entries - i;
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.
* So could the submit loop above ... but it's easier to
* 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()
@@ -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,
* 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 */
if (!io->status) {
- int i;
+ int i;
io->status = -ECONNRESET;
- spin_unlock (&io->lock);
+ spin_unlock(&io->lock);
for (i = 0; i < io->entries; i++) {
- int retval;
+ int retval;
if (!io->urbs [i]->dev)
continue;
- retval = usb_unlink_urb (io->urbs [i]);
+ retval = usb_unlink_urb(io->urbs [i]);
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);
}
- 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
* 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 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) {
/* 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;
}
+EXPORT_SYMBOL_GPL(usb_get_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,
- unsigned int index, unsigned char *buf)
+ unsigned int index, unsigned char *buf)
{
int rc;
@@ -751,7 +756,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
- *
+ *
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
* 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) {
err = usb_string_sub(dev, 0, 0, tbuf);
if (err < 0) {
- dev_err (&dev->dev,
+ dev_err(&dev->dev,
"string descriptor 0 read error: %d\n",
err);
goto errout;
} 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;
goto errout;
} else {
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);
}
}
-
+
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
if (err < 0)
goto errout;
@@ -821,12 +826,15 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
err = idx;
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:
kfree(tbuf);
return err;
}
+EXPORT_SYMBOL_GPL(usb_string);
/**
* 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;
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;
memcpy(smallbuf, buf, len);
}
@@ -883,7 +897,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
return -ENOMEM;
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
- if (ret >= 0)
+ if (ret >= 0)
memcpy(&dev->descriptor, desc, size);
kfree(desc);
return ret;
@@ -927,6 +941,7 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
kfree(status);
return ret;
}
+EXPORT_SYMBOL_GPL(usb_get_status);
/**
* 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 endp = usb_pipeendpoint(pipe);
-
- if (usb_pipein (pipe))
+
+ if (usb_pipein(pipe))
endp |= USB_DIR_IN;
/* 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;
}
+EXPORT_SYMBOL_GPL(usb_clear_halt);
/**
* 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
* @dev: the device whose endpoints are being disabled
* @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;
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) {
usb_disable_endpoint(dev, i);
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];
if (!device_is_registered(&interface->dev))
continue;
- dev_dbg (&dev->dev, "unregistering interface %s\n",
+ dev_dbg(&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id);
usb_remove_sysfs_intf_files(interface);
- device_del (&interface->dev);
+ device_del(&interface->dev);
}
/* Now that the interfaces are unbound, nobody should
* try to access them.
*/
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 = 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
* @dev: the device whose interface is being enabled
* @ep: the endpoint
@@ -1116,7 +1131,7 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
ep->enabled = 1;
}
-/*
+/**
* usb_enable_interface - Enable all the endpoints for an interface
* @dev: the device whose interface is being enabled
* @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;
int ret;
int manual = 0;
+ unsigned int epaddr;
+ unsigned int pipe;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
@@ -1226,11 +1243,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
int 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);
}
@@ -1253,6 +1270,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return 0;
}
+EXPORT_SYMBOL_GPL(usb_set_interface);
/**
* usb_reset_configuration - lightweight device reset
@@ -1328,6 +1346,7 @@ int usb_reset_configuration(struct usb_device *dev)
}
return 0;
}
+EXPORT_SYMBOL_GPL(usb_reset_configuration);
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;
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.idProduct),
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,
- 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 *intf_assoc;
@@ -1415,7 +1435,6 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
return retval;
}
-
/*
* usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated
@@ -1533,12 +1552,12 @@ free_interfaces:
* getting rid of old interfaces means unbinding their drivers.
*/
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?
* The device is probably useless now anyway.
*/
@@ -1585,11 +1604,11 @@ free_interfaces:
intf->dev.bus = &usb_bus_type;
intf->dev.type = &usb_if_device_type;
intf->dev.dma_mask = dev->dev.dma_mask;
- device_initialize (&intf->dev);
+ device_initialize(&intf->dev);
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);
@@ -1605,11 +1624,11 @@ free_interfaces:
for (i = 0; i < nintf; ++i) {
struct usb_interface *intf = cp->interface[i];
- dev_dbg (&dev->dev,
+ dev_dbg(&dev->dev,
"adding %s (config #%d, interface %d)\n",
intf->dev.bus_id, configuration,
intf->cur_altsetting->desc.bInterfaceNumber);
- ret = device_add (&intf->dev);
+ ret = device_add(&intf->dev);
if (ret != 0) {
dev_err(&dev->dev, "device_add(%s) --> %d\n",
intf->dev.bus_id, ret);
@@ -1677,22 +1696,3 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
return 0;
}
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);
-
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c
index 6b36897ca15..7542dce3f5a 100644
--- a/drivers/usb/core/notify.c
+++ b/drivers/usb/core/notify.c
@@ -33,7 +33,7 @@ EXPORT_SYMBOL_GPL(usb_register_notify);
* usb_unregister_notify - unregister a notifier callback
* @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.
*/
void usb_unregister_notify(struct notifier_block *nb)
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 7f31a495a25..e8cdce571bb 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -14,7 +14,7 @@
* mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
*
* YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
- */
+ */
static struct usb_device_id whitelist_table [] = {
@@ -55,7 +55,7 @@ static int is_targeted(struct usb_device *dev)
return 1;
/* 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))
return 0;
@@ -86,7 +86,7 @@ static int is_targeted(struct usb_device *dev)
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
- (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+ (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 32bd130b1ee..a37ccbd1e00 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -72,7 +72,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr,
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);
/* String fields */
@@ -249,6 +249,41 @@ static void remove_persist_attributes(struct device *dev)
#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
show_autosuspend(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev = to_usb_device(dev);
@@ -365,6 +400,14 @@ static int add_power_attributes(struct device *dev)
rc = sysfs_add_file_to_group(&dev->kobj,
&dev_attr_level.attr,
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;
}
@@ -372,6 +415,12 @@ static int add_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,
&dev_attr_level.attr,
power_group);
sysfs_remove_file_from_group(&dev->kobj,
@@ -601,21 +650,21 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
/* Interface Accociation Descriptor fields */
#define usb_intf_assoc_attr(field, format_string) \
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) \
{ \
- 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);
-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 */
#define usb_intf_attr(field, format_string) \
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index d05ead20081..9d7e63292c0 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -42,6 +42,7 @@ void usb_init_urb(struct urb *urb)
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
@@ -73,6 +74,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
usb_init_urb(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
@@ -89,6 +91,7 @@ void usb_free_urb(struct urb *urb)
if (urb)
kref_put(&urb->kref, urb_destroy);
}
+EXPORT_SYMBOL_GPL(usb_free_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.
*/
-struct urb * usb_get_urb(struct urb *urb)
+struct urb *usb_get_urb(struct urb *urb)
{
if (urb)
kref_get(&urb->kref);
return urb;
}
+EXPORT_SYMBOL_GPL(usb_get_urb);
/**
* 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
* be indicated later, asynchronously, by calling the completion handler.
* 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.
*
@@ -255,7 +259,7 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
* semaphores), or
* (c) current->state != TASK_RUNNING, this is the case only after
* you've changed it.
- *
+ *
* GFP_NOIO is used in the block io path and error handling of storage
* devices.
*
@@ -284,7 +288,8 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL;
- if (!(dev = urb->dev) || dev->state < USB_STATE_DEFAULT)
+ dev = urb->dev;
+ if ((!dev) || (dev->state < USB_STATE_DEFAULT))
return -ENODEV;
/* 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;
}
- if (urb->number_of_packets <= 0)
+ if (urb->number_of_packets <= 0)
return -EINVAL;
for (n = 0; n < urb->number_of_packets; n++) {
len = urb->iso_frame_desc[n].length;
- if (len < 0 || len > max)
+ if (len < 0 || len > max)
return -EMSGSIZE;
urb->iso_frame_desc[n].status = -EXDEV;
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? */
switch (dev->speed) {
case USB_SPEED_HIGH: /* units are microframes */
- // NOTE usb handles 2^15
+ /* NOTE usb handles 2^15 */
if (urb->interval > (1024 * 8))
urb->interval = 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 (urb->interval > 255)
return -EINVAL;
- // NOTE ohci only handles up to 32
+ /* NOTE ohci only handles up to 32 */
max = 128;
} else {
if (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;
}
break;
@@ -444,6 +449,7 @@ int usb_submit_urb(struct urb *urb, gfp_t 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 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
@@ -553,6 +560,7 @@ void usb_kill_urb(struct urb *urb)
--urb->reject;
mutex_unlock(&reject_mutex);
}
+EXPORT_SYMBOL_GPL(usb_kill_urb);
/**
* 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);
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*/
usb_get_urb(victim);
spin_unlock_irq(&anchor->lock);
@@ -595,11 +604,3 @@ int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
msecs_to_jiffies(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);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8f142370103..4e984060c98 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -96,6 +96,7 @@ struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
return NULL;
}
+EXPORT_SYMBOL_GPL(usb_ifnum_to_if);
/**
* 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
* 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;
@@ -126,13 +128,14 @@ struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *
}
return NULL;
}
+EXPORT_SYMBOL_GPL(usb_altnum_to_altsetting);
struct find_interface_arg {
int minor;
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 usb_interface *intf;
@@ -154,7 +157,7 @@ static int __find_interface(struct device * dev, void * data)
* @drv: the driver whose current configuration is considered
* @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
* USB major number.
*/
@@ -170,6 +173,7 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
__find_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.
@@ -230,7 +234,7 @@ static int ksuspend_usb_init(void)
* singlethreaded. Its job doesn't justify running on more
* than one CPU.
*/
- ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
+ ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd");
if (!ksuspend_usb_wq)
return -ENOMEM;
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.
*/
-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_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);
INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
dev->autosuspend_delay = usb_autosuspend_delay * HZ;
+ dev->connect_time = jiffies;
+ dev->active_duration = -jiffies;
#endif
if (root_hub) /* Root hub always ok [and always wired] */
dev->authorized = 1;
@@ -367,6 +373,7 @@ struct usb_device *usb_get_dev(struct usb_device *dev)
get_device(&dev->dev);
return dev;
}
+EXPORT_SYMBOL_GPL(usb_get_dev);
/**
* 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)
put_device(&dev->dev);
}
+EXPORT_SYMBOL_GPL(usb_put_dev);
/**
* 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);
return intf;
}
+EXPORT_SYMBOL_GPL(usb_get_intf);
/**
* 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)
put_device(&intf->dev);
}
-
+EXPORT_SYMBOL_GPL(usb_put_intf);
/* USB device locking
*
@@ -461,11 +470,11 @@ int usb_lock_device_for_reset(struct usb_device *udev,
return -EHOSTUNREACH;
if (iface) {
switch (iface->condition) {
- case USB_INTERFACE_BINDING:
+ case USB_INTERFACE_BINDING:
return 0;
- case USB_INTERFACE_BOUND:
+ case USB_INTERFACE_BOUND:
break;
- default:
+ default:
return -EINTR;
}
}
@@ -487,7 +496,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
return 1;
}
-
+EXPORT_SYMBOL_GPL(usb_lock_device_for_reset);
static struct usb_device *match_device(struct usb_device *dev,
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 usb_bus *bus;
struct usb_device *dev = NULL;
-
+
mutex_lock(&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
- buslist != &usb_bus_list;
+ buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list);
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);
}
+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,
- unsigned char type, void **ptr)
+ unsigned char type, void **ptr)
{
struct usb_descriptor_header *header;
@@ -595,7 +605,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
printk(KERN_ERR
"%s: bogus descriptor, type %d length %d\n",
usbcore_name,
- header->bDescriptorType,
+ header->bDescriptorType,
header->bLength);
return -1;
}
@@ -610,6 +620,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
}
return -1;
}
+EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
/**
* 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().
*/
-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)
return NULL;
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()
@@ -656,12 +664,8 @@ void *usb_buffer_alloc(
* been allocated using usb_buffer_alloc(), and the parameters must match
* 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)
return;
@@ -669,6 +673,7 @@ void usb_buffer_free(
return;
hcd_buffer_free(dev->bus, size, addr, dma);
}
+EXPORT_SYMBOL_GPL(usb_buffer_free);
/**
* 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,
sizeof(struct usb_ctrlrequest),
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
urb->transfer_dma = ~0;
urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
return urb;
}
+EXPORT_SYMBOL_GPL(usb_buffer_map);
#endif /* 0 */
/* 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);
}
}
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync);
#endif
/**
@@ -788,6 +795,7 @@ void usb_buffer_unmap(struct urb *urb)
urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
}
+EXPORT_SYMBOL_GPL(usb_buffer_unmap);
#endif /* 0 */
/**
@@ -828,10 +836,11 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in,
|| !controller->dma_mask)
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,
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 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,
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
+EXPORT_SYMBOL_GPL(usb_buffer_dmasync_sg);
#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,
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 */
__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
@@ -902,6 +913,7 @@ int usb_disabled(void)
{
return nousb;
}
+EXPORT_SYMBOL_GPL(usb_disabled);
/*
* Init
@@ -918,7 +930,7 @@ static int __init usb_init(void)
if (retval)
goto out;
retval = bus_register(&usb_bus_type);
- if (retval)
+ if (retval)
goto bus_register_failed;
retval = usb_host_init();
if (retval)
@@ -983,45 +995,4 @@ static void __exit usb_exit(void)
subsys_initcall(usb_init);
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");
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index c52626c51f7..2375194a9d4 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -1,22 +1,23 @@
/* 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);
extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
extern void usb_enable_endpoint(struct usb_device *dev,
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);
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 int usb_get_device_descriptor(struct usb_device *dev,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 77a3759d6fc..c1395516468 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -12,10 +12,9 @@
# 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).
#
-menu "USB Gadget Support"
-config USB_GADGET
- tristate "Support for USB Gadgets"
+menuconfig USB_GADGET
+ tristate "USB Gadget Support"
help
USB is a master/slave protocol, organized with one master
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
the kernel DocBook documentation for this API.
+if USB_GADGET
+
config USB_GADGET_DEBUG
boolean "Debugging messages"
depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
@@ -220,6 +221,16 @@ config USB_M66592
default USB_GADGET
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
boolean "Toshiba TC86C001 'Goku-S'"
depends on PCI
@@ -538,6 +549,20 @@ config USB_MIDI_GADGET
Say "y" to link the driver statically, or "m" to build a
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
# or video class gadget drivers), or specific hardware, here.
@@ -546,4 +571,4 @@ config USB_MIDI_GADGET
endchoice
-endmenu
+endif # USB_GADGET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 904e57bf611..c3aab80b6c7 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -28,6 +28,8 @@ g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o usbstring.o config.o \
epautoconf.o
+g_printer-objs := printer.o usbstring.o config.o \
+ epautoconf.o
ifeq ($(CONFIG_USB_ETH_RNDIS),y)
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_FILE_STORAGE) += g_file_storage.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
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index c72e9620bf8..b663f23f264 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/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 */
if (!ep->in) {
if (!use_dma && udc_rxfifo_pending) {
- DBG(dev, "udc_queue(): pending bytes in"
+ DBG(dev, "udc_queue(): pending bytes in "
"rxfifo after nyet\n");
/*
* 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);
driver->unbind(&dev->gadget);
+ dev->gadget.dev.driver = NULL;
dev->driver = NULL;
/* set SD */
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index cd62b029d17..a83e8b798ec 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -21,8 +21,7 @@
* Boston, MA 02111-1307, USA.
*/
-#undef DEBUG
-#undef VERBOSE
+#undef VERBOSE_DEBUG
#undef PACKET_TRACE
#include <linux/kernel.h>
@@ -46,8 +45,8 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
+#include <asm/gpio.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>
#include <asm/arch/at91sam9261_matrix.h>
@@ -580,7 +579,7 @@ static int at91_ep_disable (struct usb_ep * _ep)
*/
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;
@@ -881,6 +880,8 @@ static void clk_off(struct at91_udc *udc)
*/
static void pullup(struct at91_udc *udc, int is_on)
{
+ int active = !udc->board.pullup_active_low;
+
if (!udc->enabled || !udc->vbus)
is_on = 0;
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_TXVC, 0);
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()) {
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_TXVC, AT91_UDP_TXVC_TXVDIS);
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()) {
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:
tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
ep = &udc->ep[tmp];
- if (tmp > NUM_ENDPOINTS || (tmp && !ep->desc))
+ if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
goto stall;
if (tmp) {
@@ -1176,7 +1177,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_SET_FEATURE:
tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
ep = &udc->ep[tmp];
- if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+ if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
goto stall;
if (!ep->desc || ep->is_iso)
goto stall;
@@ -1195,7 +1196,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_CLEAR_FEATURE:
tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
ep = &udc->ep[tmp];
- if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS)
+ if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
goto stall;
if (tmp == 0)
goto succeed;
@@ -1551,7 +1552,7 @@ static irqreturn_t at91_vbus_irq(int irq, void *_udc)
/* vbus needs at least brief debouncing */
udelay(10);
- value = at91_get_gpio_value(udc->board.vbus_pin);
+ value = gpio_get_value(udc->board.vbus_pin);
if (value != udc->vbus)
at91_vbus_session(&udc->gadget, value);
@@ -1616,6 +1617,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
local_irq_enable();
driver->unbind(&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+ udc->gadget.dev.driver_data = NULL;
udc->driver = NULL;
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) {
- DBG("invalid num_resources");
+ DBG("invalid num_resources\n");
return -ENODEV;
}
if ((pdev->resource[0].flags != IORESOURCE_MEM)
|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
- DBG("invalid resource type");
+ DBG("invalid resource type\n");
return -ENODEV;
}
@@ -1672,10 +1675,26 @@ static int __init at91udc_probe(struct platform_device *pdev)
udc->pdev = pdev;
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);
if (!udc->udp_baseaddr) {
- release_mem_region(res->start, res->end - res->start + 1);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto fail0a;
}
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)) {
DBG("clocks missing\n");
retval = -ENODEV;
- goto fail0;
+ /* NOTE: we "know" here that refcounts on these are NOPs */
+ goto fail0b;
}
retval = device_register(&udc->gadget.dev);
if (retval < 0)
- goto fail0;
+ goto fail0b;
/* don't do anything until we have both gadget driver and VBUS */
clk_enable(udc->iclk);
@@ -1703,25 +1723,32 @@ static int __init at91udc_probe(struct platform_device *pdev)
/* request UDC and maybe VBUS irqs */
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);
- retval = -EBUSY;
goto fail1;
}
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
* 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,
IRQF_DISABLED, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
udc->board.vbus_pin);
free_irq(udc->udp_irq, udc);
retval = -EBUSY;
- goto fail1;
+ goto fail3;
}
} else {
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);
return 0;
+fail3:
+ if (udc->board.vbus_pin > 0)
+ gpio_free(udc->board.vbus_pin);
+fail2:
+ free_irq(udc->udp_irq, udc);
fail1:
device_unregister(&udc->gadget.dev);
+fail0b:
+ iounmap(udc->udp_baseaddr);
+fail0a:
+ if (cpu_is_at91rm9200())
+ gpio_free(udc->board.pullup_pin);
fail0:
release_mem_region(res->start, res->end - res->start + 1);
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);
remove_debug_file(udc);
- if (udc->board.vbus_pin > 0)
+ if (udc->board.vbus_pin > 0) {
free_irq(udc->board.vbus_pin, udc);
+ gpio_free(udc->board.vbus_pin);
+ }
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
iounmap(udc->udp_baseaddr);
+
+ if (cpu_is_at91rm9200())
+ gpio_free(udc->board.pullup_pin);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, res->end - res->start + 1);
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 7e34e2f864f..a973f2a50fb 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -53,7 +53,7 @@
#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_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_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
#else
# define VDBG(stuff...) do{}while(0)
@@ -176,9 +170,10 @@ struct at91_request {
# define PACKET(stuff...) do{}while(0)
#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
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 4fb5ff46957..af8b2a3a2d4 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1384,8 +1384,7 @@ delegate:
return retval;
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",
ep->ep.name, crq->bRequestType, crq->bRequest,
le16_to_cpu(crq->wValue), le16_to_cpu(crq->wIndex),
@@ -1456,8 +1455,7 @@ restart:
set_protocol_stall(udc, ep);
break;
default:
- printk(KERN_ERR
- "udc: %s: TXCOMP: Invalid endpoint state %d, "
+ pr_err("udc: %s: TXCOMP: Invalid endpoint state %d, "
"halting endpoint...\n",
ep->ep.name, ep->state);
set_protocol_stall(udc, ep);
@@ -1486,8 +1484,7 @@ restart:
default:
usba_ep_writel(ep, CLR_STA, 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",
ep->ep.name, ep->state);
set_protocol_stall(udc, ep);
@@ -1532,7 +1529,7 @@ restart:
pkt_len = USBA_BFEXT(BYTE_COUNT, usba_ep_readl(ep, STA));
DBG(DBG_HW, "Packet length: %u\n", pkt_len);
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));
set_protocol_stall(udc, ep);
return;
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index a68304e31a6..08bf6f9aaf7 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -216,7 +216,6 @@
#define FIFO_IOMEM_ID 0
#define CTRL_IOMEM_ID 1
-#ifdef DEBUG
#define DBG_ERR 0x0001 /* report all error returns */
#define DBG_HW 0x0002 /* debug hardware initialization */
#define DBG_GADGET 0x0004 /* calls to/from gadget driver */
@@ -230,14 +229,12 @@
#define DBG_NONE 0x0000
#define DEBUG_LEVEL (DBG_ERR)
+
#define DBG(level, fmt, ...) \
do { \
if ((level) & DEBUG_LEVEL) \
- printk(KERN_DEBUG "udc: " fmt, ## __VA_ARGS__); \
+ pr_debug("udc: " fmt, ## __VA_ARGS__); \
} while (0)
-#else
-#define DBG(level, fmt...)
-#endif
enum usba_ctrl_state {
WAIT_FOR_SETUP,
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 9db2482bdfa..cbe44535c0f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -61,6 +61,8 @@
#define DRIVER_DESC "USB Host+Gadget Emulator"
#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_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);
INIT_LIST_HEAD(&dum->fifo_req.queue);
+ driver->driver.bus = NULL;
dum->driver = driver;
dum->gadget.dev.driver = &driver->driver;
dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n",
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 */
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));
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);
@@ -830,11 +817,9 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
spin_unlock_irqrestore (&dum->lock, flags);
driver->unbind (&dum->gadget);
+ dum->gadget.dev.driver = NULL;
dum->driver = NULL;
- device_release_driver (&dum->gadget.dev);
- driver_unregister (&driver->driver);
-
spin_lock_irqsave (&dum->lock, flags);
dum->pullup = 0;
set_link_state (dum);
@@ -1827,8 +1812,7 @@ static int dummy_start (struct usb_hcd *hcd)
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->uses_new_polling = 1;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 9e732bff9df..a70e255402b 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1067,19 +1067,19 @@ done:
/* on error, disable any endpoints */
if (result < 0) {
- if (!subset_active(dev))
+ if (!subset_active(dev) && dev->status_ep)
(void) usb_ep_disable (dev->status_ep);
dev->status = NULL;
(void) usb_ep_disable (dev->in_ep);
(void) usb_ep_disable (dev->out_ep);
dev->in = NULL;
dev->out = NULL;
- } else
+ }
/* activate non-CDC configs right away
* this isn't strictly according to the RNDIS spec
*/
- if (!cdc_active (dev)) {
+ else if (!cdc_active (dev)) {
netif_carrier_on (dev->net);
if (netif_running (dev->net)) {
spin_unlock (&dev->lock);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 1d174dcb3ac..3301167d4f2 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -275,19 +275,15 @@ MODULE_LICENSE("Dual BSD/GPL");
/*-------------------------------------------------------------------------*/
-#ifdef DEBUG
#define LDBG(lun,fmt,args...) \
dev_dbg(&(lun)->dev , 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 DUMP_MSGS
-#endif /* DEBUG */
+#endif /* !DEBUG */
#ifdef VERBOSE_DEBUG
#define VLDBG LDBG
@@ -304,7 +300,7 @@ MODULE_LICENSE("Dual BSD/GPL");
dev_info(&(lun)->dev , fmt , ## args)
#define MINFO(fmt,args...) \
- printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
+ pr_info(DRIVER_NAME ": " fmt , ## args)
#define DBG(d, fmt, args...) \
dev_dbg(&(d)->gadget->dev , fmt , ## args)
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 038e7d7b4da..63e8fa3a69e 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/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__);
return -EINVAL;
}
- if (!_ep || (!ep->desc && ep_index(ep))) {
+ if (unlikely(!_ep || !ep->desc)) {
VDBG("%s, bad ep\n", __FUNCTION__);
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);
- /* ------basic driver infomation ---- */
+ /* ------basic driver information ---- */
t = scnprintf(next, size,
DRIVER_DESC "\n"
"%s version: %s\n"
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 832ab82b488..9fb0b1ec852 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/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)
#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)
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 7da7fcb0564..5b42ccd0035 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1158,7 +1158,7 @@ static int __devinit gmidi_bind(struct usb_gadget *gadget)
/* support optional vendor/distro customization */
if (idVendor) {
if (!idProduct) {
- printk(KERN_ERR "idVendor needs idProduct!\n");
+ pr_err("idVendor needs idProduct!\n");
return -ENODEV;
}
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);
if (!in_ep) {
autoconf_fail:
- printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+ pr_err("%s: can't autoconfigure on %s\n",
shortname, gadget->name);
return -ENODEV;
}
@@ -1212,7 +1212,7 @@ autoconf_fail:
* it SHOULD NOT have problems with bulk-capable hardware.
* 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);
device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 2ec9d196a8c..d3e702576de 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/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);
driver->unbind(&dev->gadget);
+ dev->gadget.dev.driver = NULL;
DBG(dev, "unregistered driver '%s'\n", driver->driver.name);
return 0;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 47ef8bd58a0..805602a687c 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1699,7 +1699,7 @@ gadgetfs_bind (struct usb_gadget *gadget)
if (!dev)
return -ESRCH;
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);
return -ENODEV;
}
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 367b75c0b25..37243ef7104 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/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);
driver->unbind(&dev->gadget);
+ dev->gadget.dev.driver = NULL;
device_del(&dev->gadget.dev);
udc_disable(dev);
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ebc5536aa27..835948f0715 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -36,9 +36,14 @@ MODULE_DESCRIPTION("M66592 USB gadget driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yoshihiro Shimoda");
-#define DRIVER_VERSION "29 May 2007"
+#define DRIVER_VERSION "18 Oct 2007"
/* 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;
module_param(clock, ushort, 0644);
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_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 "
"(default=2)");
+#endif
static const char udc_name[] = "m66592_udc";
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);
pid = m66592_read(m66592, offset) & M66592_PID;
} else
- printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+ pr_err("unexpect pipe num (%d)\n", pipenum);
return pid;
}
@@ -157,7 +163,7 @@ static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
offset = get_pipectr_addr(pipenum);
m66592_mdfy(m66592, pid, M66592_PID, offset);
} 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)
@@ -186,7 +192,7 @@ static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
offset = get_pipectr_addr(pipenum);
ret = m66592_read(m66592, offset);
} else
- printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+ pr_err("unexpect pipe num (%d)\n", pipenum);
return ret;
}
@@ -203,7 +209,7 @@ static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
offset = get_pipectr_addr(pipenum);
m66592_bset(m66592, M66592_SQCLR, offset);
} 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)
@@ -285,7 +291,7 @@ static int pipe_buffer_setting(struct m66592 *m66592,
break;
}
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);
return -ENOMEM;
}
@@ -326,7 +332,7 @@ static void pipe_buffer_release(struct m66592 *m66592,
if (info->type == M66592_BULK)
m66592->bulk--;
} else
- printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+ pr_err("ep_release: unexpect pipenum (%d)\n",
info->pipe);
}
@@ -360,6 +366,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
ep->fifosel = M66592_D0FIFOSEL;
ep->fifoctr = M66592_D0FIFOCTR;
ep->fifotrn = M66592_D0FIFOTRN;
+#if !defined(CONFIG_SUPERH_BUILT_IN_M66592)
} else if (m66592->num_dma == 1) {
m66592->num_dma++;
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->fifoctr = M66592_D1FIFOCTR;
ep->fifotrn = M66592_D1FIFOTRN;
+#endif
} else {
ep->use_dma = 0;
ep->fifoaddr = M66592_CFIFO;
@@ -422,7 +430,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
case USB_ENDPOINT_XFER_BULK:
if (m66592->bulk >= M66592_MAX_NUM_BULK) {
if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
- printk(KERN_ERR "bulk pipe is insufficient\n");
+ pr_err("bulk pipe is insufficient\n");
return -ENODEV;
} else {
info.pipe = M66592_BASE_PIPENUM_ISOC
@@ -438,7 +446,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
break;
case USB_ENDPOINT_XFER_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;
}
info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
@@ -447,7 +455,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
break;
case USB_ENDPOINT_XFER_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;
}
info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
@@ -455,7 +463,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
counter = &m66592->isochronous;
break;
default:
- printk(KERN_ERR "unexpect xfer type\n");
+ pr_err("unexpect xfer type\n");
return -EINVAL;
}
ep->type = info.type;
@@ -470,7 +478,7 @@ static int alloc_pipe_config(struct m66592_ep *ep,
ret = pipe_buffer_setting(m66592, &info);
if (ret < 0) {
- printk(KERN_ERR "pipe_buffer_setting fail\n");
+ pr_err("pipe_buffer_setting fail\n");
return ret;
}
@@ -606,11 +614,33 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
control_end(ep->m66592, 0);
break;
default:
- printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+ pr_err("start_ep0: unexpect ctsq(%x)\n", ctsq);
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)
{
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_DMA0CFG);
}
+#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_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);
udelay(1);
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);
udelay(1);
m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+#endif
}
static void m66592_start_xclock(struct m66592 *m66592)
{
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+ usbf_start_clock();
+#else
u16 tmp;
tmp = m66592_read(m66592, M66592_SYSCFG);
if (!(tmp & M66592_XCKE))
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 {
tmp = m66592_read(m66592, ep->fifoctr);
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.");
return;
}
@@ -759,7 +798,7 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
if (unlikely((tmp & M66592_FRDY) == 0)) {
pipe_stop(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;
}
@@ -808,7 +847,7 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
req->req.status = -EPIPE;
pipe_stop(m66592, pipenum);
pipe_irq_disable(m66592, pipenum);
- printk(KERN_ERR "read fifo not ready");
+ pr_err("read fifo not ready");
return;
}
@@ -1063,7 +1102,7 @@ static void m66592_update_usb_speed(struct m66592 *m66592)
break;
default:
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);
break;
default:
- printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+ pr_err("ctrl_stage: unexpect ctsq(%x)\n", ctsq);
break;
}
}
@@ -1142,6 +1181,19 @@ static irqreturn_t m66592_irq(int irq, void *_m66592)
intsts0 = m66592_read(m66592, M66592_INTSTS0);
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);
mask0 = intsts0 & intenb0;
@@ -1409,13 +1461,13 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
retval = device_add(&m66592->gadget.dev);
if (retval) {
- printk(KERN_ERR "device_add error (%d)\n", retval);
+ pr_err("device_add error (%d)\n", retval);
goto error;
}
retval = driver->bind (&m66592->gadget);
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);
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);
driver->unbind(&m66592->gadget);
+ m66592->gadget.dev.driver = NULL;
init_controller(m66592);
disable_controller(m66592);
@@ -1485,6 +1538,7 @@ static int __exit m66592_remove(struct platform_device *pdev)
iounmap(m66592->reg);
free_irq(platform_get_irq(pdev, 0), m66592);
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+ usbf_stop_clock();
kfree(m66592);
return 0;
}
@@ -1508,28 +1562,28 @@ static int __init m66592_probe(struct platform_device *pdev)
(char *)udc_name);
if (!res) {
ret = -ENODEV;
- printk(KERN_ERR "platform_get_resource_byname error.\n");
+ pr_err("platform_get_resource_byname error.\n");
goto clean_up;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = -ENODEV;
- printk(KERN_ERR "platform_get_irq error.\n");
+ pr_err("platform_get_irq error.\n");
goto clean_up;
}
reg = ioremap(res->start, resource_len(res));
if (reg == NULL) {
ret = -ENOMEM;
- printk(KERN_ERR "ioremap error.\n");
+ pr_err("ioremap error.\n");
goto clean_up;
}
/* initialize ucd */
m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
if (m66592 == NULL) {
- printk(KERN_ERR "kzalloc error\n");
+ pr_err("kzalloc error\n");
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,
udc_name, m66592);
if (ret < 0) {
- printk(KERN_ERR "request_irq error (%d)\n", ret);
+ pr_err("request_irq error (%d)\n", ret);
goto clean_up;
}
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
index bfa0c645f22..17b792b7f6b 100644
--- a/drivers/usb/gadget/m66592-udc.h
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -72,6 +72,11 @@
#define M66592_P_TST_J 0x0001 /* PERI TEST J */
#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_LDRV 0x8000 /* b15: Drive Current Adjust */
#define M66592_BIGEND 0x0100 /* b8: Big endian mode */
@@ -91,6 +96,7 @@
#define M66592_PKTM 0x0020 /* b5: Packet mode */
#define M66592_DENDE 0x0010 /* b4: Dend enable */
#define M66592_OBUS 0x0004 /* b2: OUTbus mode */
+#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#define M66592_CFIFO 0x10
#define M66592_D0FIFO 0x14
@@ -103,9 +109,13 @@
#define M66592_REW 0x4000 /* b14: Buffer rewind */
#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */
#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_8 0x0000 /* 8bit */
#define M66592_MBW_16 0x0400 /* 16bit */
+#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */
#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */
#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;
+#if defined(CONFIG_SUPERH_BUILT_IN_M66592)
+ len = (len + 3) / 4;
+ insl(fifoaddr, buf, len);
+#else
len = (len + 1) / 2;
insw(fifoaddr, buf, len);
+#endif
}
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)
{
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;
len = len / 2;
@@ -553,6 +586,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592,
unsigned char *p = buf + len*2;
outb(*p, fifoaddr);
}
+#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */
}
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) \
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__ */
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index d5d473f8144..33469cf5aec 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2435,7 +2435,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
break;
default:
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",
u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length,
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index d377154658b..e6d68bda428 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -4,6 +4,8 @@
* Copyright (C) 2004 Texas Instruments, Inc.
* 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
* it under the terms of the GNU General Public License as published by
* 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 */
#define USE_DMA
-/* FIXME: OMAP2 currently has some problem in DMA mode */
-#ifdef CONFIG_ARCH_OMAP2
-#undef USE_DMA
-#endif
-
/* ISO too */
#define USE_ISO
@@ -73,6 +70,8 @@
#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
@@ -571,20 +570,25 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
const int sync_mode = cpu_is_omap15xx()
? OMAP_DMA_SYNC_FRAME
: 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 */
if ((cpu_is_omap16xx() && length <= UDC_TXN_TSC)
+ || (cpu_is_omap24xx() && length < ep->maxpacket)
|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
txdma_ctrl = UDC_TXN_EOT | length;
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 {
length = min(length / ep->maxpacket,
(unsigned) UDC_TXN_TSC + 1);
txdma_ctrl = length;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
ep->ep.maxpacket >> 1, length, sync_mode,
- 0, 0);
+ dma_trigger, 0);
length *= ep->maxpacket;
}
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)
{
- 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
* 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_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
0, 0);
@@ -743,6 +758,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
{
u16 reg;
int status, restart, is_in;
+ int dma_channel;
is_in = ep->bEndpointAddress & USB_DIR_IN;
if (is_in)
@@ -769,11 +785,15 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
ep->dma_channel = channel;
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);
if (status == 0) {
UDC_TXDMA_CFG_REG = reg;
- /* EMIFF */
+ /* EMIFF or SDRC */
omap_set_dma_src_burst_mode(ep->lch,
OMAP_DMA_DATA_BURST_4);
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);
}
} 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);
if (status == 0) {
UDC_RXDMA_CFG_REG = reg;
@@ -795,7 +820,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
OMAP_DMA_AMODE_CONSTANT,
(unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
0, 0);
- /* EMIFF */
+ /* EMIFF or SDRC */
omap_set_dma_dest_burst_mode(ep->lch,
OMAP_DMA_DATA_BURST_4);
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);
/* 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;
}
@@ -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
* have a hard time with partial packet reads... reject it.
+ * Except OMAP2 can handle the small packets.
*/
if (use_dma
&& ep->has_dma
&& ep->bEndpointAddress != 0
&& (ep->bEndpointAddress & USB_DIR_IN) == 0
+ && !cpu_class_is_omap2()
&& (req->req.length % ep->ep.maxpacket) != 0) {
DBG("%s, no partial packet OUT reads\n", __FUNCTION__);
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
* 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_CTRL_REG = UDC_CLR_EP;
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 1dc398bb9ab..c6b9cbc7230 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/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
# define VDBG DBG
#else
# define VDBG(stuff...) do{}while(0)
#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)
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
new file mode 100644
index 00000000000..9fdabc8fcac
--- /dev/null
+++ b/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);
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 3173b39f0bf..4402d6f042d 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -24,7 +24,7 @@
*
*/
-// #define VERBOSE DBG_VERBOSE
+/* #define VERBOSE_DEBUG */
#include <linux/device.h>
#include <linux/module.h>
@@ -38,13 +38,14 @@
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
#include <asm/byteorder.h>
#include <asm/dma.h>
@@ -127,8 +128,10 @@ static int is_vbus_present(void)
{
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)
return mach->udc_is_connected();
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? */
if (list_empty(&ep->queue) && !ep->stopped) {
- if (ep->desc == 0 /* ep0 */) {
+ if (ep->desc == NULL/* ep0 */) {
unsigned length = _req->length;
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. */
- if (likely (req != 0))
+ if (likely(req != NULL))
list_add_tail(&req->queue, &ep->queue);
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
-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;
- int i, t;
+ int i;
u32 tmp;
- if (off != 0)
- return 0;
-
local_irq_save(flags);
/* 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",
driver_name, DRIVER_VERSION SIZE_STR "(pio)",
dev->driver ? dev->driver->driver.name : "(none)",
is_vbus_present() ? "full speed" : "disconnected");
- size -= t;
- next += t;
/* registers for device and ep0 */
- t = scnprintf(next, size,
+ seq_printf(m,
"uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n",
UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
- size -= t;
- next += t;
tmp = UDCCR;
- t = scnprintf(next, size,
+ seq_printf(m,
"udccr %02X =%s%s%s%s%s%s%s%s\n", tmp,
(tmp & UDCCR_REM) ? " rem" : "",
(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_UDA) ? " uda" : "",
(tmp & UDCCR_UDE) ? " ude" : "");
- size -= t;
- next += t;
tmp = UDCCS0;
- t = scnprintf(next, size,
+ seq_printf(m,
"udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp,
(tmp & UDCCS0_SA) ? " sa" : "",
(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_IPR) ? " ipr" : "",
(tmp & UDCCS0_OPR) ? " opr" : "");
- size -= t;
- next += t;
if (dev->has_cfr) {
tmp = UDCCFR;
- t = scnprintf(next, size,
+ seq_printf(m,
"udccfr %02X =%s%s\n", tmp,
(tmp & UDCCFR_AREN) ? " aren" : "",
(tmp & UDCCFR_ACM) ? " acm" : "");
- size -= t;
- next += t;
}
if (!is_vbus_present() || !dev->driver)
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.read.bytes, dev->stats.read.ops,
dev->stats.irqs);
- size -= t;
- next += t;
/* dump endpoint queues */
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;
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;
tmp = *dev->ep [i].reg_udccs;
- t = scnprintf(next, size,
+ seq_printf(m,
"%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);
/* TODO translate all five groups of udccs bits! */
} 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);
- if (t <= 0 || t > size)
- goto done;
- size -= t;
- next += t;
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;
}
list_for_each_entry(req, &ep->queue, queue) {
- t = scnprintf(next, size,
+ seq_printf(m,
"\treq %p len %d/%d buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
- if (t <= 0 || t > size)
- goto done;
- size -= t;
- next += t;
}
}
done:
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 */
-#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 */
@@ -1345,6 +1334,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
local_irq_enable();
driver->unbind(&dev->gadget);
+ dev->gadget.dev.driver = NULL;
dev->driver = NULL;
device_del (&dev->gadget.dev);
@@ -1397,6 +1387,9 @@ static irqreturn_t udc_vbus_irq(int irq, void *_dev)
struct pxa2xx_udc *dev = _dev;
int vbus = gpio_get_value(dev->mach->gpio_vbus);
+ if (dev->mach->gpio_vbus_inverted)
+ vbus = !vbus;
+
pxa2xx_udc_vbus_session(&dev->gadget, vbus);
return IRQ_HANDLED;
}
@@ -2099,7 +2092,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
/* insist on Intel/ARM/XScale */
asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
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;
}
@@ -2128,7 +2121,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
break;
#endif
default:
- printk(KERN_ERR "%s: unrecognized processor: %08x\n",
+ pr_err("%s: unrecognized processor: %08x\n",
driver_name, chiprev);
/* iop3xx, ixp4xx, ... */
return -ENODEV;
@@ -2199,7 +2192,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
retval = request_irq(irq, pxa2xx_udc_irq,
IRQF_DISABLED, driver_name, dev);
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);
goto err_irq1;
}
@@ -2212,7 +2205,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
driver_name, dev);
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);
lubbock_fail0:
goto err_irq_lub;
@@ -2222,7 +2215,7 @@ lubbock_fail0:
IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
driver_name, dev);
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);
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
goto lubbock_fail0;
@@ -2235,12 +2228,12 @@ lubbock_fail0:
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
driver_name, dev);
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);
goto err_vbus_irq;
}
}
- create_proc_files();
+ create_debug_files(dev);
return 0;
@@ -2277,7 +2270,7 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
return -EBUSY;
udc_disable(dev);
- remove_proc_files();
+ remove_debug_files(dev);
if (dev->got_irq) {
free_irq(platform_get_irq(pdev, 0), dev);
@@ -2361,7 +2354,7 @@ static struct platform_driver udc_driver = {
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);
}
module_init(udc_init);
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 1db46d70577..b67e3ff5e4e 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -129,6 +129,10 @@ struct pxa2xx_udc {
struct pxa2xx_udc_mach_info *mach;
u64 dma_mask;
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_VERY_NOISY 4 /* ... even more: packet level */
+#define DMSG(stuff...) pr_debug("udc: " stuff)
+
#ifdef DEBUG
+static int is_vbus_present(void);
+
static const char *state_name[] = {
"EP0_IDLE",
"EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE",
"EP0_END_XFER", "EP0_STALL"
};
-#define DMSG(stuff...) printk(KERN_DEBUG "udc: " stuff)
-
-#ifdef VERBOSE
+#ifdef VERBOSE_DEBUG
# define UDC_DEBUG DBG_VERBOSE
#else
# define UDC_DEBUG DBG_NORMAL
@@ -207,7 +213,7 @@ dump_state(struct pxa2xx_udc *dev)
unsigned i;
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],
UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL);
dump_udccr("udccr");
@@ -224,7 +230,7 @@ dump_state(struct pxa2xx_udc *dev)
} else
DMSG("ep0 driver '%s'\n", dev->driver->driver.name);
- if (!is_usb_connected())
+ if (!is_vbus_present())
return;
dump_udccs0 ("udccs0");
@@ -233,7 +239,7 @@ dump_state(struct pxa2xx_udc *dev)
dev->stats.read.bytes, dev->stats.read.ops);
for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
- if (dev->ep [i].desc == 0)
+ if (dev->ep [i].desc == NULL)
continue;
DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
}
@@ -241,8 +247,6 @@ dump_state(struct pxa2xx_udc *dev)
#else
-#define DMSG(stuff...) do{}while(0)
-
#define dump_udccr(x) do{}while(0)
#define dump_udccs0(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 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 */
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index db1b2bfcee4..3d036647431 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -53,21 +53,18 @@
*/
#if 0
-#define DBG(str,args...) do { \
- if (rndis_debug) \
- printk(KERN_DEBUG str , ## args ); \
- } while (0)
static int rndis_debug = 0;
-
module_param (rndis_debug, int, 0);
MODULE_PARM_DESC (rndis_debug, "enable debugging");
-
#else
-
#define rndis_debug 0
-#define DBG(str,args...) do{}while(0)
#endif
+#define DBG(str,args...) do { \
+ if (rndis_debug) \
+ pr_debug(str , ## args); \
+ } while (0)
+
#define RNDIS_MAX_CONFIGS 1
@@ -679,7 +676,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
#endif
default:
- printk (KERN_WARNING "%s: query unknown OID 0x%08X\n",
+ pr_warning("%s: query unknown OID 0x%08X\n",
__FUNCTION__, OID);
}
if (retval < 0)
@@ -804,7 +801,7 @@ update_linkstate:
#endif /* RNDIS_PM */
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);
}
@@ -1126,8 +1123,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
* In one case those messages seemed to relate to the host
* 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);
{
unsigned i;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index 4ce050c3d13..aadc4204d6f 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/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
*/
-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;
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 */
udc_write(idx, S3C2410_UDC_INDEX_REG);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f5738eb8e76..f5c3896b1d9 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -89,9 +89,9 @@ static int debug = 1;
#endif
#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...) \
- 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.
@@ -553,7 +553,8 @@ static int __init gs_module_init(void)
retval = usb_gadget_register_driver(&gs_gadget_driver);
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;
}
@@ -579,11 +580,13 @@ static int __init gs_module_init(void)
if (retval) {
usb_gadget_unregister_driver(&gs_gadget_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;
}
- 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;
}
@@ -598,7 +601,8 @@ static void __exit gs_module_exit(void)
put_tty_driver(gs_tty_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 */
@@ -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);
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);
return -ENODEV;
}
@@ -629,15 +633,14 @@ static int gs_open(struct tty_struct *tty, struct file *file)
dev = gs_device;
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);
return -ENODEV;
}
mtx = &gs_open_close_lock[port_num];
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);
return -ERESTARTSYS;
}
@@ -645,8 +648,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
spin_lock_irqsave(&dev->dev_lock, flags);
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);
ret = -ENODEV;
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];
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);
ret = -ENODEV;
goto exit_unlock_dev;
@@ -665,7 +667,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
spin_unlock(&dev->dev_lock);
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);
ret = -EIO;
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 */
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->port_in_use = 0;
ret = -EIO;
@@ -701,7 +702,8 @@ static int gs_open(struct tty_struct *tty, struct file *file)
}
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->port_in_use = 0;
ret = -ENOMEM;
@@ -714,7 +716,7 @@ static int gs_open(struct tty_struct *tty, struct file *file)
/* might have been disconnected while asleep, check */
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->port_in_use = 0;
ret = -EIO;
@@ -762,7 +764,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
struct mutex *mtx;
if (port == NULL) {
- printk(KERN_ERR "gs_close: NULL port pointer\n");
+ pr_err("gs_close: NULL port pointer\n");
return;
}
@@ -774,8 +776,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
spin_lock_irq(&port->port_lock);
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);
goto exit;
}
@@ -837,7 +838,7 @@ static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
int ret;
if (port == NULL) {
- printk(KERN_ERR "gs_write: NULL port pointer\n");
+ pr_err("gs_write: NULL port pointer\n");
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);
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);
ret = -EIO;
goto exit;
}
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);
ret = -EBADF;
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;
if (port == NULL) {
- printk(KERN_ERR "gs_put_char: NULL port pointer\n");
+ pr_err("gs_put_char: NULL port pointer\n");
return;
}
@@ -898,13 +899,13 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
spin_lock_irqsave(&port->port_lock, flags);
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);
goto exit;
}
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);
goto exit;
}
@@ -924,7 +925,7 @@ static void gs_flush_chars(struct tty_struct *tty)
struct gs_port *port = tty->driver_data;
if (port == NULL) {
- printk(KERN_ERR "gs_flush_chars: NULL port pointer\n");
+ pr_err("gs_flush_chars: NULL port pointer\n");
return;
}
@@ -933,14 +934,13 @@ static void gs_flush_chars(struct tty_struct *tty)
spin_lock_irqsave(&port->port_lock, flags);
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);
goto exit;
}
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);
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;
if (port == NULL) {
- printk(KERN_ERR "gs_ioctl: NULL port pointer\n");
+ pr_err("gs_ioctl: NULL port pointer\n");
return -EIO;
}
@@ -1076,7 +1076,7 @@ static int gs_send(struct gs_dev *dev)
struct gs_req_entry *req_entry;
if (dev == NULL) {
- printk(KERN_ERR "gs_send: NULL device pointer\n");
+ pr_err("gs_send: NULL device pointer\n");
return -ENODEV;
}
@@ -1103,7 +1103,7 @@ static int gs_send(struct gs_dev *dev)
req->length = len;
spin_unlock_irqrestore(&dev->dev_lock, flags);
if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
- printk(KERN_ERR
+ pr_err(
"gs_send: cannot queue read request, ret=%d\n",
ret);
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];
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;
}
@@ -1193,7 +1191,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
port = dev->dev_port[0];
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);
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);
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);
ret = -EIO;
goto exit;
@@ -1211,14 +1209,14 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
tty = port->port_tty;
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);
ret = -EIO;
goto exit;
}
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);
ret = -EIO;
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;
if (dev == NULL) {
- printk(KERN_ERR "gs_read_complete: NULL device pointer\n");
+ pr_err("gs_read_complete: NULL device pointer\n");
return;
}
@@ -1256,7 +1254,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
requeue:
req->length = ep->maxpacket;
if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
- printk(KERN_ERR
+ pr_err(
"gs_read_complete: cannot queue read request, ret=%d\n",
ret);
}
@@ -1270,7 +1268,7 @@ requeue:
default:
/* unexpected */
- printk(KERN_ERR
+ pr_err(
"gs_read_complete: unexpected status error, status=%d\n",
req->status);
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;
if (dev == NULL) {
- printk(KERN_ERR "gs_write_complete: NULL device pointer\n");
+ pr_err("gs_write_complete: NULL device pointer\n");
return;
}
@@ -1296,8 +1294,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
/* normal completion */
requeue:
if (gs_req == NULL) {
- printk(KERN_ERR
- "gs_write_complete: NULL request pointer\n");
+ pr_err("gs_write_complete: NULL request pointer\n");
return;
}
@@ -1316,7 +1313,7 @@ requeue:
break;
default:
- printk(KERN_ERR
+ pr_err(
"gs_write_complete: unexpected status error, status=%d\n",
req->status);
goto requeue;
@@ -1351,7 +1348,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
gs_device_desc.bcdDevice =
cpu_to_le16(GS_VERSION_NUM | gcnum);
else {
- printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
+ pr_warning("gs_bind: controller '%s' not recognized\n",
gadget->name);
/* unrecognized, but safe unless bulk is REALLY quirky */
gs_device_desc.bcdDevice =
@@ -1375,7 +1372,7 @@ static int __init gs_bind(struct usb_gadget *gadget)
if (use_acm) {
ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
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;
}
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);
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);
return ret;
}
@@ -1441,13 +1438,13 @@ static int __init gs_bind(struct usb_gadget *gadget)
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);
return 0;
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;
}
@@ -1480,7 +1477,7 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
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);
}
@@ -1513,7 +1510,8 @@ static int gs_setup(struct usb_gadget *gadget,
break;
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,
wValue, wIndex, wLength);
break;
@@ -1526,7 +1524,7 @@ static int gs_setup(struct usb_gadget *gadget,
&& (ret % gadget->ep0->maxpacket) == 0;
ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
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);
req->status = 0;
gs_setup_complete(gadget->ep0, req);
@@ -1656,7 +1654,8 @@ set_interface_done:
break;
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,
wValue, wIndex, wLength);
break;
@@ -1682,7 +1681,7 @@ static int gs_setup_class(struct usb_gadget *gadget,
* handler copy that data to port->port_line_coding (iff
* 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");
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
* 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");
break;
default:
- printk(KERN_ERR "gs_setup: unknown class request, "
+ pr_err("gs_setup: unknown class request, "
"type=%02x, request=%02x, value=%04x, "
"index=%04x, length=%d\n",
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)
{
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);
}
}
@@ -1751,11 +1751,11 @@ static void gs_disconnect(struct usb_gadget *gadget)
/* re-allocate ports for the next connection */
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);
- 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;
if (dev == NULL) {
- printk(KERN_ERR "gs_set_config: NULL device pointer\n");
+ pr_err("gs_set_config: NULL device pointer\n");
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_desc = ep_desc;
} 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);
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_desc = ep_desc;
} 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);
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_desc = ep_desc;
} 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);
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
|| (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;
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))) {
req->complete = gs_read_complete;
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 {
- printk(KERN_ERR "gs_set_config: cannot allocate read requests\n");
+ pr_err("gs_set_config: cannot allocate "
+ "read requests\n");
ret = -ENOMEM;
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;
list_add(&req_entry->re_entry, &dev->dev_req_list);
} else {
- printk(KERN_ERR "gs_set_config: cannot allocate write requests\n");
+ pr_err("gs_set_config: cannot allocate "
+ "write requests\n");
ret = -ENOMEM;
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,
gadget->speed == USB_SPEED_HIGH ? "high" : "full",
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;
if (dev == NULL) {
- printk(KERN_ERR "gs_reset_config: NULL device pointer\n");
+ pr_err("gs_reset_config: NULL device pointer\n");
return;
}
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index fcde5d9c87d..d3d4f4048e6 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1115,7 +1115,7 @@ zero_bind (struct usb_gadget *gadget)
ep = usb_ep_autoconfig (gadget, &fs_source_desc);
if (!ep) {
autoconf_fail:
- printk (KERN_ERR "%s: can't autoconfigure on %s\n",
+ pr_err("%s: can't autoconfigure on %s\n",
shortname, gadget->name);
return -ENODEV;
}
@@ -1139,7 +1139,7 @@ autoconf_fail:
* things like configuration and altsetting numbering
* 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);
device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
}
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 49a91c5ee51..d97b16b52ef 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -29,15 +29,6 @@ config USB_EHCI_HCD
To compile this driver as a module, choose M here: the
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
bool "Root Hub Transaction Translators (EXPERIMENTAL)"
depends on USB_EHCI_HCD && EXPERIMENTAL
@@ -69,21 +60,30 @@ config USB_EHCI_TT_NEWSCHED
config USB_EHCI_BIG_ENDIAN_MMIO
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
config USB_EHCI_BIG_ENDIAN_DESC
bool
- depends on USB_EHCI_HCD && 440EPX
+ depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX)
default y
config USB_EHCI_FSL
bool
+ depends on USB_EHCI_HCD
select USB_EHCI_ROOT_HUB_TT
default y if MPC834x || PPC_MPC831x
---help---
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
tristate "ISP116X HCD support"
depends on USB
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 766ef68a0b4..da7532d38bf 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -222,6 +222,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
.hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index c9cc4413198..64ebfc5548a 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -323,7 +323,43 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
#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; \
switch (info1 & (3 << 12)) { \
@@ -441,10 +477,8 @@ done:
*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 ehci_hcd *ehci;
unsigned long flags;
@@ -452,14 +486,13 @@ show_async (struct class_device *class_dev, char *buf)
char *next;
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);
- next = buf;
+ next = buf->page;
size = PAGE_SIZE;
+ *next = 0;
+
/* dumps a snapshot of the async schedule.
* usually empty except for long-term bulk reads, or head.
* 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);
- return strlen (buf);
+ return strlen(buf->page);
}
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
#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 ehci_hcd *ehci;
unsigned long flags;
@@ -500,10 +529,9 @@ show_periodic (struct class_device *class_dev, char *buf)
return 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);
- next = buf;
+ next = buf->page;
size = PAGE_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;
}
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
#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 ehci_hcd *ehci;
unsigned long flags;
@@ -639,15 +663,14 @@ show_registers (struct class_device *class_dev, char *buf)
static char fmt [] = "%*s\n";
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);
- next = buf;
+ next = buf->page;
size = PAGE_SIZE;
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,
"bus %s, device %s (driver " DRIVER_VERSION ")\n"
"%s\n"
@@ -763,9 +786,7 @@ show_registers (struct class_device *class_dev, char *buf)
}
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;
next += temp;
}
@@ -789,26 +810,150 @@ done:
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 */
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 430821cb95c..adb0defa163 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -25,7 +25,7 @@
#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
/* 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,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
};
static int ehci_fsl_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5f2d74ed5ad..4caa6a8b9a3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -33,6 +33,7 @@
#include <linux/usb.h>
#include <linux/moduleparam.h>
#include <linux/dma-mapping.h>
+#include <linux/debugfs.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_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_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#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);
#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;
unsigned long flags;
+ u32 status, cmd;
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) {
- u32 status = ehci_readl(ehci, &ehci->regs->status);
if (status & STS_IAA) {
ehci_vdbg (ehci, "lost IAA\n");
COUNT (ehci->stats.lost_iaa);
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))
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)
{
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
* it reports urb completions. this flag guards against bogus
@@ -399,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd)
/* no more interrupts ... */
del_timer_sync (&ehci->watchdog);
+ del_timer_sync(&ehci->iaa_watchdog);
spin_lock_irq(&ehci->lock);
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.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.
* 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->reclaim = NULL;
- ehci->reclaim_ready = 0;
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] */
if (status & STS_IAA) {
COUNT (ehci->stats.reclaim);
- ehci->reclaim_ready = 1;
- bh = 1;
+ end_unlink_async(ehci);
}
/* 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)
{
- /* 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;
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;
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);
}
@@ -806,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
qh = (struct ehci_qh *) urb->hcpriv;
if (!qh)
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;
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 */
if (!list_empty (&qh->qtd_list)
&& 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);
- if (status != 0) {
+ if (schedule_status != 0) {
// shouldn't happen often, but ...
// FIXME kill those tds' urbs
err ("can't reschedule qh %p, err %d",
- qh, status);
+ qh, schedule_status);
}
return status;
}
@@ -898,6 +931,7 @@ rescan:
unlink_async (ehci, qh);
/* FALL THROUGH */
case QH_STATE_UNLINK: /* wait for hw to finish? */
+ case QH_STATE_UNLINK_WAIT:
idle_timeout:
spin_unlock_irqrestore (&ehci->lock, flags);
schedule_timeout_uninterruptible(1);
@@ -959,11 +993,26 @@ MODULE_LICENSE ("GPL");
#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
#endif
-#ifdef CONFIG_440EPX
+#if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE)
#include "ehci-ppc-soc.c"
#define PLATFORM_DRIVER ehci_ppc_soc_driver
#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) && \
!defined(PS3_SYSTEM_BUS_DRIVER)
#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_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
retval = platform_driver_register(&PLATFORM_DRIVER);
if (retval < 0)
- return retval;
+ goto clean0;
#endif
#ifdef 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
#ifdef 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
#ifdef PCI_DRIVER
- pci_unregister_driver(&PCI_DRIVER);
+ pci_unregister_driver(&PCI_DRIVER);
+clean1:
#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
-
return retval;
}
module_init(ehci_hcd_init);
static void __exit ehci_hcd_cleanup(void)
{
+#ifdef OF_PLATFORM_DRIVER
+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
@@ -1022,6 +1096,9 @@ static void __exit ehci_hcd_cleanup(void)
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
+#ifdef DEBUG
+ debugfs_remove(ehci_debug_root);
+#endif
}
module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 735db4aec83..40e8240b785 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/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))
msleep(5);
+ del_timer_sync(&ehci->watchdog);
+ del_timer_sync(&ehci->iaa_watchdog);
port = HCS_N_PORTS (ehci->hcs_params);
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);
if (ehci->reclaim)
- ehci->reclaim_ready = 1;
+ end_unlink_async(ehci);
ehci_work(ehci);
/* 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 */
- del_timer_sync (&ehci->watchdog);
ehci_halt (ehci);
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 */
-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;
int nports, index, n;
int count = PAGE_SIZE;
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);
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 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
* enabled, so this loop will sometimes require at least two
* iterations: one to disable the port and one to set OWNER.
*/
-
for (try = 4; try > 0; --try) {
spin_lock_irq(&ehci->lock);
port_status = ehci_readl(ehci, status_reg);
@@ -362,9 +350,39 @@ static ssize_t store_companion(struct class_device *class_dev,
if (try > 1)
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;
}
-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)
{
@@ -372,16 +390,16 @@ static inline void create_companion_file(struct ehci_hcd *ehci)
/* with integrated TT there is no companion! */
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)
{
/* with integrated TT there is no companion! */
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,
int port_status
) {
- if (!(port_status & PORT_CONNECT)) {
- ehci->reset_done [index] = 0;
+ if (!(port_status & PORT_CONNECT))
return port_status;
- }
/* if reset finished and it's still not enabled -- handoff */
if (!(port_status & PORT_PE)) {
@@ -475,8 +491,6 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
* controller by the user.
*/
- if (!(temp & PORT_CONNECT))
- ehci->reset_done [i] = 0;
if ((temp & mask) != 0
|| ((temp & PORT_RESUME) != 0
&& time_after_eq(jiffies,
@@ -864,3 +878,13 @@ error:
spin_unlock_irqrestore (&ehci->lock, flags);
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);
+}
+
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
new file mode 100644
index 00000000000..3041d8f055f
--- /dev/null
+++ b/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
+ },
+};
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
new file mode 100644
index 00000000000..e129981f139
--- /dev/null
+++ b/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",
+};
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index ad0d4965f2f..3ba01664f82 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/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 */
spin_lock_irq(&ehci->lock);
if (ehci->reclaim)
- ehci->reclaim_ready = 1;
+ end_unlink_async(ehci);
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);
@@ -364,6 +364,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
.hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
new file mode 100644
index 00000000000..ee305b1f99f
--- /dev/null
+++ b/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,
+ },
+};
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
index 452d4b1bc85..a3249078c80 100644
--- a/drivers/usb/host/ehci-ppc-soc.c
+++ b/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,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
+ .relinquish_port = ehci_relinquish_port,
};
static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 03a6b2f4e6e..bbda58eb881 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/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_resume = ehci_bus_resume,
#endif
+ .relinquish_port = ehci_relinquish_port,
};
static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b10f39c047e..776a97f3391 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/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 (status != -EPIPE
- && urb->dev->tt && !usb_pipeint (urb->pipe)
+ && urb->dev->tt
+ && !usb_pipeint(urb->pipe)
&& ((token & QTD_STS_MMF) != 0
|| QTD_CERR(token) == 0)
&& (!ehci_is_TDI(ehci)
@@ -211,6 +212,9 @@ static int qtd_copy_status (
urb->dev->ttport, urb->dev->devnum,
usb_pipeendpoint (urb->pipe), token);
#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);
}
}
@@ -638,6 +642,7 @@ qh_make (
u32 info1 = 0, info2 = 0;
int is_input, type;
int maxp = 0;
+ struct usb_tt *tt = urb->dev->tt;
if (!qh)
return qh;
@@ -661,8 +666,9 @@ qh_make (
* For control/bulk requests, the HC or TT handles these.
*/
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;
if (urb->dev->speed == USB_SPEED_HIGH) {
@@ -680,7 +686,6 @@ qh_make (
goto done;
}
} else {
- struct usb_tt *tt = urb->dev->tt;
int think_time;
/* gap is f(FS/LS transfer times) */
@@ -736,10 +741,8 @@ qh_make (
/* set the address of the TT; for TDI's integrated
* 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 } */
@@ -973,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
struct ehci_qh *qh = ehci->reclaim;
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->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) */
next = qh->reclaim;
ehci->reclaim = next;
- ehci->reclaim_ready = 0;
qh->reclaim = NULL;
qh_completions (ehci, qh);
@@ -1059,11 +1061,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
return;
}
- ehci->reclaim_ready = 0;
cmd |= CMD_IAAD;
ehci_writel(ehci, cmd, &ehci->regs->command);
(void)ehci_readl(ehci, &ehci->regs->command);
- timer_action (ehci, TIMER_IAA_WATCHDOG);
+ iaa_watchdog_start(ehci);
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 80d99bce2b3..8a8e08a51ba 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/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;
break;
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;
q = &q->itd->itd_next;
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,
* 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.
*/
static void
@@ -1536,7 +1537,6 @@ itd_link_urb (
uframe = next_uframe & 0x07;
frame = next_uframe >> 3;
- itd->usecs [uframe] = stream->usecs;
itd_patch(ehci, itd, iso_sched, packet, uframe);
next_uframe += stream->interval;
@@ -1565,6 +1565,16 @@ itd_link_urb (
#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
itd_complete (
struct ehci_hcd *ehci,
@@ -1577,6 +1587,7 @@ itd_complete (
int urb_index = -1;
struct ehci_iso_stream *stream = itd->stream;
struct usb_device *dev;
+ unsigned retval = false;
/* for each uframe with a packet */
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? */
if (likely ((urb_index + 1) != urb->number_of_packets))
- return 0;
+ goto done;
/* ASSERT: it's really the last itd for this urb
list_for_each_entry (itd, &stream->td_list, itd_list)
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;
ehci_urb_done(ehci, urb, 0);
+ retval = true;
urb = NULL;
-
- /* defer stopping schedule; completion can submit */
ehci->periodic_sched--;
- if (unlikely (!ehci->periodic_sched))
- (void) disable_periodic (ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (unlikely (list_empty (&stream->td_list))) {
@@ -1645,8 +1647,15 @@ itd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
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;
}
-#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 \
| 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
sitd_complete (
struct ehci_hcd *ehci,
@@ -1961,6 +1978,7 @@ sitd_complete (
int urb_index = -1;
struct ehci_iso_stream *stream = sitd->stream;
struct usb_device *dev;
+ unsigned retval = false;
urb_index = sitd->index;
desc = &urb->iso_frame_desc [urb_index];
@@ -1981,32 +1999,23 @@ sitd_complete (
desc->status = 0;
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;
- iso_stream_put (ehci, stream);
/* handle completion now? */
if ((urb_index + 1) != urb->number_of_packets)
- return 0;
+ goto done;
/* ASSERT: it's really the last sitd for this urb
list_for_each_entry (sitd, &stream->td_list, sitd_list)
BUG_ON (sitd->urb == urb);
*/
- /* give urb back to the driver */
+ /* give urb back to the driver; completion often (re)submits */
dev = urb->dev;
ehci_urb_done(ehci, urb, 0);
+ retval = true;
urb = NULL;
-
- /* defer stopping schedule; completion can submit */
ehci->periodic_sched--;
- if (!ehci->periodic_sched)
- (void) disable_periodic (ehci);
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (list_empty (&stream->td_list)) {
@@ -2018,8 +2027,15 @@ sitd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
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;
}
-#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
@@ -2127,17 +2123,9 @@ scan_periodic (struct ehci_hcd *ehci)
for (;;) {
union ehci_shadow q, *q_p;
__hc32 type, *hw_p;
- unsigned uframes;
+ unsigned incomplete = false;
- /* don't scan past the live uframe */
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:
/* scan each element in frame's queue for completions */
@@ -2175,12 +2163,15 @@ restart:
q = q.fstn->fstn_next;
break;
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 ();
- for (uf = live ? uframes : 8; uf < 8; uf++) {
+ for (uf = 0; uf < 8 && live; uf++) {
if (0 == (q.itd->hw_transaction [uf]
& ITD_ACTIVE(ehci)))
continue;
+ incomplete = true;
q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next;
type = Q_NEXT_TYPE(ehci,
@@ -2188,10 +2179,12 @@ restart:
q = *q_p;
break;
}
- if (uf != 8)
+ if (uf < 8 && live)
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.
*/
*q_p = q.itd->itd_next;
@@ -2202,8 +2195,12 @@ restart:
q = *q_p;
break;
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))
&& live) {
+ incomplete = true;
q_p = &q.sitd->sitd_next;
hw_p = &q.sitd->hw_next;
type = Q_NEXT_TYPE(ehci,
@@ -2211,6 +2208,11 @@ restart:
q = *q_p;
break;
}
+
+ /* Take finished SITDs out of the schedule
+ * and process them: recycle, maybe report
+ * URB completion.
+ */
*q_p = q.sitd->sitd_next;
*hw_p = q.sitd->hw_next;
type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
@@ -2226,11 +2228,24 @@ restart:
}
/* 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
// latencies climb; that should be rare, but...
@@ -2243,7 +2258,8 @@ restart:
if (now_uframe == clock) {
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;
ehci->next_uframe = now_uframe;
now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 951d69fec51..bf92d209a1a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,7 +74,6 @@ struct ehci_hcd { /* one per controller */
/* async schedule support */
struct ehci_qh *async;
struct ehci_qh *reclaim;
- unsigned reclaim_ready : 1;
unsigned scanning : 1;
/* 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 *sitd_pool; /* sitd per split iso urb */
+ struct timer_list iaa_watchdog;
struct timer_list watchdog;
unsigned long actions;
unsigned stamp;
@@ -127,6 +127,14 @@ struct ehci_hcd { /* one per controller */
#else
# 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
};
/* convert between an HCD pointer and the corresponding EHCI_HCD */
@@ -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 {
TIMER_IO_WATCHDOG,
- TIMER_IAA_WATCHDOG,
TIMER_ASYNC_SHRINK,
TIMER_ASYNC_OFF,
};
@@ -160,9 +180,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
unsigned long t;
switch (action) {
- case TIMER_IAA_WATCHDOG:
- t = EHCI_IAA_JIFFIES;
- break;
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
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
// to go OFF neither can matter, and afterwards the IO
// 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))
return;
mod_timer (&ehci->watchdog, t);
@@ -534,8 +550,8 @@ struct ehci_iso_stream {
* trusting urb->interval == f(epdesc->bInterval) and
* including the extra info for hw_bufp[0..2]
*/
- u8 interval;
u8 usecs, c_usecs;
+ u16 interval;
u16 tt_usecs;
u16 maxp;
u16 raw_mask;
@@ -586,7 +602,6 @@ struct ehci_itd {
unsigned frame; /* where scheduled */
unsigned pg;
unsigned index[8]; /* in urb->iso_frame_desc */
- u8 usecs[8];
} __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
* 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 writel_be(val, addr) out_be32((__force unsigned *)addr, val)
#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,
__u32 __iomem * regs)
{
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index c27417f5b9d..0130fd8571e 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/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)) {
changed = 1;
buf[0] |= 1 << (i + 1);
- continue;
}
}
spin_unlock_irqrestore(&isp116x->lock, flags);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index d849c809acb..126fcbdd640 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -17,6 +17,8 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
+#include <asm/gpio.h>
+
#include <asm/arch/board.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)
{
+ 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);
return usb_hcd_at91_probe(&ohci_at91_hc_driver, 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);
return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
}
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index ebab5ce8f5c..a22c30aa745 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -401,6 +401,42 @@ static inline void remove_debug_files (struct ohci_hcd *bus) { }
#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
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;
}
-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;
@@ -476,25 +511,23 @@ show_async (struct class_device *class_dev, char *buf)
size_t temp;
unsigned long flags;
- bus = class_get_devdata(class_dev);
+ bus = dev_get_drvdata(buf->dev);
hcd = bus_to_hcd(bus);
ohci = hcd_to_ohci(hcd);
/* display control and bulk lists together, for simplicity */
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);
return temp;
}
-static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
-
#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;
@@ -509,10 +542,10 @@ show_periodic (struct class_device *class_dev, char *buf)
return 0;
seen_count = 0;
- bus = class_get_devdata(class_dev);
+ bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
hcd = bus_to_hcd(bus);
ohci = hcd_to_ohci(hcd);
- next = buf;
+ next = buf->page;
size = PAGE_SIZE;
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;
}
-static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
-
-
#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;
@@ -606,11 +635,11 @@ show_registers (struct class_device *class_dev, char *buf)
char *next;
u32 rdata;
- bus = class_get_devdata(class_dev);
+ bus = (struct usb_bus *)dev_get_drvdata(buf->dev);
hcd = bus_to_hcd(bus);
ohci = hcd_to_ohci(hcd);
regs = ohci->regs;
- next = buf;
+ next = buf->page;
size = PAGE_SIZE;
spin_lock_irqsave (&ohci->lock, flags);
@@ -677,29 +706,155 @@ show_registers (struct class_device *class_dev, char *buf)
done:
spin_unlock_irqrestore (&ohci->lock, flags);
+
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)
{
- 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");
+ 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)
{
- 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
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ddd4ee1f241..dd4798ee028 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -36,6 +36,7 @@
#include <linux/dmapool.h>
#include <linux/reboot.h>
#include <linux/workqueue.h>
+#include <linux/debugfs.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -809,13 +810,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
}
if (ints & OHCI_INTR_WDH) {
- if (HC_IS_RUNNING(hcd->state))
- ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
spin_lock (&ohci->lock);
dl_done_list (ohci);
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)) {
@@ -1032,6 +1029,13 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER usb_hcd_pnx4008_driver
#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
#include "ohci-ppc-of.c"
@@ -1048,6 +1052,11 @@ MODULE_LICENSE ("GPL");
#define SSB_OHCI_DRIVER ssb_ohci_driver
#endif
+#ifdef CONFIG_MFD_SM501
+#include "ohci-sm501.c"
+#define PLATFORM_DRIVER ohci_hcd_sm501_driver
+#endif
+
#if !defined(PCI_DRIVER) && \
!defined(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,
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
retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
if (retval < 0)
@@ -1130,6 +1147,12 @@ static int __init ohci_hcd_mod_init(void)
ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
error_ps3:
#endif
+#ifdef DEBUG
+ debugfs_remove(ohci_debug_root);
+ ohci_debug_root = NULL;
+ error_debug:
+#endif
+
return retval;
}
module_init(ohci_hcd_mod_init);
@@ -1154,6 +1177,9 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef PS3_SYSTEM_BUS_DRIVER
ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
+#ifdef DEBUG
+ debugfs_remove(ohci_debug_root);
+#endif
}
module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
new file mode 100644
index 00000000000..5309ac039e1
--- /dev/null
+++ b/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,
+ },
+};
+
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
new file mode 100644
index 00000000000..a9707014286
--- /dev/null
+++ b/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",
+ },
+};
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 47c5c66a282..dc544ddc784 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -408,6 +408,13 @@ struct ohci_hcd {
unsigned eds_scheduled;
struct ed *ed_to_check;
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
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index c225159ca3d..0ee694f043c 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -190,9 +190,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
msleep(10);
}
if (wait_time <= 0)
- printk(KERN_WARNING "%s %s: BIOS handoff "
- "failed (BIOS bug ?) %08x\n",
- pdev->dev.bus_id, "OHCI",
+ dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
+ " (BIOS bug?) %08x\n",
readl(base + OHCI_CONTROL));
/* reset controller, preserving RWC */
@@ -243,8 +242,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
switch (cap & 0xff) {
case 1: /* BIOS/SMM/... handoff support */
if ((cap & EHCI_USBLEGSUP_BIOS)) {
- pr_debug("%s %s: BIOS handoff\n",
- pdev->dev.bus_id, "EHCI");
+ dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
#if 0
/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
@@ -285,9 +283,8 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
/* well, possibly buggy BIOS... try to shut
* it down, and hope nothing goes too wrong
*/
- printk(KERN_WARNING "%s %s: BIOS handoff "
- "failed (BIOS bug ?) %08x\n",
- pdev->dev.bus_id, "EHCI", cap);
+ dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
+ " (BIOS bug?) %08x\n", cap);
pci_write_config_byte(pdev, offset + 2, 0);
}
@@ -306,17 +303,14 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
cap = 0;
/* FALLTHROUGH */
default:
- printk(KERN_WARNING "%s %s: unrecognized "
- "capability %02x\n",
- pdev->dev.bus_id, "EHCI",
- cap & 0xff);
+ dev_warn(&pdev->dev, "EHCI: unrecognized capability "
+ "%02x\n", cap & 0xff);
break;
}
offset = (cap >> 8) & 0xff;
}
if (!count)
- printk(KERN_DEBUG "%s %s: capability loop?\n",
- pdev->dev.bus_id, "EHCI");
+ dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n");
/*
* halt EHCI & disable its interrupts in any case
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
index fe9ceb077d9..57388252b69 100644
--- a/drivers/usb/host/r8a66597.h
+++ b/drivers/usb/host/r8a66597.h
@@ -405,7 +405,7 @@
struct r8a66597_pipe_info {
u16 pipenum;
- u16 address; /* R8A66597 HCD usb addres */
+ u16 address; /* R8A66597 HCD usb address */
u16 epnum;
u16 maxpacket;
u16 type;
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index d1131a87a5b..0fb114ca1eb 100644
--- a/drivers/usb/image/mdc800.c
+++ b/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;
}
-
- continue;
}
}
if (mdc800->endpoint[i] == -1)
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index d721380b242..937940404b7 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -1,7 +1,7 @@
/*
* 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
* (cyport) and the 2.0 version of Greg Kroah-Hartman's
@@ -21,6 +21,9 @@
* 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
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
@@ -31,7 +34,7 @@
#include <linux/kernel.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 CYPRESS_VENDOR_ID 0xa2c
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 764696ff1e8..801070502cc 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/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
* device would use "struct tty_driver".
*/
-static struct file_operations iowarrior_fops = {
+static const struct file_operations iowarrior_fops = {
.owner = THIS_MODULE,
.write = iowarrior_write,
.read = iowarrior_read,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index aab320085eb..6664043f464 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -205,7 +205,7 @@ static DEFINE_MUTEX(open_disc_mutex);
/* Structure to hold all of our device specific stuff */
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 */
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 */
- if (down_interruptible (&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->lock)) {
mutex_unlock(&open_disc_mutex);
retval = -ERESTARTSYS;
goto exit;
@@ -421,7 +421,7 @@ static int tower_open (struct inode *inode, struct file *file)
file->private_data = dev;
unlock_exit:
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
exit:
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);
- if (down_interruptible (&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->lock)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -460,7 +460,9 @@ static int tower_release (struct inode *inode, struct file *file)
}
if (dev->udev == NULL) {
/* 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);
goto exit;
}
@@ -473,7 +475,7 @@ static int tower_release (struct inode *inode, struct file *file)
dev->open_count = 0;
unlock_exit:
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
exit:
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;
/* lock this object */
- if (down_interruptible (&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->lock)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -653,7 +655,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count,
unlock_exit:
/* unlock the device */
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
exit:
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;
/* lock this object */
- if (down_interruptible (&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->lock)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -737,7 +739,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
unlock_exit:
/* unlock the device */
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
exit:
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;
}
- init_MUTEX (&dev->sem);
+ mutex_init(&dev->lock);
dev->udev = udev;
dev->open_count = 0;
@@ -1007,16 +1009,16 @@ static void tower_disconnect (struct usb_interface *interface)
/* give back our minor */
usb_deregister_dev (interface, &tower_class);
- down (&dev->sem);
+ mutex_lock(&dev->lock);
mutex_unlock(&open_disc_mutex);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
tower_delete (dev);
} else {
dev->udev = NULL;
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
}
info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 9244d067cec..cb7fa0eaf3a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/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);
retval = -ETIMEDOUT;
} else {
- /* URB completed within timout */
+ /* URB completed within timeout */
retval = urb->status;
readbytes = urb->actual_length;
}
@@ -3195,20 +3195,6 @@ static int sisusb_probe(struct usb_interface *intf,
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) {
int initscreen = 1;
#ifdef INCL_SISUSB_CON
@@ -3271,19 +3257,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
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->ready = 0;
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index d2d7872cd02..cf0b4a5883f 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -120,9 +120,6 @@ struct sisusb_usb_data {
int isopen; /* !=0 if open */
int present; /* !=0 if device is present on the bus */
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 */
char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */
int obufsize, ibufsize;
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index ea316214648..da922dfc0dc 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/scatterlist.h>
+#include <linux/mutex.h>
#include <linux/usb.h>
@@ -64,7 +65,7 @@ struct usbtest_dev {
int in_iso_pipe;
int out_iso_pipe;
struct usb_endpoint_descriptor *iso_in, *iso_out;
- struct semaphore sem;
+ struct mutex lock;
#define TBUF_SIZE 256
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);
return retval;
}
+ le16_to_cpus(&status);
if (status != 1) {
dbg ("ep %02x bogus status: %04x != 1", ep, status);
return -EINVAL;
@@ -1310,7 +1312,7 @@ static int ctrl_out (struct usbtest_dev *dev,
len += vary;
/* [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.
*/
if (len > length)
@@ -1558,11 +1560,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
|| param->sglen < 0 || param->vary < 0)
return -EINVAL;
- if (down_interruptible (&dev->sem))
+ if (mutex_lock_interruptible(&dev->lock))
return -ERESTARTSYS;
if (intf->dev.power.power_state.event != PM_EVENT_ON) {
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
return -EHOSTUNREACH;
}
@@ -1574,7 +1576,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
int res;
if (intf->altsetting->desc.bInterfaceNumber) {
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
return -ENODEV;
}
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,
"set altsetting to %d failed, %d\n",
dev->info->alt, res);
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
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_sec -= 1;
}
- up (&dev->sem);
+ mutex_unlock(&dev->lock);
return retval;
}
@@ -1905,7 +1907,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
return -ENOMEM;
info = (struct usbtest_info *) id->driver_info;
dev->info = info;
- init_MUTEX (&dev->sem);
+ mutex_init(&dev->lock);
dev->intf = intf;
@@ -1990,8 +1992,6 @@ static void usbtest_disconnect (struct usb_interface *intf)
{
struct usbtest_dev *dev = usb_get_intfdata (intf);
- down (&dev->sem);
-
usb_set_intfdata (intf, NULL);
dev_dbg (&intf->dev, "disconnect\n");
kfree (dev);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index f06e4e2b49d..1774ba5c4c3 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1026,6 +1026,8 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
return mask;
}
+#if 0
+
/*
* open and close: just keep track of how many times the device is
* 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.
*/
-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;
unsigned long offset, chunk_idx;
struct page *pageptr;
- offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+ offset = vmf->pgoff << PAGE_SHIFT;
if (offset >= rp->b_size)
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
chunk_idx = offset / CHUNK_SIZE;
pageptr = rp->b_vec[chunk_idx].pg;
get_page(pageptr);
- if (type)
- *type = VM_FAULT_MINOR;
- return pageptr;
+ vmf->page = pageptr;
+ return 0;
}
struct vm_operations_struct mon_bin_vm_ops = {
.open = mon_bin_vma_open,
.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)
{
- /* 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_flags |= VM_RESERVED;
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;
}
-struct file_operations mon_fops_binary = {
+#endif /* 0 */
+
+static const struct file_operations mon_fops_binary = {
.owner = THIS_MODULE,
.open = mon_bin_open,
.llseek = no_llseek,
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 4a86696e6c7..c1e65dfd935 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -2,10 +2,7 @@
# USB Serial device configuration
#
-menu "USB Serial Converter support"
- depends on USB!=n
-
-config USB_SERIAL
+menuconfig USB_SERIAL
tristate "USB Serial Converter support"
depends on USB
---help---
@@ -20,6 +17,8 @@ config USB_SERIAL
To compile this driver as a module, choose M here: the
module will be called usbserial.
+if USB_SERIAL
+
config USB_SERIAL_CONSOLE
bool "USB Serial Console device support (EXPERIMENTAL)"
depends on USB_SERIAL=y && EXPERIMENTAL
@@ -43,6 +42,12 @@ config USB_SERIAL_CONSOLE
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
bool "USB Generic Serial Driver"
depends on USB_SERIAL
@@ -105,6 +110,7 @@ config USB_SERIAL_CH341
config USB_SERIAL_WHITEHEAT
tristate "USB ConnectTech WhiteHEAT Serial Driver"
depends on USB_SERIAL
+ select USB_EZUSB
help
Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
USB to serial converter device.
@@ -282,9 +288,21 @@ config USB_SERIAL_IPW
To compile this driver as a module, choose M here: the
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
tristate "USB Keyspan PDA Single Port Serial Driver"
depends on USB_SERIAL
+ select USB_EZUSB
help
Say Y here if you want to use a Keyspan PDA single port USB to
serial converter device. This driver makes use of firmware
@@ -296,6 +314,7 @@ config USB_SERIAL_KEYSPAN_PDA
config USB_SERIAL_KEYSPAN
tristate "USB Keyspan USA-xxx Serial Driver"
depends on USB_SERIAL
+ select USB_EZUSB
---help---
Say Y here if you want to use Keyspan USB to serial converter
devices. This driver makes use of Keyspan's official firmware
@@ -538,6 +557,7 @@ config USB_SERIAL_CYBERJACK
config USB_SERIAL_XIRCOM
tristate "USB Xircom / Entregra Single Port Serial Driver"
depends on USB_SERIAL
+ select USB_EZUSB
help
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
@@ -585,11 +605,4 @@ config USB_SERIAL_DEBUG
To compile this driver as a module, choose M here: the
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
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index d6fb384e52b..0db109a54d1 100644
--- a/drivers/usb/serial/Makefile
+++ b/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_IPAQ) += ipaq.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_KEYSPAN) += keyspan.o
obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 77bb893bf2e..f156dba0300 100644
--- a/drivers/usb/serial/airprime.c
+++ b/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->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) {
usb_kill_urb (priv->read_urbp[i]);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ddfee918000..fe2bfd67ba8 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -151,8 +151,10 @@ static int ark3116_attach(struct usb_serial *serial)
return 0;
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);
+ }
return -ENOMEM;
}
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 86724e88570..df0a2b3b029 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/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;
int bad_flow_control;
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 */
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;
/* 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 */
if( (old_cflag&CBAUD) == B0 ) {
control_state |= (TIOCM_DTR|TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
err("Set DTR error");
/* 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)
err("Set RTS error");
}
}
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)
err("Set baudrate error");
} else {
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 0362654d3b5..66ce30c1b75 100644
--- a/drivers/usb/serial/console.c
+++ b/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_port *port;
int retval = 0;
- struct tty_struct *tty;
- struct ktermios *termios;
+ struct tty_struct *tty = NULL;
+ struct ktermios *termios = NULL, dummy;
dbg ("%s", __FUNCTION__);
@@ -133,11 +133,14 @@ static int usb_console_setup(struct console *co, char *options)
}
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) {
/* 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;
}
@@ -148,49 +151,64 @@ static int usb_console_setup(struct console *co, char *options)
++port->open_count;
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
* is the first time the port is opened */
if (serial->type->open)
retval = serial->type->open(port, NULL);
else
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;
+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)
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 22833589c4b..f3ca66017a0 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/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(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ 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, 0x8053) }, /* Enfora EDG1228 */
{ 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, 0xEA60) }, /* 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(0x13AD, 0x9999) }, /* Baltech card reader */
+ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* 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->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);
}
/*
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4353df92487..8d9b045aa7e 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/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 */
if( (urb->actual_length==4) && (data[0]==0x01) ) {
short old_rdtodo;
- int result;
/* This is a announcement of coming bulk_ins. */
unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 163386336a5..08c65c1a377 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/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);
unsigned int c_cflag;
- unsigned long flags;
int bps;
long timeout;
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);
/* wait for data to drain from buffer */
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
timeout = CYPRESS_CLOSING_WAIT;
init_waitqueue_entry(&wait, current);
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);
if (cypress_buf_data_avail(priv->buf) == 0
|| timeout == 0 || signal_pending(current)
- || !usb_get_intfdata(port->serial->interface))
+ /* without mutex, allowed due to harmless failure mode */
+ || port->serial->disconnected)
break;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irq(&priv->lock);
timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->tty->write_wait, &wait);
/* clear out any remaining data in the buffer */
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 */
bps = tty_get_baud_rate(port->tty);
if (bps > 1200)
@@ -727,10 +733,10 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
if (c_cflag & HUPCL) {
/* drop dtr and rts */
priv = usb_get_serial_port_data(port);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irq(&priv->lock);
priv->line_control = 0;
priv->cmd_ctrl = 1;
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irq(&priv->lock);
cypress_write(port, NULL, 0);
}
}
@@ -738,6 +744,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
if (stats)
dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
priv->bytes_in, priv->bytes_out, priv->cmd_count);
+ mutex_unlock(&port->serial->disc_mutex);
} /* cypress_close */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index ae410c4678e..5f9c6e46bee 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/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];
struct tty_struct *tty = port->tty;
struct digi_port *priv = usb_get_serial_port_data(port);
- unsigned long flags = 0;
dbg("digi_close: TOP: port=%d, open_count=%d",
priv->dp_port_num, port->open_count);
+ mutex_lock(&port->serial->disc_mutex);
/* if disconnected, just clear flags */
- if (!usb_get_intfdata(port->serial->interface))
+ if (port->serial->disconnected)
goto exit;
/* 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;
- spin_unlock_irqrestore(&priv->dp_port_lock, flags);
+ spin_unlock_irq(&priv->dp_port_lock);
/* tell line discipline to process only XON/XOFF */
tty->closing = 1;
@@ -1482,11 +1482,12 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
}
tty->closing = 0;
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_in_close = 0;
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");
}
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 97ee718b1da..3f698baa0ab 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -53,6 +53,6 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
}
-EXPORT_SYMBOL(ezusb_writememory);
-EXPORT_SYMBOL(ezusb_set_reset);
+EXPORT_SYMBOL_GPL(ezusb_writememory);
+EXPORT_SYMBOL_GPL(ezusb_set_reset);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c40e77dccf8..90dcc625f70 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -17,226 +17,8 @@
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
*
- * (21/Jul/2004) Ian Abbott
- * Incorporated Steven Turner's code to add support for the FT2232C chip.
- * The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff. I have
- * fixed a couple of things.
- *
- * (27/May/2004) Ian Abbott
- * Improved throttling code, mostly stolen from the WhiteHEAT driver.
- *
- * (26/Mar/2004) Jan Capek
- * Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc.
- *
- * (09/Feb/2004) Ian Abbott
- * Changed full name of USB-UIRT device to avoid "/" character.
- * Added FTDI's alternate PID (0x6006) for FT232/245 devices.
- * Added PID for "ELV USB Module UO100" from Stefan Frings.
- *
- * (21/Oct/2003) Ian Abbott
- * Renamed some VID/PID macros for Matrix Orbital and Perle Systems
- * devices. Removed Matrix Orbital and Perle Systems devices from the
- * 8U232AM device table, but left them in the FT232BM table, as they are
- * known to use only FT232BM.
- *
- * (17/Oct/2003) Scott Allen
- * Added vid/pid for Perle Systems UltraPort USB serial converters
- *
- * (21/Sep/2003) Ian Abbott
- * Added VID/PID for Omnidirectional Control Technology US101 USB to
- * RS-232 adapter (also rebadged as Dick Smith Electronics XH6381).
- * VID/PID supplied by Donald Gordon.
- *
- * (19/Aug/2003) Ian Abbott
- * Freed urb's transfer buffer in write bulk callback.
- * Omitted some paranoid checks in write bulk callback that don't matter.
- * Scheduled work in write bulk callback regardless of port's open count.
- *
- * (05/Aug/2003) Ian Abbott
- * Added VID/PID for ID TECH IDT1221U USB to RS-232 adapter.
- * VID/PID provided by Steve Briggs.
- *
- * (23/Jul/2003) Ian Abbott
- * Added PIDs for CrystalFontz 547, 633, 631, 635, 640 and 640 from
- * Wayne Wylupski.
- *
- * (10/Jul/2003) David Glance
- * Added PID for DSS-20 SyncStation cradle for Sony-Ericsson P800.
- *
- * (27/Jun/2003) Ian Abbott
- * Reworked the urb handling logic. We have no more pool, but dynamically
- * allocate the urb and the transfer buffer on the fly. In testing this
- * does not incure any measurable overhead. This also relies on the fact
- * that we have proper reference counting logic for urbs. I nicked this
- * from Greg KH's Visor driver.
- *
- * (23/Jun/2003) Ian Abbott
- * Reduced flip buffer pushes and corrected a data length test in
- * ftdi_read_bulk_callback.
- * Defererence pointers after any paranoid checks, not before.
- *
- * (21/Jun/2003) Erik Nygren
- * Added support for Home Electronics Tira-1 IR transceiver using FT232BM chip.
- * See <http://www.home-electro.com/tira1.htm>. Only operates properly
- * at 100000 and RTS-CTS, so set custom divisor mode on startup.
- * Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
- *
- * (18/Jun/2003) Ian Abbott
- * Added Device ID of the USB relais from Rudolf Gugler (backported from
- * Philipp Gühring's patch for 2.5.x kernel).
- * Moved read transfer buffer reallocation into startup function.
- * Free existing write urb and transfer buffer in startup function.
- * Only use urbs in write urb pool that were successfully allocated.
- * Moved some constant macros out of functions.
- * Minor whitespace and comment changes.
- *
- * (12/Jun/2003) David Norwood
- * Added support for USB-UIRT IR transceiver using 8U232AM chip.
- * See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>. Only
- * operates properly at 312500, so set custom divisor mode on startup.
- *
- * (12/Jun/2003) Ian Abbott
- * Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang
- * - I've eliminated some that don't seem to exist!
- * Added Home Electronics Tira-1 IR transceiver pid from Chris Horn
- * Some whitespace/coding-style cleanups
- *
- * (11/Jun/2003) Ian Abbott
- * Fixed unsafe spinlock usage in ftdi_write
- *
- * (24/Feb/2003) Richard Shooter
- * Increase read buffer size to improve read speeds at higher baud rates
- * (specifically tested with up to 1Mb/sec at 1.5M baud)
- *
- * (23/Feb/2003) John Wilkins
- * Added Xon/xoff flow control (activating support in the ftdi device)
- * Added vid/pid for Videonetworks/Homechoice (UK ISP)
- *
- * (23/Feb/2003) Bill Ryder
- * Added matrix orb device vid/pids from Wayne Wylupski
- *
- * (19/Feb/2003) Ian Abbott
- * For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has
- * changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI,
- * ASYNC_SPD_SHI or ASYNC_SPD_WARP. Also, unless ASYNC_SPD_CUST is in
- * force, don't bother changing baud rate when custom_divisor has changed.
- *
- * (18/Feb/2003) Ian Abbott
- * Fixed TIOCMGET handling to include state of DTR and RTS, the state
- * of which are now saved by set_dtr() and set_rts().
- * Fixed improper storage class for buf in set_dtr() and set_rts().
- * Added FT232BM chip type and support for its extra baud rates (compared
- * to FT8U232AM).
- * Took account of special case divisor values for highest baud rates of
- * FT8U232AM and FT232BM.
- * For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used,
- * as previous alt_speed setting is now stale.
- * Moved startup code common between the startup routines for the
- * different chip types into a common subroutine.
- *
- * (17/Feb/2003) Bill Ryder
- * Added write urb buffer pool on a per device basis
- * Added more checking for open file on callbacks (fixed OOPS)
- * Added CrystalFontz 632 and 634 PIDs
- * (thanx to CrystalFontz for the sample devices - they flushed out
- * some driver bugs)
- * Minor debugging message changes
- * Added throttle, unthrottle and chars_in_buffer functions
- * Fixed FTDI_SIO (the original device) bug
- * Fixed some shutdown handling
- *
- *
- *
- *
- * (07/Jun/2002) Kuba Ober
- * Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
- * function. It was getting too complex.
- * Fix the divisor calculation logic which was setting divisor of 0.125
- * instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8.
- * Also make it bump up the divisor to next integer in case of 7/8 - it's
- * a better approximation.
- *
- * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
- * Not tested by me but it doesn't break anything I use.
- *
- * (04/Jan/2002) Kuba Ober
- * Implemented 38400 baudrate kludge, where it can be substituted with other
- * values. That's the only way to set custom baudrates.
- * Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
- * FIXME: both baudrate things should eventually go to usbserial.c as other
- * devices may need that functionality too. Actually, it can probably be
- * merged in serial.c somehow - too many drivers repeat this code over
- * and over.
- * Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
- * Divisors for baudrates are calculated by a macro.
- * Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
- *
- * (04/Nov/2001) Bill Ryder
- * Fixed bug in read_bulk_callback where incorrect urb buffer was used.
- * Cleaned up write offset calculation
- * Added write_room since default values can be incorrect for sio
- * Changed write_bulk_callback to use same queue_task as other drivers
- * (the previous version caused panics)
- * Removed port iteration code since the device only has one I/O port and it
- * was wrong anyway.
- *
- * (31/May/2001) gkh
- * Switched from using spinlock to a semaphore, which fixes lots of problems.
- *
- * (23/May/2001) Bill Ryder
- * Added runtime debug patch (thanx Tyson D Sawyer).
- * Cleaned up comments for 8U232
- * Added parity, framing and overrun error handling
- * Added receive break handling.
- *
- * (04/08/2001) gb
- * Identify version on module load.
- *
- * (18/March/2001) Bill Ryder
- * (Not released)
- * Added send break handling. (requires kernel patch too)
- * Fixed 8U232AM hardware RTS/CTS etc status reporting.
- * Added flipbuf fix copied from generic device
- *
- * (12/3/2000) Bill Ryder
- * Added support for 8U232AM device.
- * Moved PID and VIDs into header file only.
- * Turned on low-latency for the tty (device will do high baudrates)
- * Added shutdown routine to close files when device removed.
- * More debug and error message cleanups.
- *
- * (11/13/2000) Bill Ryder
- * Added spinlock protected open code and close code.
- * Multiple opens work (sort of - see webpage mentioned above).
- * Cleaned up comments. Removed multiple PID/VID definitions.
- * Factorised cts/dtr code
- * Made use of __FUNCTION__ in dbg's
- *
- * (11/01/2000) Adam J. Richter
- * usb_device_id table support
- *
- * (10/05/2000) gkh
- * Fixed bug with urb->dev not being set properly, now that the usb
- * core needs it.
- *
- * (09/11/2000) gkh
- * Removed DEBUG #ifdefs with call to usb_serial_debug_data
- *
- * (07/19/2000) gkh
- * Added module_init and module_exit functions to handle the fact that this
- * driver is a loadable module now.
- *
- * (04/04/2000) Bill Ryder
- * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
- * handled elsewhere in the tty io driver chain).
- *
- * (03/30/2000) Bill Ryder
- * Implemented lots of ioctls
- * Fixed a race condition in write
- * Changed some dbg's to errs
- *
- * (03/26/2000) gkh
- * Split driver up into device specific pieces.
+ * Change entries from 2004 and earlier can be found in versions of this
+ * file in kernel versions prior to the 2.6.24 release.
*
*/
@@ -309,12 +91,12 @@ struct ftdi_sio_quirk {
void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
};
-static int ftdi_olimex_probe (struct usb_serial *serial);
+static int ftdi_jtag_probe (struct usb_serial *serial);
static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
-static struct ftdi_sio_quirk ftdi_olimex_quirk = {
- .probe = ftdi_olimex_probe,
+static struct ftdi_sio_quirk ftdi_jtag_quirk = {
+ .probe = ftdi_jtag_probe,
};
static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
@@ -471,30 +253,28 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
/*
- * These will probably use user-space drivers. Uncomment them if
- * you need them or use the user-specified vendor/product module
- * parameters (see ftdi_sio.h for the numbers). Make a fuss if
- * you think the driver should recognize any of them by default.
+ * Due to many user requests for multiple ELV devices we enable
+ * them by default.
*/
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
- /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
{ USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
{ USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
@@ -545,6 +325,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
{ USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
@@ -569,8 +350,13 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
- .driver_info = (kernel_ulong_t)&ftdi_olimex_quirk },
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -1283,10 +1069,11 @@ static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
} /* ftdi_HE_TIRA1_setup */
/*
- * First port on Olimex arm-usb-ocd is reserved for JTAG interface
- * and can be accessed from userspace using openocd.
+ * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
+ * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
+ * userspace using openocd.
*/
-static int ftdi_olimex_probe(struct usb_serial *serial)
+static int ftdi_jtag_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
struct usb_interface *interface = serial->interface;
@@ -1294,7 +1081,7 @@ static int ftdi_olimex_probe(struct usb_serial *serial)
dbg("%s",__FUNCTION__);
if (interface == udev->actconfig->interface[0]) {
- info("Ignoring reserved serial port on Olimex arm-usb-ocd\n");
+ info("Ignoring serial port reserved for JTAG");
return -ENODEV;
}
@@ -1411,7 +1198,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
dbg("%s", __FUNCTION__);
- if (c_cflag & HUPCL){
+ mutex_lock(&port->serial->disc_mutex);
+ if (c_cflag & HUPCL && !port->serial->disconnected){
/* Disable flow control */
if (usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
@@ -1425,6 +1213,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
/* drop RTS and DTR */
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} /* Note change no line if hupcl is off */
+ mutex_unlock(&port->serial->disc_mutex);
/* cancel any scheduled reading */
cancel_delayed_work(&priv->rx_work);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index b51cbb0eaa0..6eee2ab914e 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -98,6 +98,10 @@
#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */
#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */
+/* OOCDlink by Joern Kaipf <joernk@web.de>
+ * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */
+#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */
+
/* Interbiometrics USB I/O Board */
/* Developed for Interbiometrics by Rudolf Gugler */
#define INTERBIOMETRICS_VID 0x1209
@@ -245,6 +249,7 @@
#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */
#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */
#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */
+#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */
/*
* Definitions for ID TECH (www.idt-net.com) devices
@@ -278,6 +283,7 @@
#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */
#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */
#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */
+#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */
/*
* Protego product ids
@@ -534,6 +540,8 @@
#define OLIMEX_VID 0x15BA
#define OLIMEX_ARM_USB_OCD_PID 0x0003
+/* www.elsterelectricity.com Elster Unicom III Optical Probe */
+#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */
/*
* The Mobility Lab (TML)
@@ -556,6 +564,13 @@
/*
+ * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3
+ * Submitted by Harald Welte <laforge@openmoko.org>
+ */
+#define FIC_VID 0x1457
+#define FIC_NEO1973_DEBUG_PID 0x5118
+
+/*
* BmRequestType: 1100 0000b
* bRequest: FTDI_E2_READ
* wValue: 0
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index f1c90cfe725..d74e43d6923 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1020,19 +1020,26 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
- garmin_clear(garmin_data_p);
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected)
+ garmin_clear(garmin_data_p);
/* shutdown our urbs */
usb_kill_urb (port->read_urb);
usb_kill_urb (port->write_urb);
- if (noResponseFromAppLayer(garmin_data_p) ||
- ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) {
- process_resetdev_request(port);
- garmin_data_p->state = STATE_RESET;
+ if (!port->serial->disconnected) {
+ if (noResponseFromAppLayer(garmin_data_p) ||
+ ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) {
+ process_resetdev_request(port);
+ garmin_data_p->state = STATE_RESET;
+ } else {
+ garmin_data_p->state = STATE_DISCONNECTED;
+ }
} else {
garmin_data_p->state = STATE_DISCONNECTED;
}
+ mutex_unlock(&port->serial->disc_mutex);
}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index d41531139c5..97fa3c42843 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -175,6 +175,14 @@ int usb_serial_generic_resume(struct usb_serial *serial)
struct usb_serial_port *port;
int i, c = 0, r;
+#ifdef CONFIG_PM
+ /*
+ * If this is an autoresume, don't submit URBs.
+ * They will be submitted in the open function instead.
+ */
+ if (serial->dev->auto_pm)
+ return 0;
+#endif
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
if (port->open_count && port->read_urb) {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index a5d2e115e16..3428ccc28da 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -959,7 +959,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
*
* This function will block the close until one of the following:
* 1. Response to our Chase comes from Edgeport
- * 2. A timout of 10 seconds without activity has expired
+ * 2. A timeout of 10 seconds without activity has expired
* (1K of Edgeport data @ 2400 baud ==> 4 sec to empty)
*
************************************************************************/
@@ -999,7 +999,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
return;
}
} else {
- // Reset timout value back to 10 seconds
+ // Reset timeout value back to 10 seconds
dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
loop = 10;
}
@@ -1014,7 +1014,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
* This function will block the close until one of the following:
* 1. TX count are 0
* 2. The edgeport has stopped
- * 3. A timout of 3 seconds without activity has expired
+ * 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
static void block_until_tx_empty (struct edgeport_port *edge_port)
@@ -1050,7 +1050,7 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
return;
}
} else {
- // Reset timout value back to seconds
+ // Reset timeout value back to seconds
loop = 30;
}
}
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index b8670905bc3..cd3405953f7 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -34,6 +34,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/serial.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
@@ -133,7 +134,7 @@ struct edgeport_serial {
struct product_info product_info;
u8 TI_I2C_Type; // Type of I2C in UMP
u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode
- struct semaphore es_sem;
+ struct mutex es_lock;
int num_ports_open;
struct usb_serial *serial;
};
@@ -1978,7 +1979,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
}
/* set up the port settings */
- edge_set_termios (port, NULL);
+ edge_set_termios (port, port->tty->termios);
/* open up the port */
@@ -2044,7 +2045,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr);
edge_serial = edge_port->edge_serial;
- if (down_interruptible(&edge_serial->es_sem))
+ if (mutex_lock_interruptible(&edge_serial->es_lock))
return -ERESTARTSYS;
if (edge_serial->num_ports_open == 0) {
/* we are the first port to be opened, let's post the interrupt urb */
@@ -2052,7 +2053,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
if (!urb) {
dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
status = -EINVAL;
- goto up_es_sem;
+ goto release_es_lock;
}
urb->complete = edge_interrupt_callback;
urb->context = edge_serial;
@@ -2060,7 +2061,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
status = usb_submit_urb (urb, GFP_KERNEL);
if (status) {
dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
- goto up_es_sem;
+ goto release_es_lock;
}
}
@@ -2092,13 +2093,13 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
dbg("%s - exited", __FUNCTION__);
- goto up_es_sem;
+ goto release_es_lock;
unlink_int_urb:
if (edge_port->edge_serial->num_ports_open == 0)
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
-up_es_sem:
- up(&edge_serial->es_sem);
+release_es_lock:
+ mutex_unlock(&edge_serial->es_lock);
return status;
}
@@ -2137,14 +2138,14 @@ static void edge_close (struct usb_serial_port *port, struct file *filp)
0,
NULL,
0);
- down(&edge_serial->es_sem);
+ mutex_lock(&edge_serial->es_lock);
--edge_port->edge_serial->num_ports_open;
if (edge_port->edge_serial->num_ports_open <= 0) {
/* last port is now closed, let's shut down our interrupt urb */
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
edge_port->edge_serial->num_ports_open = 0;
}
- up(&edge_serial->es_sem);
+ mutex_unlock(&edge_serial->es_lock);
edge_port->close_pending = 0;
dbg("%s - exited", __FUNCTION__);
@@ -2393,11 +2394,6 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
dbg("%s - port %d", __FUNCTION__, edge_port->port->number);
tty = edge_port->port->tty;
- if ((!tty) ||
- (!tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
@@ -2492,15 +2488,21 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
}
}
+ tty->termios->c_cflag &= ~CMSPAR;
+
/* Round the baud rate */
baud = tty_get_baud_rate(tty);
if (!baud) {
/* pick a default, any default... */
baud = 9600;
- }
+ } else
+ tty_encode_baud_rate(tty, baud, baud);
+
edge_port->baud_rate = baud;
config->wBaudRate = (__u16)((461550L + baud/2) / baud);
+ /* FIXME: Recompute actual baud from divisor here */
+
dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate);
dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate));
@@ -2538,19 +2540,12 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
struct tty_struct *tty = port->tty;
unsigned int cflag;
- if (!port->tty || !port->tty->termios) {
- dbg ("%s - no tty or termios", __FUNCTION__);
- return;
- }
-
cflag = tty->termios->c_cflag;
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, tty->termios->c_iflag);
- if (old_termios) {
- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
- old_termios->c_cflag, old_termios->c_iflag);
- }
+ dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+ old_termios->c_cflag, old_termios->c_iflag);
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -2743,7 +2738,7 @@ static int edge_startup (struct usb_serial *serial)
dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM;
}
- sema_init(&edge_serial->es_sem, 1);
+ mutex_init(&edge_serial->es_lock);
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
new file mode 100644
index 00000000000..fde188e23ce
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -0,0 +1,1217 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
+ *
+ * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás)
+ *
+ * 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.
+ *
+ * And tested with help of WB Electronics
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include "iuu_phoenix.h"
+#include <linux/random.h>
+
+
+#ifdef CONFIG_USB_SERIAL_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5"
+#define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
+
+static struct usb_device_id id_table[] = {
+ {USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver iuu_driver = {
+ .name = "iuu_phoenix",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+/* turbo parameter */
+static int boost = 100;
+static int clockmode = 1;
+static int cdmode = 1;
+static int iuu_cardin;
+static int iuu_cardout;
+static int xmas;
+
+static void read_rxcmd_callback(struct urb *urb);
+
+struct iuu_private {
+ spinlock_t lock; /* store irq state */
+ wait_queue_head_t delta_msr_wait;
+ u8 line_control;
+ u8 line_status;
+ u8 termios_initialized;
+ int tiostatus; /* store IUART SIGNAL for tiocmget call */
+ u8 reset; /* if 1 reset is needed */
+ int poll; /* number of poll */
+ u8 *writebuf; /* buffer for writing to device */
+ int writelen; /* num of byte to write to device */
+ u8 *buf; /* used for initialize speed */
+ u8 *dbgbuf; /* debug buffer */
+ u8 len;
+};
+
+
+static void iuu_free_buf(struct iuu_private *priv)
+{
+ kfree(priv->buf);
+ kfree(priv->dbgbuf);
+ kfree(priv->writebuf);
+}
+
+static int iuu_alloc_buf(struct iuu_private *priv)
+{
+ priv->buf = kzalloc(256, GFP_KERNEL);
+ priv->dbgbuf = kzalloc(256, GFP_KERNEL);
+ priv->writebuf = kzalloc(256, GFP_KERNEL);
+ if (!priv->buf || !priv->dbgbuf || !priv->writebuf) {
+ iuu_free_buf(priv);
+ dbg("%s problem allocation buffer", __FUNCTION__);
+ return -ENOMEM;
+ }
+ dbg("%s - Privates buffers allocation success", __FUNCTION__);
+ return 0;
+}
+
+static int iuu_startup(struct usb_serial *serial)
+{
+ struct iuu_private *priv;
+ priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
+ dbg("%s- priv allocation success", __FUNCTION__);
+ if (!priv)
+ return -ENOMEM;
+ if (iuu_alloc_buf(priv)) {
+ kfree(priv);
+ return -ENOMEM;
+ }
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+ usb_set_serial_port_data(serial->port[0], priv);
+ return 0;
+}
+
+/* Shutdown function */
+static void iuu_shutdown(struct usb_serial *serial)
+{
+ struct usb_serial_port *port = serial->port[0];
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ if (!port)
+ return;
+
+ dbg("%s", __FUNCTION__);
+
+ if (priv) {
+ iuu_free_buf(priv);
+ dbg("%s - I will free all", __FUNCTION__);
+ usb_set_serial_port_data(port, NULL);
+
+ dbg("%s - priv is not anymore in port structure", __FUNCTION__);
+ kfree(priv);
+
+ dbg("%s priv is now kfree", __FUNCTION__);
+ }
+}
+
+static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ tty = port->tty;
+
+ dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __FUNCTION__,
+ port->number, set, clear);
+ if (set & TIOCM_RTS)
+ priv->tiostatus = TIOCM_RTS;
+
+ if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) {
+ dbg("%s TIOCMSET RESET called !!!", __FUNCTION__);
+ priv->reset = 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* This is used to provide a carrier detect mechanism
+ * When a card is present, the response is 0x00
+ * When no card , the reader respond with TIOCM_CD
+ * This is known as CD autodetect mechanism
+ */
+static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ return priv->tiostatus;
+}
+
+static void iuu_rxcmd(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int result;
+ dbg("%s - enter", __FUNCTION__);
+
+ if (urb->status) {
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ /* error stop all */
+ return;
+ }
+
+
+ memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 1,
+ read_rxcmd_callback, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+static int iuu_reset(struct usb_serial_port *port, u8 wt)
+{
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ dbg("%s - enter", __FUNCTION__);
+
+ /* Prepare the reset sequence */
+
+ *buf_ptr++ = IUU_RST_SET;
+ *buf_ptr++ = IUU_DELAY_MS;
+ *buf_ptr++ = wt;
+ *buf_ptr = IUU_RST_CLEAR;
+
+ /* send the sequence */
+
+ usb_fill_bulk_urb(port->write_urb,
+ port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 4, iuu_rxcmd, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ priv->reset = 0;
+ return result;
+}
+
+/* Status Function
+ * Return value is
+ * 0x00 = no card
+ * 0x01 = smartcard
+ * 0x02 = sim card
+ */
+static void iuu_update_status_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ u8 *st;
+ dbg("%s - enter", __FUNCTION__);
+
+ if (urb->status) {
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ /* error stop all */
+ return;
+ }
+
+ st = urb->transfer_buffer;
+ dbg("%s - enter", __FUNCTION__);
+ if (urb->actual_length == 1) {
+ switch (st[0]) {
+ case 0x1:
+ priv->tiostatus = iuu_cardout;
+ break;
+ case 0x0:
+ priv->tiostatus = iuu_cardin;
+ break;
+ default:
+ priv->tiostatus = iuu_cardin;
+ }
+ }
+ iuu_rxcmd(urb);
+}
+
+static void iuu_status_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int result;
+ dbg("%s - enter", __FUNCTION__);
+
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, 256,
+ iuu_update_status_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+}
+
+static int iuu_status(struct usb_serial_port *port)
+{
+ int result;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ memset(port->write_urb->transfer_buffer, IUU_GET_STATE_REGISTER, 1);
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 1,
+ iuu_status_callback, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ return result;
+
+}
+
+static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+{
+ int status;
+ struct usb_serial *serial = port->serial;
+ int actual = 0;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ /* send the data out the bulk port */
+
+ status =
+ usb_bulk_msg(serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress), buf,
+ count, &actual, HZ * 1);
+
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - error = %2x", __FUNCTION__, status);
+ } else {
+ dbg("%s - write OK !", __FUNCTION__);
+ }
+ return status;
+}
+
+static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count)
+{
+ int status;
+ struct usb_serial *serial = port->serial;
+ int actual = 0;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ /* send the data out the bulk port */
+
+ status =
+ usb_bulk_msg(serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress), buf,
+ count, &actual, HZ * 1);
+
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - error = %2x", __FUNCTION__, status);
+ } else {
+ dbg("%s - read OK !", __FUNCTION__);
+ }
+
+ return status;
+}
+
+static int iuu_led(struct usb_serial_port *port, unsigned int R,
+ unsigned int G, unsigned int B, u8 f)
+{
+ int status;
+ u8 *buf;
+ buf = kmalloc(8, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ buf[0] = IUU_SET_LED;
+ buf[1] = R & 0xFF;
+ buf[2] = (R >> 8) & 0xFF;
+ buf[3] = G & 0xFF;
+ buf[4] = (G >> 8) & 0xFF;
+ buf[5] = B & 0xFF;
+ buf[6] = (B >> 8) & 0xFF;
+ buf[7] = f;
+ status = bulk_immediate(port, buf, 8);
+ kfree(buf);
+ if (status != IUU_OPERATION_OK)
+ dbg("%s - led error status = %2x", __FUNCTION__, status);
+ else
+ dbg("%s - led OK !", __FUNCTION__);
+ return IUU_OPERATION_OK;
+}
+
+static void iuu_rgbf_fill_buffer(u8 *buf, u8 r1, u8 r2, u8 g1, u8 g2, u8 b1,
+ u8 b2, u8 freq)
+{
+ *buf++ = IUU_SET_LED;
+ *buf++ = r1;
+ *buf++ = r2;
+ *buf++ = g1;
+ *buf++ = g2;
+ *buf++ = b1;
+ *buf++ = b2;
+ *buf = freq;
+}
+
+static void iuu_led_activity_on(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ *buf_ptr++ = IUU_SET_LED;
+ if (xmas == 1) {
+ get_random_bytes(buf_ptr, 6);
+ *(buf_ptr+7) = 1;
+ } else {
+ iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255);
+ }
+
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 8 ,
+ iuu_rxcmd, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+static void iuu_led_activity_off(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int result;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ if (xmas == 1) {
+ iuu_rxcmd(urb);
+ return;
+ } else {
+ *buf_ptr++ = IUU_SET_LED;
+ iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255);
+ }
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 8 ,
+ iuu_rxcmd, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+}
+
+
+
+static int iuu_clk(struct usb_serial_port *port, int dwFrq)
+{
+ int status;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ int Count = 0;
+ u8 FrqGenAdr = 0x69;
+ u8 DIV = 0; /* 8bit */
+ u8 XDRV = 0; /* 8bit */
+ u8 PUMP = 0; /* 3bit */
+ u8 PBmsb = 0; /* 2bit */
+ u8 PBlsb = 0; /* 8bit */
+ u8 PO = 0; /* 1bit */
+ u8 Q = 0; /* 7bit */
+ /* 24bit = 3bytes */
+ unsigned int P = 0;
+ unsigned int P2 = 0;
+ int frq = (int)dwFrq;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ if (frq == 0) {
+ priv->buf[Count++] = IUU_UART_WRITE_I2C;
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x09;
+ priv->buf[Count++] = 0x00;
+
+ status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ if (status != 0) {
+ dbg("%s - write error ", __FUNCTION__);
+ return status;
+ }
+ } else if (frq == 3579000) {
+ DIV = 100;
+ P = 1193;
+ Q = 40;
+ XDRV = 0;
+ } else if (frq == 3680000) {
+ DIV = 105;
+ P = 161;
+ Q = 5;
+ XDRV = 0;
+ } else if (frq == 6000000) {
+ DIV = 66;
+ P = 66;
+ Q = 2;
+ XDRV = 0x28;
+ } else {
+ unsigned int result = 0;
+ unsigned int tmp = 0;
+ unsigned int check;
+ unsigned int check2;
+ char found = 0x00;
+ unsigned int lQ = 2;
+ unsigned int lP = 2055;
+ unsigned int lDiv = 4;
+
+ for (lQ = 2; lQ <= 47 && !found; lQ++)
+ for (lP = 2055; lP >= 8 && !found; lP--)
+ for (lDiv = 4; lDiv <= 127 && !found; lDiv++) {
+ tmp = (12000000 / lDiv) * (lP / lQ);
+ if (abs((int)(tmp - frq)) <
+ abs((int)(frq - result))) {
+ check2 = (12000000 / lQ);
+ if (check2 < 250000)
+ continue;
+ check = (12000000 / lQ) * lP;
+ if (check > 400000000)
+ continue;
+ if (check < 100000000)
+ continue;
+ if (lDiv < 4 || lDiv > 127)
+ continue;
+ result = tmp;
+ P = lP;
+ DIV = lDiv;
+ Q = lQ;
+ if (result == frq)
+ found = 0x01;
+ }
+ }
+ }
+ P2 = ((P - PO) / 2) - 4;
+ DIV = DIV;
+ PUMP = 0x04;
+ PBmsb = (P2 >> 8 & 0x03);
+ PBlsb = P2 & 0xFF;
+ PO = (P >> 10) & 0x01;
+ Q = Q - 2;
+
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x09;
+ priv->buf[Count++] = 0x20; /* Adr = 0x09 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x0C;
+ priv->buf[Count++] = DIV; /* Adr = 0x0C */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x12;
+ priv->buf[Count++] = XDRV; /* Adr = 0x12 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x13;
+ priv->buf[Count++] = 0x6B; /* Adr = 0x13 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x40;
+ priv->buf[Count++] = (0xC0 | ((PUMP & 0x07) << 2)) |
+ (PBmsb & 0x03); /* Adr = 0x40 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x41;
+ priv->buf[Count++] = PBlsb; /* Adr = 0x41 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x42;
+ priv->buf[Count++] = Q | (((PO & 0x01) << 7)); /* Adr = 0x42 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x44;
+ priv->buf[Count++] = (char)0xFF; /* Adr = 0x44 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x45;
+ priv->buf[Count++] = (char)0xFE; /* Adr = 0x45 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x46;
+ priv->buf[Count++] = 0x7F; /* Adr = 0x46 */
+ priv->buf[Count++] = IUU_UART_WRITE_I2C; /* 0x4C */
+ priv->buf[Count++] = FrqGenAdr << 1;
+ priv->buf[Count++] = 0x47;
+ priv->buf[Count++] = (char)0x84; /* Adr = 0x47 */
+
+ status = bulk_immediate(port, (u8 *) priv->buf, Count);
+ if (status != IUU_OPERATION_OK)
+ dbg("%s - write error ", __FUNCTION__);
+ return status;
+}
+
+static int iuu_uart_flush(struct usb_serial_port *port)
+{
+ int i;
+ int status;
+ u8 rxcmd = IUU_UART_RX;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+
+ dbg("%s - enter", __FUNCTION__);
+
+ if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
+ return -EIO;
+
+ for (i = 0; i < 2; i++) {
+ status = bulk_immediate(port, &rxcmd, 1);
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - uart_flush_write error", __FUNCTION__);
+ return status;
+ }
+
+ status = read_immediate(port, &priv->len, 1);
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - uart_flush_read error", __FUNCTION__);
+ return status;
+ }
+
+ if (priv->len > 0) {
+ dbg("%s - uart_flush datalen is : %i ", __FUNCTION__,
+ priv->len);
+ status = read_immediate(port, priv->buf, priv->len);
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - uart_flush_read error", __FUNCTION__);
+ return status;
+ }
+ }
+ }
+ dbg("%s - uart_flush_read OK!", __FUNCTION__);
+ iuu_led(port, 0, 0xF000, 0, 0xFF);
+ return status;
+}
+
+static void read_buf_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ struct tty_struct *tty;
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+
+ if (urb->status) {
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ if (urb->status == -EPROTO) {
+ /* reschedule needed */
+ }
+ return;
+ }
+
+ dbg("%s - %i chars to write", __FUNCTION__, urb->actual_length);
+ tty = port->tty;
+ if (data == NULL)
+ dbg("%s - data is NULL !!!", __FUNCTION__);
+ if (tty && urb->actual_length && data) {
+ tty_insert_flip_string(tty, data, urb->actual_length);
+ tty_flip_buffer_push(tty);
+ }
+ iuu_led_activity_on(urb);
+}
+
+static int iuu_bulk_write(struct usb_serial_port *port)
+{
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned int flags;
+ int result;
+ int i;
+ char *buf_ptr = port->write_urb->transfer_buffer;
+ dbg("%s - enter", __FUNCTION__);
+
+ *buf_ptr++ = IUU_UART_ESC;
+ *buf_ptr++ = IUU_UART_TX;
+ *buf_ptr++ = priv->writelen;
+
+ memcpy(buf_ptr, priv->writebuf,
+ priv->writelen);
+ if (debug == 1) {
+ for (i = 0; i < priv->writelen; i++)
+ sprintf(priv->dbgbuf + i*2 ,
+ "%02X", priv->writebuf[i]);
+ priv->dbgbuf[priv->writelen+i*2] = 0;
+ dbg("%s - writing %i chars : %s", __FUNCTION__,
+ priv->writelen, priv->dbgbuf);
+ }
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, priv->writelen + 3,
+ iuu_rxcmd, port);
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->writelen = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ usb_serial_port_softint(port);
+ return result;
+}
+
+static int iuu_read_buf(struct usb_serial_port *port, int len)
+{
+ int result;
+ dbg("%s - enter", __FUNCTION__);
+
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, len,
+ read_buf_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ return result;
+}
+
+static void iuu_uart_read_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned int flags;
+ int status;
+ int error = 0;
+ int len = 0;
+ unsigned char *data = urb->transfer_buffer;
+ priv->poll++;
+
+ dbg("%s - enter", __FUNCTION__);
+
+ if (urb->status) {
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ /* error stop all */
+ return;
+ }
+ if (data == NULL)
+ dbg("%s - data is NULL !!!", __FUNCTION__);
+
+ if (urb->actual_length == 1 && data != NULL)
+ len = (int) data[0];
+
+ if (urb->actual_length > 1) {
+ dbg("%s - urb->actual_length = %i", __FUNCTION__,
+ urb->actual_length);
+ error = 1;
+ return;
+ }
+ /* if len > 0 call readbuf */
+
+ if (len > 0 && error == 0) {
+ dbg("%s - call read buf - len to read is %i ",
+ __FUNCTION__, len);
+ status = iuu_read_buf(port, len);
+ return;
+ }
+ /* need to update status ? */
+ if (priv->poll > 99) {
+ status = iuu_status(port);
+ priv->poll = 0;
+ return;
+ }
+
+ /* reset waiting ? */
+
+ if (priv->reset == 1) {
+ status = iuu_reset(port, 0xC);
+ return;
+ }
+ /* Writebuf is waiting */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->writelen > 0) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ status = iuu_bulk_write(port);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ /* if nothing to write call again rxcmd */
+ dbg("%s - rxcmd recall", __FUNCTION__);
+ iuu_led_activity_off(urb);
+ return;
+}
+
+static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
+ int count)
+{
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned int flags;
+ dbg("%s - enter", __FUNCTION__);
+
+ if (count > 256)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->writelen > 0) {
+ /* buffer already filled but not commited */
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return (0);
+ }
+ /* fill the buffer */
+ memcpy(priv->writebuf, buf, count);
+ priv->writelen = count;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return (count);
+}
+
+static void read_rxcmd_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int result;
+ dbg("%s - enter", __FUNCTION__);
+
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+
+ if (urb->status) {
+ dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ /* error stop all */
+ return;
+ }
+
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer, 256,
+ iuu_uart_read_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ dbg("%s - submit result = %d", __FUNCTION__, result);
+ return;
+}
+
+static int iuu_uart_on(struct usb_serial_port *port)
+{
+ int status;
+ u8 *buf;
+
+ buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ buf[0] = IUU_UART_ENABLE;
+ buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF);
+ buf[2] = (u8) (0x00FF & IUU_BAUD_9600);
+ buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN);
+
+ status = bulk_immediate(port, buf, 4);
+ if (status != IUU_OPERATION_OK) {
+ dbg("%s - uart_on error", __FUNCTION__);
+ goto uart_enable_failed;
+ }
+ /* iuu_reset() the card after iuu_uart_on() */
+ status = iuu_uart_flush(port);
+ if (status != IUU_OPERATION_OK)
+ dbg("%s - uart_flush error", __FUNCTION__);
+uart_enable_failed:
+ kfree(buf);
+ return status;
+}
+
+/* Diables the IUU UART (a.k.a. the Phoenix voiderface) */
+static int iuu_uart_off(struct usb_serial_port *port)
+{
+ int status;
+ u8 *buf;
+ buf = kmalloc(1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ buf[0] = IUU_UART_DISABLE;
+
+ status = bulk_immediate(port, buf, 1);
+ if (status != IUU_OPERATION_OK)
+ dbg("%s - uart_off error", __FUNCTION__);
+
+ kfree(buf);
+ return status;
+}
+
+static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
+ u32 *actual, u8 parity)
+{
+ int status;
+ u8 *dataout;
+ u8 DataCount = 0;
+ u8 T1Frekvens = 0;
+ u8 T1reload = 0;
+ unsigned int T1FrekvensHZ = 0;
+
+ dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
+
+ if (!dataout)
+ return -ENOMEM;
+
+ if (baud < 1200 || baud > 230400) {
+ kfree(dataout);
+ return IUU_INVALID_PARAMETER;
+ }
+ if (baud > 977) {
+ T1Frekvens = 3;
+ T1FrekvensHZ = 500000;
+ }
+
+ if (baud > 3906) {
+ T1Frekvens = 2;
+ T1FrekvensHZ = 2000000;
+ }
+
+ if (baud > 11718) {
+ T1Frekvens = 1;
+ T1FrekvensHZ = 6000000;
+ }
+
+ if (baud > 46875) {
+ T1Frekvens = 0;
+ T1FrekvensHZ = 24000000;
+ }
+
+ T1reload = 256 - (u8) (T1FrekvensHZ / (baud * 2));
+
+ /* magic number here: ENTER_FIRMWARE_UPDATE; */
+ dataout[DataCount++] = IUU_UART_ESC;
+ /* magic number here: CHANGE_BAUD; */
+ dataout[DataCount++] = IUU_UART_CHANGE;
+ dataout[DataCount++] = T1Frekvens;
+ dataout[DataCount++] = T1reload;
+
+ *actual = (T1FrekvensHZ / (256 - T1reload)) / 2;
+
+ switch (parity & 0x0F) {
+ case IUU_PARITY_NONE:
+ dataout[DataCount++] = 0x00;
+ break;
+ case IUU_PARITY_EVEN:
+ dataout[DataCount++] = 0x01;
+ break;
+ case IUU_PARITY_ODD:
+ dataout[DataCount++] = 0x02;
+ break;
+ case IUU_PARITY_MARK:
+ dataout[DataCount++] = 0x03;
+ break;
+ case IUU_PARITY_SPACE:
+ dataout[DataCount++] = 0x04;
+ break;
+ default:
+ kfree(dataout);
+ return IUU_INVALID_PARAMETER;
+ break;
+ }
+
+ switch (parity & 0xF0) {
+ case IUU_ONE_STOP_BIT:
+ dataout[DataCount - 1] |= IUU_ONE_STOP_BIT;
+ break;
+
+ case IUU_TWO_STOP_BITS:
+ dataout[DataCount - 1] |= IUU_TWO_STOP_BITS;
+ break;
+ default:
+ kfree(dataout);
+ return IUU_INVALID_PARAMETER;
+ break;
+ }
+
+ status = bulk_immediate(port, dataout, DataCount);
+ if (status != IUU_OPERATION_OK)
+ dbg("%s - uart_off error", __FUNCTION__);
+ kfree(dataout);
+ return status;
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+ return 0;
+}
+
+static void iuu_close(struct usb_serial_port *port, struct file *filp)
+{
+ /* iuu_led (port,255,0,0,0); */
+ struct usb_serial *serial;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int c_cflag;
+
+ serial = port->serial;
+ if (!serial)
+ return;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ iuu_uart_off(port);
+ if (serial->dev) {
+ if (port->tty) {
+ c_cflag = port->tty->termios->c_cflag;
+ if (c_cflag & HUPCL) {
+ /* drop DTR and RTS */
+ priv = usb_get_serial_port_data(port);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->line_control = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(port->serial->dev, 0);
+ }
+ }
+ /* free writebuf */
+ /* shutdown our urbs */
+ dbg("%s - shutting down urbs", __FUNCTION__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+ msleep(1000);
+ /* wait one second to free all buffers */
+ iuu_led(port, 0, 0, 0xF000, 0xFF);
+ msleep(1000);
+ usb_reset_device(port->serial->dev);
+ }
+}
+
+static int iuu_open(struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ u8 *buf;
+ int result;
+ u32 actual;
+ unsigned long flags;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+ buf = kmalloc(10, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ /* fixup the endpoint buffer size */
+ kfree(port->bulk_out_buffer);
+ port->bulk_out_buffer = kmalloc(512, GFP_KERNEL);
+ port->bulk_out_size = 512;
+ kfree(port->bulk_in_buffer);
+ port->bulk_in_buffer = kmalloc(512, GFP_KERNEL);
+ port->bulk_in_size = 512;
+
+ if (!port->bulk_out_buffer || !port->bulk_in_buffer) {
+ kfree(port->bulk_out_buffer);
+ kfree(port->bulk_in_buffer);
+ kfree(buf);
+ return -ENOMEM;
+ }
+
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->bulk_out_buffer, 512,
+ NULL, NULL);
+
+
+ usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->bulk_in_buffer, 512,
+ NULL, NULL);
+
+ /* set the termios structure */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
+ *(port->tty->termios) = tty_std_termios;
+ port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+ | TIOCM_CTS | CSTOPB | PARENB;
+ port->tty->termios->c_lflag = 0;
+ port->tty->termios->c_oflag = 0;
+ port->tty->termios->c_iflag = 0;
+ priv->termios_initialized = 1;
+ port->tty->low_latency = 1;
+ priv->poll = 0;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* initialize writebuf */
+#define FISH(a, b, c, d) do { \
+ result = usb_control_msg(port->serial->dev, \
+ usb_rcvctrlpipe(port->serial->dev, 0), \
+ b, a, c, d, buf, 1, 1000); \
+ dbg("0x%x:0x%x:0x%x:0x%x %d - %x", a, b, c, d, result, \
+ buf[0]); } while (0);
+
+#define SOUP(a, b, c, d) do { \
+ result = usb_control_msg(port->serial->dev, \
+ usb_sndctrlpipe(port->serial->dev, 0), \
+ b, a, c, d, NULL, 0, 1000); \
+ dbg("0x%x:0x%x:0x%x:0x%x %d", a, b, c, d, result); } while (0)
+
+ /* This is not UART related but IUU USB driver related or something */
+ /* like that. Basically no IUU will accept any commands from the USB */
+ /* host unless it has received the following message */
+ /* sprintf(buf ,"%c%c%c%c",0x03,0x02,0x02,0x0); */
+
+ SOUP(0x03, 0x02, 0x02, 0x0);
+ kfree(buf);
+ iuu_led(port, 0xF000, 0xF000, 0, 0xFF);
+ iuu_uart_on(port);
+ if (boost < 100)
+ boost = 100;
+ switch (clockmode) {
+ case 2: /* 3.680 Mhz */
+ iuu_clk(port, IUU_CLK_3680000 * boost / 100);
+ result =
+ iuu_uart_baud(port, 9600 * boost / 100, &actual,
+ IUU_PARITY_EVEN);
+ break;
+ case 3: /* 6.00 Mhz */
+ iuu_clk(port, IUU_CLK_6000000 * boost / 100);
+ result =
+ iuu_uart_baud(port, 16457 * boost / 100, &actual,
+ IUU_PARITY_EVEN);
+ break;
+ default: /* 3.579 Mhz */
+ iuu_clk(port, IUU_CLK_3579000 * boost / 100);
+ result =
+ iuu_uart_baud(port, 9600 * boost / 100, &actual,
+ IUU_PARITY_EVEN);
+ }
+
+ /* set the cardin cardout signals */
+ switch (cdmode) {
+ case 0:
+ iuu_cardin = 0;
+ iuu_cardout = 0;
+ break;
+ case 1:
+ iuu_cardin = TIOCM_CD;
+ iuu_cardout = 0;
+ break;
+ case 2:
+ iuu_cardin = 0;
+ iuu_cardout = TIOCM_CD;
+ break;
+ case 3:
+ iuu_cardin = TIOCM_DSR;
+ iuu_cardout = 0;
+ break;
+ case 4:
+ iuu_cardin = 0;
+ iuu_cardout = TIOCM_DSR;
+ break;
+ case 5:
+ iuu_cardin = TIOCM_CTS;
+ iuu_cardout = 0;
+ break;
+ case 6:
+ iuu_cardin = 0;
+ iuu_cardout = TIOCM_CTS;
+ break;
+ case 7:
+ iuu_cardin = TIOCM_RNG;
+ iuu_cardout = 0;
+ break;
+ case 8:
+ iuu_cardin = 0;
+ iuu_cardout = TIOCM_RNG;
+ }
+
+ iuu_uart_flush(port);
+
+ dbg("%s - initialization done", __FUNCTION__);
+
+ memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1);
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, 1,
+ read_rxcmd_callback, port);
+ result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting read urb,"
+ " error %d\n", __FUNCTION__, result);
+ iuu_close(port, NULL);
+ return -EPROTO;
+ } else {
+ dbg("%s - rxcmd OK", __FUNCTION__);
+ }
+ return result;
+}
+
+static struct usb_serial_driver iuu_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "iuu_phoenix",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = iuu_open,
+ .close = iuu_close,
+ .write = iuu_uart_write,
+ .read_bulk_callback = iuu_uart_read_callback,
+ .tiocmget = iuu_tiocmget,
+ .tiocmset = iuu_tiocmset,
+ .attach = iuu_startup,
+ .shutdown = iuu_shutdown,
+};
+
+static int __init iuu_init(void)
+{
+ int retval;
+ retval = usb_serial_register(&iuu_device);
+ if (retval)
+ goto failed_usb_serial_register;
+ retval = usb_register(&iuu_driver);
+ if (retval)
+ goto failed_usb_register;
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+failed_usb_register:
+ usb_serial_deregister(&iuu_device);
+failed_usb_serial_register:
+ return retval;
+}
+
+static void __exit iuu_exit(void)
+{
+ usb_deregister(&iuu_driver);
+ usb_serial_deregister(&iuu_device);
+}
+
+module_init(iuu_init);
+module_exit(iuu_exit);
+
+MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(DRIVER_VERSION);
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+module_param(xmas, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xmas, "xmas color enabled or not");
+
+module_param(boost, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500");
+
+module_param(clockmode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz");
+
+module_param(cdmode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, "
+ "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING");
diff --git a/drivers/usb/serial/iuu_phoenix.h b/drivers/usb/serial/iuu_phoenix.h
new file mode 100644
index 00000000000..b82630a3b8f
--- /dev/null
+++ b/drivers/usb/serial/iuu_phoenix.h
@@ -0,0 +1,122 @@
+/*
+ * Infinity Unlimited USB Phoenix driver
+ *
+ * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com)
+ *
+ *
+ * Original code taken from iuutool ( Copyright (C) 2006 Juan Carlos Borrás )
+ *
+ * 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.
+ *
+ * And tested with help of WB Electronics
+ *
+ */
+
+#define IUU_USB_VENDOR_ID 0x104f
+#define IUU_USB_PRODUCT_ID 0x0004
+#define IUU_USB_OP_TIMEOUT 0x0200
+
+/* Programmer commands */
+
+#define IUU_NO_OPERATION 0x00
+#define IUU_GET_FIRMWARE_VERSION 0x01
+#define IUU_GET_PRODUCT_NAME 0x02
+#define IUU_GET_STATE_REGISTER 0x03
+#define IUU_SET_LED 0x04
+#define IUU_WAIT_MUS 0x05
+#define IUU_WAIT_MS 0x06
+#define IUU_GET_LOADER_VERSION 0x50
+#define IUU_RST_SET 0x52
+#define IUU_RST_CLEAR 0x53
+#define IUU_SET_VCC 0x59
+#define IUU_UART_ENABLE 0x49
+#define IUU_UART_DISABLE 0x4A
+#define IUU_UART_WRITE_I2C 0x4C
+#define IUU_UART_ESC 0x5E
+#define IUU_UART_TRAP 0x54
+#define IUU_UART_TRAP_BREAK 0x5B
+#define IUU_UART_RX 0x56
+#define IUU_AVR_ON 0x21
+#define IUU_AVR_OFF 0x22
+#define IUU_AVR_1CLK 0x23
+#define IUU_AVR_RESET 0x24
+#define IUU_AVR_RESET_PC 0x25
+#define IUU_AVR_INC_PC 0x26
+#define IUU_AVR_INCN_PC 0x27
+#define IUU_AVR_PREAD 0x29
+#define IUU_AVR_PREADN 0x2A
+#define IUU_AVR_PWRITE 0x28
+#define IUU_AVR_DREAD 0x2C
+#define IUU_AVR_DREADN 0x2D
+#define IUU_AVR_DWRITE 0x2B
+#define IUU_AVR_PWRITEN 0x2E
+#define IUU_EEPROM_ON 0x37
+#define IUU_EEPROM_OFF 0x38
+#define IUU_EEPROM_WRITE 0x39
+#define IUU_EEPROM_WRITEX 0x3A
+#define IUU_EEPROM_WRITE8 0x3B
+#define IUU_EEPROM_WRITE16 0x3C
+#define IUU_EEPROM_WRITEX32 0x3D
+#define IUU_EEPROM_WRITEX64 0x3E
+#define IUU_EEPROM_READ 0x3F
+#define IUU_EEPROM_READX 0x40
+#define IUU_EEPROM_BREAD 0x41
+#define IUU_EEPROM_BREADX 0x42
+#define IUU_PIC_CMD 0x0A
+#define IUU_PIC_CMD_LOAD 0x0B
+#define IUU_PIC_CMD_READ 0x0C
+#define IUU_PIC_ON 0x0D
+#define IUU_PIC_OFF 0x0E
+#define IUU_PIC_RESET 0x16
+#define IUU_PIC_INC_PC 0x0F
+#define IUU_PIC_INCN_PC 0x10
+#define IUU_PIC_PWRITE 0x11
+#define IUU_PIC_PREAD 0x12
+#define IUU_PIC_PREADN 0x13
+#define IUU_PIC_DWRITE 0x14
+#define IUU_PIC_DREAD 0x15
+#define IUU_UART_NOP 0x00
+#define IUU_UART_CHANGE 0x02
+#define IUU_UART_TX 0x04
+#define IUU_DELAY_MS 0x06
+
+#define IUU_OPERATION_OK 0x00
+#define IUU_DEVICE_NOT_FOUND 0x01
+#define IUU_INVALID_HANDLE 0x02
+#define IUU_INVALID_PARAMETER 0x03
+#define IUU_INVALID_voidERFACE 0x04
+#define IUU_INVALID_REQUEST_LENGTH 0x05
+#define IUU_UART_NOT_ENABLED 0x06
+#define IUU_WRITE_ERROR 0x07
+#define IUU_READ_ERROR 0x08
+#define IUU_TX_ERROR 0x09
+#define IUU_RX_ERROR 0x0A
+
+#define IUU_PARITY_NONE 0x00
+#define IUU_PARITY_EVEN 0x01
+#define IUU_PARITY_ODD 0x02
+#define IUU_PARITY_MARK 0x03
+#define IUU_PARITY_SPACE 0x04
+#define IUU_SC_INSERTED 0x01
+#define IUU_VERIFY_ERROR 0x02
+#define IUU_SIM_INSERTED 0x04
+#define IUU_TWO_STOP_BITS 0x00
+#define IUU_ONE_STOP_BIT 0x20
+#define IUU_BAUD_2400 0x0398
+#define IUU_BAUD_9600 0x0298
+#define IUU_BAUD_19200 0x0164
+#define IUU_BAUD_28800 0x0198
+#define IUU_BAUD_38400 0x01B2
+#define IUU_BAUD_57600 0x0030
+#define IUU_BAUD_115200 0x0098
+#define IUU_CLK_3579000 3579000
+#define IUU_CLK_3680000 3680000
+#define IUU_CLK_6000000 6000000
+#define IUU_FULLCARD_IN 0x01
+#define IUU_DEV_ERROR 0x02
+#define IUU_MINICARD_IN 0x04
+#define IUU_VCC_5V 0x00
+#define IUU_VCC_3V 0x01
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 7c069a02c1d..ea7bba69f4d 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -838,7 +838,7 @@ static void usa49_indat_callback(struct urb *urb)
port = (struct usb_serial_port *) urb->context;
tty = port->tty;
- if (urb->actual_length) {
+ if (tty && urb->actual_length) {
/* 0x80 bit is error flag */
if ((data[0] & 0x80) == 0) {
/* no error on any byte */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index be9ac20a8f1..b1fa5a376e9 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -303,7 +303,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
}
-static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
+static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
{
int rc;
int bindex;
@@ -319,7 +319,9 @@ static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
case 38400: bindex = 7; break;
case 57600: bindex = 8; break;
case 115200: bindex = 9; break;
- default: return -EINVAL;
+ default:
+ bindex = 5; /* Default to 9600 */
+ baud = 9600;
}
/* rather than figure out how to sleep while waiting for this
@@ -334,7 +336,9 @@ static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
NULL, /* &data */
0, /* size */
2000); /* timeout */
- return(rc);
+ if (rc < 0)
+ return 0;
+ return baud;
}
@@ -366,7 +370,7 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
- unsigned int cflag = port->tty->termios->c_cflag;
+ speed_t speed;
/* cflag specifies lots of stuff: number of stop bits, parity, number
of data bits, baud. What can the device actually handle?:
@@ -388,22 +392,18 @@ static void keyspan_pda_set_termios (struct usb_serial_port *port,
For now, just do baud. */
- switch (cflag & CBAUD) {
- /* we could support more values here, just need to calculate
- the necessary divisors in the firmware. <asm/termbits.h>
- has the Bnnn constants. */
- case B110: keyspan_pda_setbaud(serial, 110); break;
- case B300: keyspan_pda_setbaud(serial, 300); break;
- case B1200: keyspan_pda_setbaud(serial, 1200); break;
- case B2400: keyspan_pda_setbaud(serial, 2400); break;
- case B4800: keyspan_pda_setbaud(serial, 4800); break;
- case B9600: keyspan_pda_setbaud(serial, 9600); break;
- case B19200: keyspan_pda_setbaud(serial, 19200); break;
- case B38400: keyspan_pda_setbaud(serial, 38400); break;
- case B57600: keyspan_pda_setbaud(serial, 57600); break;
- case B115200: keyspan_pda_setbaud(serial, 115200); break;
- default: dbg("can't handle requested baud rate"); break;
+ speed = tty_get_baud_rate(port->tty);
+ speed = keyspan_pda_setbaud(serial, speed);
+
+ if (speed == 0) {
+ dbg("can't handle requested baud rate");
+ /* It hasn't changed so.. */
+ speed = tty_termios_baud_rate(old_termios);
}
+ /* Only speed can change so copy the old h/w parameters
+ then encode the new speed */
+ tty_termios_copy_hw(port->tty->termios, old_termios);
+ tty_encode_baud_rate(port->tty, speed, speed);
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 90e3216abd1..55736df7d2f 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -461,17 +461,21 @@ static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
dbg("%s port %d", __FUNCTION__, port->number);
- /* send READ_OFF */
- rc = usb_control_msg (port->serial->dev,
- usb_sndctrlpipe(port->serial->dev, 0),
- KL5KUSB105A_SIO_CONFIGURE,
- USB_TYPE_VENDOR | USB_DIR_OUT,
- KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
- 0, /* index */
- NULL, 0,
- KLSI_TIMEOUT);
- if (rc < 0)
- err("Disabling read failed (error = %d)", rc);
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+ /* send READ_OFF */
+ rc = usb_control_msg (port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ KL5KUSB105A_SIO_CONFIGURE,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+ 0, /* index */
+ NULL, 0,
+ KLSI_TIMEOUT);
+ if (rc < 0)
+ err("Disabling read failed (error = %d)", rc);
+ }
+ mutex_unlock(&port->serial->disc_mutex);
/* shutdown our bulk reads and writes */
usb_kill_urb(port->write_urb);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index aee450246bf..17b3baead4a 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -114,6 +114,7 @@ static struct usb_serial_driver kobil_device = {
.usb_driver = &kobil_driver,
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
+ .num_interrupt_out = NUM_DONT_CARE,
.num_bulk_in = 0,
.num_bulk_out = 0,
.num_ports = 1,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 0dc99f75bb0..fc1cea4aba1 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -182,10 +182,11 @@ struct mct_u232_private {
/*
* Later day 2.6.0-test kernels have new baud rates like B230400 which
* we do not know how to support. We ignore them for the moment.
- * XXX Rate-limit the error message, it's user triggerable.
*/
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value)
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
{
+ *result = value;
+
if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
|| le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
@@ -200,11 +201,13 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value
case 57600: return 0x0b;
case 115200: return 0x0c;
default:
- err("MCT USB-RS232: unsupported baudrate request 0x%x,"
- " using default of B9600", value);
+ *result = 9600;
return 0x08;
}
} else {
+ /* FIXME: Can we use any divider - should we do
+ divider = 115200/value;
+ real baud = 115200/divider */
switch (value) {
case 300: break;
case 600: break;
@@ -217,9 +220,8 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value
case 57600: break;
case 115200: break;
default:
- err("MCT USB-RS232: unsupported baudrate request 0x%x,"
- " using default of B9600", value);
value = 9600;
+ *result = 9600;
}
return 115200/value;
}
@@ -232,16 +234,19 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_p
int rc;
unsigned char zero_byte = 0;
unsigned char cts_enable_byte = 0;
+ speed_t speed;
- divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
+ divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
MCT_U232_SET_BAUD_RATE_REQUEST,
MCT_U232_SET_REQUEST_TYPE,
0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
WDR_TIMEOUT);
- if (rc < 0)
+ if (rc < 0) /*FIXME: What value speed results */
err("Set BAUD RATE %d failed (error = %d)", value, rc);
+ else
+ tty_encode_baud_rate(port->tty, speed, speed);
dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
@@ -482,21 +487,22 @@ error:
static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
{
unsigned int c_cflag;
- unsigned long flags;
unsigned int control_state;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
dbg("%s port %d", __FUNCTION__, port->number);
if (port->tty) {
c_cflag = port->tty->termios->c_cflag;
- if (c_cflag & HUPCL) {
- /* drop DTR and RTS */
- spin_lock_irqsave(&priv->lock, flags);
- priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- control_state = priv->control_state;
- spin_unlock_irqrestore(&priv->lock, flags);
- mct_u232_set_modem_ctrl(port->serial, control_state);
+ mutex_lock(&port->serial->disc_mutex);
+ if (c_cflag & HUPCL && !port->serial->disconnected) {
+ /* drop DTR and RTS */
+ spin_lock_irq(&priv->lock);
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ control_state = priv->control_state;
+ spin_unlock_irq(&priv->lock);
+ mct_u232_set_modem_ctrl(port->serial, control_state);
}
+ mutex_unlock(&port->serial->disc_mutex);
}
@@ -608,7 +614,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- unsigned int cflag = port->tty->termios->c_cflag;
+ struct ktermios *termios = port->tty->termios;
+ unsigned int cflag = termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
unsigned int control_state;
@@ -670,6 +677,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
break;
}
+ termios->c_cflag &= ~CMSPAR;
+
/* set the number of stop bits */
last_lcr |= (cflag & CSTOPB) ?
MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
index aae10c8174d..07b6bec31dc 100644
--- a/drivers/usb/serial/mct_u232.h
+++ b/drivers/usb/serial/mct_u232.h
@@ -79,7 +79,7 @@
* and "Intel solution". They are the regular MCT and "Sitecom" for us.
* This is pointless to document in the header, see the code for the bits.
*/
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value);
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result);
/*
* Line Control Register (LCR)
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e02c198016b..40f3a018880 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -564,22 +564,25 @@ static void mos7720_close(struct usb_serial_port *port, struct file *filp)
}
/* While closing port, shutdown all bulk read, write *
- * and interrupt read if they exists */
- if (serial->dev) {
- dbg("Shutdown bulk write");
- usb_kill_urb(port->write_urb);
- dbg("Shutdown bulk read");
- usb_kill_urb(port->read_urb);
+ * and interrupt read if they exists, otherwise nop */
+ dbg("Shutdown bulk write");
+ usb_kill_urb(port->write_urb);
+ dbg("Shutdown bulk read");
+ usb_kill_urb(port->read_urb);
+
+ mutex_lock(&serial->disc_mutex);
+ /* these commands must not be issued if the device has
+ * been disconnected */
+ if (!serial->disconnected) {
+ data = 0x00;
+ send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+ 0x04, &data);
+
+ data = 0x00;
+ send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+ 0x01, &data);
}
-
- data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x04, &data);
-
- data = 0x00;
- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
- 0x01, &data);
-
+ mutex_unlock(&serial->disc_mutex);
mos7720_port->open = 0;
dbg("Leaving %s", __FUNCTION__);
@@ -1040,11 +1043,6 @@ static void change_port_settings(struct moschip_port *mos7720_port,
tty = mos7720_port->port->tty;
- if ((!tty) || (!tty->termios)) {
- dbg("%s - no tty structures", __FUNCTION__);
- return;
- }
-
dbg("%s: Entering ..........", __FUNCTION__);
lData = UART_LCR_WLEN8;
@@ -1175,7 +1173,10 @@ static void change_port_settings(struct moschip_port *mos7720_port,
dbg("%s - baud rate = %d", __FUNCTION__, baud);
status = send_cmd_write_baud_rate(mos7720_port, baud);
-
+ /* FIXME: needs to write actual resulting baud back not just
+ blindly do so */
+ if (cflag & CBAUD)
+ tty_encode_baud_rate(tty, baud, baud);
/* Enable Interrupts */
data = 0x0c;
send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data);
@@ -1214,10 +1215,6 @@ static void mos7720_set_termios(struct usb_serial_port *port,
tty = port->tty;
- if (!port->tty || !port->tty->termios) {
- dbg("%s - no tty or termios", __FUNCTION__);
- return;
- }
if (!mos7720_port->open) {
dbg("%s - port not opened", __FUNCTION__);
@@ -1228,19 +1225,13 @@ static void mos7720_set_termios(struct usb_serial_port *port,
cflag = tty->termios->c_cflag;
- if (!cflag) {
- printk("%s %s\n",__FUNCTION__,"cflag is NULL");
- return;
- }
-
- dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+ dbg("%s - cflag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag,
RELEVANT_IFLAG(tty->termios->c_iflag));
- if (old_termios)
- dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
- old_termios->c_cflag,
- RELEVANT_IFLAG(old_termios->c_iflag));
+ dbg("%s - old cflag %08x old iflag %08x", __FUNCTION__,
+ old_termios->c_cflag,
+ RELEVANT_IFLAG(old_termios->c_iflag));
dbg("%s - port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c29c9127113..869ecd374cb 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1133,7 +1133,7 @@ static int mos7840_chars_in_buffer(struct usb_serial_port *port)
* This function will block the close until one of the following:
* 1. TX count are 0
* 2. The mos7840 has stopped
- * 3. A timout of 3 seconds without activity has expired
+ * 3. A timeout of 3 seconds without activity has expired
*
************************************************************************/
static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
@@ -1161,7 +1161,7 @@ static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
dbg("%s - TIMEOUT", __FUNCTION__);
return;
} else {
- /* Reset timout value back to seconds */
+ /* Reset timeout value back to seconds */
wait = 30;
}
}
@@ -1275,7 +1275,7 @@ static void mos7840_close(struct usb_serial_port *port, struct file *filp)
*
* This function will block the close until one of the following:
* 1. Response to our Chase comes from mos7840
- * 2. A timout of 10 seconds without activity has expired
+ * 2. A timeout of 10 seconds without activity has expired
* (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
*
************************************************************************/
@@ -1304,7 +1304,7 @@ static void mos7840_block_until_chase_response(struct moschip_port
dbg("%s - TIMEOUT", __FUNCTION__);
return;
} else {
- /* Reset timout value back to seconds */
+ /* Reset timeout value back to seconds */
wait = 10;
}
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index d1185f53447..5e8bf1bc1e5 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -180,6 +180,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, 0x8117) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8128) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
+ { USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
@@ -640,7 +641,10 @@ static void option_close(struct usb_serial_port *port, struct file *filp)
portdata->dtr_state = 0;
if (serial->dev) {
- option_send_setup(port);
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ option_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index eea226ae37b..a3847d6c946 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -79,7 +79,7 @@ static int debug;
#define PL2303_BUF_SIZE 1024
#define PL2303_TMP_BUF_SIZE 1024
-struct pl2303_buf {
+struct oti6858_buf {
unsigned int buf_size;
char *buf_buf;
char *buf_get;
@@ -161,14 +161,14 @@ static int oti6858_startup(struct usb_serial *serial);
static void oti6858_shutdown(struct usb_serial *serial);
/* functions operating on buffers */
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
-static void pl2303_buf_free(struct pl2303_buf *pb);
-static void pl2303_buf_clear(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+static struct oti6858_buf *oti6858_buf_alloc(unsigned int size);
+static void oti6858_buf_free(struct oti6858_buf *pb);
+static void oti6858_buf_clear(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb);
+static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf,
unsigned int count);
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf,
unsigned int count);
@@ -203,7 +203,7 @@ static struct usb_serial_driver oti6858_device = {
struct oti6858_private {
spinlock_t lock;
- struct pl2303_buf *buf;
+ struct oti6858_buf *buf;
struct oti6858_control_pkt status;
struct {
@@ -316,7 +316,7 @@ void send_data(struct work_struct *work)
}
priv->flags.write_urb_in_use = 1;
- count = pl2303_buf_data_avail(priv->buf);
+ count = oti6858_buf_data_avail(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
if (count > port->bulk_out_size)
count = port->bulk_out_size;
@@ -345,7 +345,7 @@ void send_data(struct work_struct *work)
}
spin_lock_irqsave(&priv->lock, flags);
- pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
+ oti6858_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
spin_unlock_irqrestore(&priv->lock, flags);
port->write_urb->transfer_buffer_length = count;
@@ -370,7 +370,7 @@ static int oti6858_startup(struct usb_serial *serial)
priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
if (!priv)
break;
- priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+ priv->buf = oti6858_buf_alloc(PL2303_BUF_SIZE);
if (priv->buf == NULL) {
kfree(priv);
break;
@@ -391,7 +391,7 @@ static int oti6858_startup(struct usb_serial *serial)
for (--i; i >= 0; --i) {
priv = usb_get_serial_port_data(serial->port[i]);
- pl2303_buf_free(priv->buf);
+ oti6858_buf_free(priv->buf);
kfree(priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
@@ -410,7 +410,7 @@ static int oti6858_write(struct usb_serial_port *port,
return count;
spin_lock_irqsave(&priv->lock, flags);
- count = pl2303_buf_put(priv->buf, buf, count);
+ count = oti6858_buf_put(priv->buf, buf, count);
spin_unlock_irqrestore(&priv->lock, flags);
return count;
@@ -425,7 +425,7 @@ static int oti6858_write_room(struct usb_serial_port *port)
dbg("%s(port = %d)", __FUNCTION__, port->number);
spin_lock_irqsave(&priv->lock, flags);
- room = pl2303_buf_space_avail(priv->buf);
+ room = oti6858_buf_space_avail(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
return room;
@@ -440,7 +440,7 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
dbg("%s(port = %d)", __FUNCTION__, port->number);
spin_lock_irqsave(&priv->lock, flags);
- chars = pl2303_buf_data_avail(priv->buf);
+ chars = oti6858_buf_data_avail(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
return chars;
@@ -458,7 +458,7 @@ static void oti6858_set_termios(struct usb_serial_port *port,
dbg("%s(port = %d)", __FUNCTION__, port->number);
- if ((!port->tty) || (!port->tty->termios)) {
+ if (!port->tty || !port->tty->termios) {
dbg("%s(): no tty structures", __FUNCTION__);
return;
}
@@ -468,6 +468,8 @@ static void oti6858_set_termios(struct usb_serial_port *port,
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
priv->flags.termios_initialized = 1;
+ port->tty->termios->c_ispeed = 38400;
+ port->tty->termios->c_ospeed = 38400;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -504,19 +506,14 @@ static void oti6858_set_termios(struct usb_serial_port *port,
br = tty_get_baud_rate(port->tty);
if (br == 0) {
divisor = 0;
- } else if (br <= OTI6858_MAX_BAUD_RATE) {
+ } else {
int real_br;
+ br = min(br, OTI6858_MAX_BAUD_RATE);
divisor = (96000000 + 8 * br) / (16 * br);
real_br = 96000000 / (16 * divisor);
- if ((((real_br - br) * 100 + br - 1) / br) > 2) {
- dbg("%s(): baud rate %d is invalid", __FUNCTION__, br);
- return;
- }
divisor = cpu_to_le16(divisor);
- } else {
- dbg("%s(): baud rate %d is too high", __FUNCTION__, br);
- return;
+ tty_encode_baud_rate(port->tty, real_br, real_br);
}
frame_fmt &= ~FMT_STOP_BITS_MASK;
@@ -650,9 +647,9 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
dbg("%s(): entering wait loop", __FUNCTION__);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
- if (pl2303_buf_data_avail(priv->buf) == 0
+ if (oti6858_buf_data_avail(priv->buf) == 0
|| timeout == 0 || signal_pending(current)
- || !usb_get_intfdata(port->serial->interface)) /* disconnect */
+ || port->serial->disconnected)
break;
spin_unlock_irqrestore(&priv->lock, flags);
timeout = schedule_timeout(timeout);
@@ -663,7 +660,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
dbg("%s(): after wait loop", __FUNCTION__);
/* clear out any remaining data in the buffer */
- pl2303_buf_clear(priv->buf);
+ oti6858_buf_clear(priv->buf);
spin_unlock_irqrestore(&priv->lock, flags);
/* wait for characters to drain from the device */
@@ -831,21 +828,6 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
return -EFAULT;
return oti6858_tiocmset(port, NULL, 0, x);
- case TIOCGSERIAL:
- if (copy_to_user(user_arg, port->tty->termios,
- sizeof(struct ktermios))) {
- return -EFAULT;
- }
- return 0;
-
- case TIOCSSERIAL:
- if (copy_from_user(port->tty->termios, user_arg,
- sizeof(struct ktermios))) {
- return -EFAULT;
- }
- oti6858_set_termios(port, NULL);
- return 0;
-
case TIOCMIWAIT:
dbg("%s(): TIOCMIWAIT", __FUNCTION__);
return wait_modem_info(port, arg);
@@ -887,7 +869,7 @@ static void oti6858_shutdown(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
priv = usb_get_serial_port_data(serial->port[i]);
if (priv) {
- pl2303_buf_free(priv->buf);
+ oti6858_buf_free(priv->buf);
kfree(priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
@@ -987,7 +969,7 @@ static void oti6858_read_int_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags);
if (priv->flags.write_urb_in_use == 0
- && pl2303_buf_data_avail(priv->buf) != 0) {
+ && oti6858_buf_data_avail(priv->buf) != 0) {
schedule_delayed_work(&priv->delayed_write_work,0);
resubmit = 0;
}
@@ -1015,9 +997,8 @@ static void oti6858_read_bulk_callback(struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
- int i, result;
int status = urb->status;
- char tty_flag;
+ int result;
dbg("%s(port = %d, status = %d)",
__FUNCTION__, port->number, status);
@@ -1045,27 +1026,9 @@ static void oti6858_read_bulk_callback(struct urb *urb)
return;
}
- // get tty_flag from status
- tty_flag = TTY_NORMAL;
-
-/* FIXME: probably, errors will be signalled using interrupt pipe! */
-/*
- // break takes precedence over parity,
- // which takes precedence over framing errors
- if (status & UART_BREAK_ERROR )
- tty_flag = TTY_BREAK;
- else if (status & UART_PARITY_ERROR)
- tty_flag = TTY_PARITY;
- else if (status & UART_FRAME_ERROR)
- tty_flag = TTY_FRAME;
- dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
-*/
-
tty = port->tty;
if (tty != NULL && urb->actual_length > 0) {
- tty_buffer_request_room(tty, urb->actual_length);
- for (i = 0; i < urb->actual_length; ++i)
- tty_insert_flip_char(tty, data[i], tty_flag);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
@@ -1133,18 +1096,18 @@ static void oti6858_write_bulk_callback(struct urb *urb)
/*
- * pl2303_buf_alloc
+ * oti6858_buf_alloc
*
* Allocate a circular buffer and all associated memory.
*/
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+static struct oti6858_buf *oti6858_buf_alloc(unsigned int size)
{
- struct pl2303_buf *pb;
+ struct oti6858_buf *pb;
if (size == 0)
return NULL;
- pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+ pb = kmalloc(sizeof(struct oti6858_buf), GFP_KERNEL);
if (pb == NULL)
return NULL;
@@ -1161,11 +1124,11 @@ static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
}
/*
- * pl2303_buf_free
+ * oti6858_buf_free
*
* Free the buffer and all associated memory.
*/
-static void pl2303_buf_free(struct pl2303_buf *pb)
+static void oti6858_buf_free(struct oti6858_buf *pb)
{
if (pb) {
kfree(pb->buf_buf);
@@ -1174,11 +1137,11 @@ static void pl2303_buf_free(struct pl2303_buf *pb)
}
/*
- * pl2303_buf_clear
+ * oti6858_buf_clear
*
* Clear out all data in the circular buffer.
*/
-static void pl2303_buf_clear(struct pl2303_buf *pb)
+static void oti6858_buf_clear(struct oti6858_buf *pb)
{
if (pb != NULL) {
/* equivalent to a get of all data available */
@@ -1187,12 +1150,12 @@ static void pl2303_buf_clear(struct pl2303_buf *pb)
}
/*
- * pl2303_buf_data_avail
+ * oti6858_buf_data_avail
*
* Return the number of bytes of data available in the circular
* buffer.
*/
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+static unsigned int oti6858_buf_data_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
@@ -1200,12 +1163,12 @@ static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
}
/*
- * pl2303_buf_space_avail
+ * oti6858_buf_space_avail
*
* Return the number of bytes of space available in the circular
* buffer.
*/
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+static unsigned int oti6858_buf_space_avail(struct oti6858_buf *pb)
{
if (pb == NULL)
return 0;
@@ -1213,14 +1176,14 @@ static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
}
/*
- * pl2303_buf_put
+ * oti6858_buf_put
*
* Copy data data from a user buffer and put it into the circular buffer.
* Restrict to the amount of space available.
*
* Return the number of bytes copied.
*/
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+static unsigned int oti6858_buf_put(struct oti6858_buf *pb, const char *buf,
unsigned int count)
{
unsigned int len;
@@ -1228,7 +1191,7 @@ static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
if (pb == NULL)
return 0;
- len = pl2303_buf_space_avail(pb);
+ len = oti6858_buf_space_avail(pb);
if (count > len)
count = len;
@@ -1252,14 +1215,14 @@ static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
}
/*
- * pl2303_buf_get
+ * oti6858_buf_get
*
* Get data from the circular buffer and copy to the given buffer.
* Restrict to the amount of data available.
*
* Return the number of bytes copied.
*/
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+static unsigned int oti6858_buf_get(struct oti6858_buf *pb, char *buf,
unsigned int count)
{
unsigned int len;
@@ -1267,7 +1230,7 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
if (pb == NULL)
return 0;
- len = pl2303_buf_data_avail(pb);
+ len = oti6858_buf_data_avail(pb);
if (count > len)
count = len;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0da1df9c79b..ae3ec1a6400 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -65,6 +65,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
{ USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
+ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
{ USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
{ USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
{ USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
@@ -84,9 +85,10 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
- { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
+ { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
+ { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
{ } /* Terminating entry */
};
@@ -97,7 +99,10 @@ static struct usb_driver pl2303_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
.no_dynamic_id = 1,
+ .supports_autosuspend = 1,
};
#define SET_LINE_REQUEST_TYPE 0x21
@@ -310,12 +315,39 @@ static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
return count;
}
+static int pl2303_vendor_read(__u16 value, __u16 index,
+ struct usb_serial *serial, unsigned char *buf)
+{
+ int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
+ value, index, buf, 1, 100);
+ dbg("0x%x:0x%x:0x%x:0x%x %d - %x", VENDOR_READ_REQUEST_TYPE,
+ VENDOR_READ_REQUEST, value, index, res, buf[0]);
+ return res;
+}
+
+static int pl2303_vendor_write(__u16 value, __u16 index,
+ struct usb_serial *serial)
+{
+ int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
+ value, index, NULL, 0, 100);
+ dbg("0x%x:0x%x:0x%x:0x%x %d", VENDOR_WRITE_REQUEST_TYPE,
+ VENDOR_WRITE_REQUEST, value, index, res);
+ return res;
+}
+
static int pl2303_startup(struct usb_serial *serial)
{
struct pl2303_private *priv;
enum pl2303_type type = type_0;
+ unsigned char *buf;
int i;
+ buf = kmalloc(10, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
if (serial->dev->descriptor.bDeviceClass == 0x02)
type = type_0;
else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
@@ -340,9 +372,27 @@ static int pl2303_startup(struct usb_serial *serial)
priv->type = type;
usb_set_serial_port_data(serial->port[i], priv);
}
+
+ pl2303_vendor_read(0x8484, 0, serial, buf);
+ pl2303_vendor_write(0x0404, 0, serial);
+ pl2303_vendor_read(0x8484, 0, serial, buf);
+ pl2303_vendor_read(0x8383, 0, serial, buf);
+ pl2303_vendor_read(0x8484, 0, serial, buf);
+ pl2303_vendor_write(0x0404, 1, serial);
+ pl2303_vendor_read(0x8484, 0, serial, buf);
+ pl2303_vendor_read(0x8383, 0, serial, buf);
+ pl2303_vendor_write(0, 1, serial);
+ pl2303_vendor_write(1, 0, serial);
+ if (type == HX)
+ pl2303_vendor_write(2, 0x44, serial);
+ else
+ pl2303_vendor_write(2, 0x24, serial);
+
+ kfree(buf);
return 0;
cleanup:
+ kfree(buf);
for (--i; i>=0; --i) {
priv = usb_get_serial_port_data(serial->port[i]);
pl2303_buf_free(priv->buf);
@@ -582,24 +632,12 @@ static void pl2303_set_termios(struct usb_serial_port *port,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
if (cflag & CRTSCTS) {
- __u16 index;
if (priv->type == HX)
- index = 0x61;
+ pl2303_vendor_write(0x0, 0x61, serial);
else
- index = 0x41;
- i = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- VENDOR_WRITE_REQUEST,
- VENDOR_WRITE_REQUEST_TYPE,
- 0x0, index, NULL, 0, 100);
- dbg("0x40:0x1:0x0:0x%x %d", index, i);
+ pl2303_vendor_write(0x0, 0x41, serial);
} else {
- i = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- VENDOR_WRITE_REQUEST,
- VENDOR_WRITE_REQUEST_TYPE,
- 0x0, 0x0, NULL, 0, 100);
- dbg ("0x40:0x1:0x0:0x0 %d", i);
+ pl2303_vendor_write(0x0, 0x0, serial);
}
/* FIXME: Need to read back resulting baud rate */
@@ -629,7 +667,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
set_current_state(TASK_INTERRUPTIBLE);
if (pl2303_buf_data_avail(priv->buf) == 0 ||
timeout == 0 || signal_pending(current) ||
- !usb_get_intfdata(port->serial->interface)) /* disconnect */
+ port->serial->disconnected)
break;
spin_unlock_irqrestore(&priv->lock, flags);
timeout = schedule_timeout(timeout);
@@ -678,7 +716,6 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
- unsigned char *buf;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -686,45 +723,12 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp)
if (priv->type != HX) {
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
- }
-
- buf = kmalloc(10, GFP_KERNEL);
- if (buf==NULL)
- return -ENOMEM;
-
-#define FISH(a,b,c,d) \
- result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \
- b, a, c, d, buf, 1, 100); \
- dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]);
-
-#define SOUP(a,b,c,d) \
- result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \
- b, a, c, d, NULL, 0, 100); \
- dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result);
-
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
- FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
-
- if (priv->type == HX) {
- /* HX chip */
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
- /* reset upstream data pipes */
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
} else {
- SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
+ /* reset upstream data pipes */
+ pl2303_vendor_write(8, 0, serial);
+ pl2303_vendor_write(9, 0, serial);
}
- kfree(buf);
-
/* Setup termios */
if (port->tty) {
pl2303_set_termios(port, &tmp_termios);
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index d31f5d29998..237a41f6638 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -35,6 +35,7 @@
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID 0xb000
+#define RATOC_PRODUCT_ID_USB60F 0xb020
#define TRIPP_VENDOR_ID 0x2478
#define TRIPP_PRODUCT_ID 0x2008
@@ -96,10 +97,6 @@
#define ALCOR_VENDOR_ID 0x058F
#define ALCOR_PRODUCT_ID 0x9720
-/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
-#define HUAWEI_VENDOR_ID 0x12d1
-#define HUAWEI_PRODUCT_ID 0x1001
-
/* Willcom WS002IN Data Driver (by NetIndex Inc.) */
#define WS002IN_VENDOR_ID 0x11f6
#define WS002IN_PRODUCT_ID 0x2001
@@ -107,3 +104,11 @@
/* Corega CG-USBRS232R Serial Adapter */
#define COREGA_VENDOR_ID 0x07aa
#define COREGA_PRODUCT_ID 0x002a
+
+/* HL HL-340 (ID: 4348:5523) */
+#define HL340_VENDOR_ID 0x4348
+#define HL340_PRODUCT_ID 0x5523
+
+/* Y.C. Cable U.S.A., Inc - USB to RS-232 */
+#define YCCABLE_VENDOR_ID 0x05ad
+#define YCCABLE_PRODUCT_ID 0x0fba
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index c295d0495f9..4c925e3e8a6 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1,7 +1,7 @@
/*
USB Driver for Sierra Wireless
- Copyright (C) 2006, 2007 Kevin Lloyd <linux@sierrawireless.com>
+ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <linux@sierrawireless.com>
IMPORTANT DISCLAIMER: This driver is not commercially supported by
Sierra Wireless. Use at your own risk.
@@ -14,7 +14,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/
-#define DRIVER_VERSION "v.1.2.5b"
+#define DRIVER_VERSION "v.1.2.7"
#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -26,10 +26,12 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <linux/usb/ch9.h>
+#define SWIMS_USB_REQUEST_SetPower 0x00
+#define SWIMS_USB_REQUEST_SetNmea 0x07
#define SWIMS_USB_REQUEST_SetMode 0x0B
-#define SWIMS_USB_REQUEST_TYPE_SetMode 0x40
-#define SWIMS_USB_INDEX_SetMode 0x0000
+#define SWIMS_USB_REQUEST_TYPE_VSC_SET 0x40
#define SWIMS_SET_MODE_Modem 0x0001
/* per port private data */
@@ -38,6 +40,8 @@
#define IN_BUFLEN 4096
static int debug;
+static int nmea;
+static int truinstall = 1;
enum devicetype {
DEVICE_3_PORT = 0,
@@ -50,48 +54,96 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
int result;
dev_dbg(&udev->dev, "%s", "SET POWER STATE\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x00, /* __u8 request */
- 0x40, /* __u8 request type */
- swiState, /* __u16 value */
- 0, /* __u16 index */
- NULL, /* void *data */
- 0, /* __u16 size */
- USB_CTRL_SET_TIMEOUT); /* int timeout */
+ SWIMS_USB_REQUEST_SetPower, /* __u8 request */
+ SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+ swiState, /* __u16 value */
+ 0, /* __u16 index */
+ NULL, /* void *data */
+ 0, /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
return result;
}
-static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
+static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
{
int result;
dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n");
result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
SWIMS_USB_REQUEST_SetMode, /* __u8 request */
- SWIMS_USB_REQUEST_TYPE_SetMode, /* __u8 request type */
- eSocMode, /* __u16 value */
- SWIMS_USB_INDEX_SetMode, /* __u16 index */
+ SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+ eSWocMode, /* __u16 value */
+ 0x0000, /* __u16 index */
NULL, /* void *data */
0, /* __u16 size */
USB_CTRL_SET_TIMEOUT); /* int timeout */
return result;
}
-static int sierra_probe(struct usb_interface *iface,
- const struct usb_device_id *id)
+static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
+{
+ int result;
+ dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n");
+ result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ SWIMS_USB_REQUEST_SetNmea, /* __u8 request */
+ SWIMS_USB_REQUEST_TYPE_VSC_SET, /* __u8 request type */
+ enable, /* __u16 value */
+ 0x0000, /* __u16 index */
+ NULL, /* void *data */
+ 0, /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
+ return result;
+}
+
+static int sierra_calc_num_ports(struct usb_serial *serial)
{
int result;
+ int *num_ports = usb_get_serial_data(serial);
+
+ result = *num_ports;
+
+ if (result) {
+ kfree(num_ports);
+ usb_set_serial_data(serial, NULL);
+ }
+
+ return result;
+}
+
+static int sierra_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ int result = 0;
struct usb_device *udev;
+ int *num_ports;
+ u8 ifnum;
+
+ num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL);
+ if (!num_ports)
+ return -ENOMEM;
- udev = usb_get_dev(interface_to_usbdev(iface));
+ ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ udev = serial->dev;
/* Check if in installer mode */
- if (id->driver_info == DEVICE_INSTALLER) {
- dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n");
+ if (truinstall && id->driver_info == DEVICE_INSTALLER) {
+ dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n");
result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
- /*We do not want to bind to the device when in installer mode*/
+ /* Don't bind to the device when in installer mode */
+ kfree(num_ports);
return -EIO;
- }
+ } else if (id->driver_info == DEVICE_1_PORT)
+ *num_ports = 1;
+ else if (ifnum == 0x99)
+ *num_ports = 0;
+ else
+ *num_ports = 3;
+ /*
+ * save off our num_ports info so that we can use it in the
+ * calc_num_ports callback
+ */
+ usb_set_serial_data(serial, (void *)num_ports);
- return usb_serial_probe(iface, id);
+ return result;
}
static struct usb_device_id id_table [] = {
@@ -104,6 +156,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
{ USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+ { USB_DEVICE(0x1199, 0x0023) }, /* Sierra Wireless AirCard */
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
{ USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
@@ -117,56 +170,29 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
{ USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
{ USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
+ { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
+ { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
+
+ { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
+ { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
{ USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
{ USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
+ { USB_DEVICE(0x05C6, 0x6613), .driver_info = DEVICE_1_PORT }, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
{ }
};
MODULE_DEVICE_TABLE(usb, id_table);
-static struct usb_device_id id_table_1port [] = {
- { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
- { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
- { }
-};
-
-static struct usb_device_id id_table_3port [] = {
- { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
- { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
- { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
- { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
- { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
- { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
- { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
- { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
- { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/
-
- { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
- { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
- { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
- { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
- { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */
- { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
- { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/
- { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/
- { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */
- { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
- { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */
- { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */
- { }
-};
-
static struct usb_driver sierra_driver = {
.name = "sierra",
- .probe = sierra_probe,
+ .probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
.no_dynamic_id = 1,
};
-
struct sierra_port_private {
spinlock_t lock; /* lock the structure */
int outstanding_urbs; /* number of out urbs in flight */
@@ -188,6 +214,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
+ __u16 interface = 0;
dbg("%s", __FUNCTION__);
@@ -200,9 +227,18 @@ static int sierra_send_setup(struct usb_serial_port *port)
if (portdata->rts_state)
val |= 0x02;
+ /* Determine which port is targeted */
+ if (port->bulk_out_endpointAddress == 2)
+ interface = 0;
+ else if (port->bulk_out_endpointAddress == 4)
+ interface = 1;
+ else if (port->bulk_out_endpointAddress == 5)
+ interface = 2;
+
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
- 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ 0x22, 0x21, val, interface,
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
}
return 0;
@@ -561,7 +597,10 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
portdata->dtr_state = 0;
if (serial->dev) {
- sierra_send_setup(port);
+ mutex_lock(&serial->disc_mutex);
+ if (!serial->disconnected)
+ sierra_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
@@ -583,9 +622,13 @@ static int sierra_startup(struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- /*Set Device mode to D0 */
+ /* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
+ /* Check NMEA and set */
+ if (nmea)
+ sierra_vsc_set_nmea(serial->dev, 1);
+
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
@@ -646,47 +689,19 @@ static void sierra_shutdown(struct usb_serial *serial)
}
}
-static struct usb_serial_driver sierra_1port_device = {
+static struct usb_serial_driver sierra_device = {
.driver = {
.owner = THIS_MODULE,
.name = "sierra1",
},
- .description = "Sierra USB modem (1 port)",
- .id_table = id_table_1port,
- .usb_driver = &sierra_driver,
- .num_interrupt_in = NUM_DONT_CARE,
- .num_bulk_in = 1,
- .num_bulk_out = 1,
- .num_ports = 1,
- .open = sierra_open,
- .close = sierra_close,
- .write = sierra_write,
- .write_room = sierra_write_room,
- .chars_in_buffer = sierra_chars_in_buffer,
- .throttle = sierra_rx_throttle,
- .unthrottle = sierra_rx_unthrottle,
- .ioctl = sierra_ioctl,
- .set_termios = sierra_set_termios,
- .break_ctl = sierra_break_ctl,
- .tiocmget = sierra_tiocmget,
- .tiocmset = sierra_tiocmset,
- .attach = sierra_startup,
- .shutdown = sierra_shutdown,
- .read_int_callback = sierra_instat_callback,
-};
-
-static struct usb_serial_driver sierra_3port_device = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "sierra3",
- },
- .description = "Sierra USB modem (3 port)",
- .id_table = id_table_3port,
+ .description = "Sierra USB modem",
+ .id_table = id_table,
.usb_driver = &sierra_driver,
.num_interrupt_in = NUM_DONT_CARE,
- .num_bulk_in = 3,
- .num_bulk_out = 3,
- .num_ports = 3,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .calc_num_ports = sierra_calc_num_ports,
+ .probe = sierra_probe,
.open = sierra_open,
.close = sierra_close,
.write = sierra_write,
@@ -708,12 +723,9 @@ static struct usb_serial_driver sierra_3port_device = {
static int __init sierra_init(void)
{
int retval;
- retval = usb_serial_register(&sierra_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_serial_register(&sierra_3port_device);
+ retval = usb_serial_register(&sierra_device);
if (retval)
- goto failed_3port_device_register;
+ goto failed_device_register;
retval = usb_register(&sierra_driver);
@@ -725,18 +737,15 @@ static int __init sierra_init(void)
return 0;
failed_driver_register:
- usb_serial_deregister(&sierra_3port_device);
-failed_3port_device_register:
- usb_serial_deregister(&sierra_1port_device);
-failed_1port_device_register:
+ usb_serial_deregister(&sierra_device);
+failed_device_register:
return retval;
}
static void __exit sierra_exit(void)
{
usb_deregister (&sierra_driver);
- usb_serial_deregister(&sierra_1port_device);
- usb_serial_deregister(&sierra_3port_device);
+ usb_serial_deregister(&sierra_device);
}
module_init(sierra_init);
@@ -747,6 +756,12 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
+module_param(truinstall, bool, 0);
+MODULE_PARM_DESC(truinstall, "TRU-Install support");
+
+module_param(nmea, bool, 0);
+MODULE_PARM_DESC(nmea, "NMEA streaming");
+
#ifdef CONFIG_USB_DEBUG
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug messages");
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 1f0149495fb..b517f93352e 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -80,6 +80,7 @@
#include <linux/ioctl.h>
#include <linux/serial.h>
#include <linux/circ_buf.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <linux/usb.h>
@@ -139,7 +140,7 @@ struct ti_port {
};
struct ti_device {
- struct semaphore td_open_close_sem;
+ struct mutex td_open_close_lock;
int td_open_port_count;
struct usb_serial *td_serial;
int td_is_3410;
@@ -424,7 +425,7 @@ static int ti_startup(struct usb_serial *serial)
dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
- sema_init(&tdev->td_open_close_sem, 1);
+ mutex_init(&tdev->td_open_close_lock);
tdev->td_serial = serial;
usb_set_serial_data(serial, tdev);
@@ -547,7 +548,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
tdev = tport->tp_tdev;
/* only one open on any port on a device at a time */
- if (down_interruptible(&tdev->td_open_close_sem))
+ if (mutex_lock_interruptible(&tdev->td_open_close_lock))
return -ERESTARTSYS;
if (port->tty)
@@ -568,7 +569,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
if (!urb) {
dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
status = -EINVAL;
- goto up_sem;
+ goto release_lock;
}
urb->complete = ti_interrupt_callback;
urb->context = tdev;
@@ -576,11 +577,11 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
- goto up_sem;
+ goto release_lock;
}
}
- ti_set_termios(port, NULL);
+ ti_set_termios(port, port->tty->termios);
dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -617,7 +618,7 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
usb_clear_halt(dev, port->write_urb->pipe);
usb_clear_halt(dev, port->read_urb->pipe);
- ti_set_termios(port, NULL);
+ ti_set_termios(port, port->tty->termios);
dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
status = ti_command_out_sync(tdev, TI_OPEN_PORT,
@@ -656,13 +657,13 @@ static int ti_open(struct usb_serial_port *port, struct file *file)
tport->tp_is_open = 1;
++tdev->td_open_port_count;
- goto up_sem;
+ goto release_lock;
unlink_int_urb:
if (tdev->td_open_port_count == 0)
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
-up_sem:
- up(&tdev->td_open_close_sem);
+release_lock:
+ mutex_unlock(&tdev->td_open_close_lock);
dbg("%s - exit %d", __FUNCTION__, status);
return status;
}
@@ -674,7 +675,7 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
struct ti_port *tport;
int port_number;
int status;
- int do_up;
+ int do_unlock;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -699,16 +700,16 @@ static void ti_close(struct usb_serial_port *port, struct file *file)
if (status)
dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
- /* if down is interrupted, continue anyway */
- do_up = !down_interruptible(&tdev->td_open_close_sem);
+ /* if mutex_lock is interrupted, continue anyway */
+ do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
--tport->tp_tdev->td_open_port_count;
if (tport->tp_tdev->td_open_port_count <= 0) {
/* last port is closed, shut down interrupt urb */
usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
tport->tp_tdev->td_open_port_count = 0;
}
- if (do_up)
- up(&tdev->td_open_close_sem);
+ if (do_unlock)
+ mutex_unlock(&tdev->td_open_close_lock);
dbg("%s - exit", __FUNCTION__);
}
@@ -896,24 +897,11 @@ static void ti_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __FUNCTION__, port->number);
- if (!tty || !tty->termios) {
- dbg("%s - no tty or termios", __FUNCTION__);
- return;
- }
-
cflag = tty->termios->c_cflag;
iflag = tty->termios->c_iflag;
- if (old_termios && cflag == old_termios->c_cflag
- && iflag == old_termios->c_iflag) {
- dbg("%s - nothing to change", __FUNCTION__);
- return;
- }
-
- dbg("%s - clfag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
-
- if (old_termios)
- dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
+ dbg("%s - cflag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
+ dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
if (tport == NULL)
return;
@@ -947,6 +935,9 @@ static void ti_set_termios(struct usb_serial_port *port,
break;
}
+ /* CMSPAR isn't supported by this driver */
+ tty->termios->c_cflag &= ~CMSPAR;
+
if (cflag & PARENB) {
if (cflag & PARODD) {
config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING;
@@ -989,12 +980,17 @@ static void ti_set_termios(struct usb_serial_port *port,
}
baud = tty_get_baud_rate(tty);
- if (!baud) baud = 9600;
+ if (!baud)
+ baud = 9600;
if (tport->tp_tdev->td_is_3410)
config->wBaudRate = (__u16)((923077 + baud/2) / baud);
else
config->wBaudRate = (__u16)((461538 + baud/2) / baud);
+ /* FIXME: Should calculate resulting baud here and report it back */
+ if ((cflag & CBAUD) != B0)
+ tty_encode_baud_rate(tty, baud, baud);
+
dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
__FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
@@ -1497,11 +1493,10 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
struct ti_device *tdev = tport->tp_tdev;
struct usb_serial_port *port = tport->tp_port;
wait_queue_t wait;
- unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
- spin_lock_irqsave(&tport->tp_lock, flags);
+ spin_lock_irq(&tport->tp_lock);
/* wait for data to drain from the buffer */
tdev->td_urb_error = 0;
@@ -1512,11 +1507,11 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
if (ti_buf_data_avail(tport->tp_write_buf) == 0
|| timeout == 0 || signal_pending(current)
|| tdev->td_urb_error
- || !usb_get_intfdata(port->serial->interface)) /* disconnect */
+ || port->serial->disconnected) /* disconnect */
break;
- spin_unlock_irqrestore(&tport->tp_lock, flags);
+ spin_unlock_irq(&tport->tp_lock);
timeout = schedule_timeout(timeout);
- spin_lock_irqsave(&tport->tp_lock, flags);
+ spin_lock_irq(&tport->tp_lock);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&tport->tp_write_wait, &wait);
@@ -1525,19 +1520,23 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
if (flush)
ti_buf_clear(tport->tp_write_buf);
- spin_unlock_irqrestore(&tport->tp_lock, flags);
+ spin_unlock_irq(&tport->tp_lock);
+ mutex_lock(&port->serial->disc_mutex);
/* wait for data to drain from the device */
/* wait for empty tx register, plus 20 ms */
timeout += jiffies;
tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
&& !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
- && usb_get_intfdata(port->serial->interface)) { /* not disconnected */
+ && !port->serial->disconnected) {
if (ti_get_lsr(tport))
break;
+ mutex_unlock(&port->serial->disc_mutex);
msleep_interruptible(20);
+ mutex_lock(&port->serial->disc_mutex);
}
+ mutex_unlock(&port->serial->disc_mutex);
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 497e29a700c..3ce98e8d7bc 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -225,16 +225,21 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
goto bailout_mutex_unlock;
}
+ retval = usb_autopm_get_interface(serial->interface);
+ if (retval)
+ goto bailout_module_put;
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(port, filp);
if (retval)
- goto bailout_module_put;
+ goto bailout_interface_put;
}
mutex_unlock(&port->mutex);
return 0;
+bailout_interface_put:
+ usb_autopm_put_interface(serial->interface);
bailout_module_put:
module_put(serial->type->driver.owner);
bailout_mutex_unlock:
@@ -264,17 +269,21 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
}
--port->open_count;
- if (port->open_count == 0) {
+ if (port->open_count == 0)
/* only call the device specific close if this
* port is being closed by the last owner */
port->serial->type->close(port, filp);
+ if (port->open_count == (port->console? 1 : 0)) {
if (port->tty) {
if (port->tty->driver_data)
port->tty->driver_data = NULL;
port->tty = NULL;
}
+ }
+ if (port->open_count == 0) {
+ usb_autopm_put_interface(port->serial->interface);
module_put(port->serial->type->driver.owner);
}
@@ -625,6 +634,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
serial->type = driver;
serial->interface = interface;
kref_init(&serial->kref);
+ mutex_init(&serial->disc_mutex);
return serial;
}
@@ -1080,20 +1090,22 @@ void usb_serial_disconnect(struct usb_interface *interface)
usb_serial_console_disconnect(serial);
dbg ("%s", __FUNCTION__);
+ mutex_lock(&serial->disc_mutex);
usb_set_intfdata (interface, NULL);
- if (serial) {
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- if (port) {
- if (port->tty)
- tty_hangup(port->tty);
- kill_traffic(port);
- }
+ /* must set a flag, to signal subdrivers */
+ serial->disconnected = 1;
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port) {
+ if (port->tty)
+ tty_hangup(port->tty);
+ kill_traffic(port);
}
- /* let the last holder of this object
- * cause it to be cleaned up */
- usb_serial_put(serial);
}
+ /* let the last holder of this object
+ * cause it to be cleaned up */
+ mutex_unlock(&serial->disc_mutex);
+ usb_serial_put(serial);
dev_info(dev, "device disconnected\n");
}
@@ -1103,9 +1115,6 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
struct usb_serial_port *port;
int i, r = 0;
- if (!serial) /* device has been disconnected */
- return 0;
-
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port)
@@ -1253,6 +1262,7 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, read_bulk_callback);
set_to_generic_if_null(device, write_bulk_callback);
set_to_generic_if_null(device, shutdown);
+ set_to_generic_if_null(device, resume);
}
int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 7ee087fed91..22b3f78a388 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -349,16 +349,20 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
- /* Try to send shutdown message, if the device is gone, this will just fail. */
- transfer_buffer = kmalloc (0x12, GFP_KERNEL);
- if (transfer_buffer) {
- usb_control_msg (port->serial->dev,
- usb_rcvctrlpipe(port->serial->dev, 0),
- VISOR_CLOSE_NOTIFICATION, 0xc2,
- 0x0000, 0x0000,
- transfer_buffer, 0x12, 300);
- kfree (transfer_buffer);
+ mutex_lock(&port->serial->disc_mutex);
+ if (!port->serial->disconnected) {
+ /* Try to send shutdown message, unless the device is gone */
+ transfer_buffer = kmalloc (0x12, GFP_KERNEL);
+ if (transfer_buffer) {
+ usb_control_msg (port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ VISOR_CLOSE_NOTIFICATION, 0xc2,
+ 0x0000, 0x0000,
+ transfer_buffer, 0x12, 300);
+ kfree (transfer_buffer);
+ }
}
+ mutex_unlock(&port->serial->disc_mutex);
if (stats)
dev_info(&port->dev, "Bytes In = %d Bytes Out = %d\n",
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index ee5dd8b5a71..38726ef3132 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -610,8 +610,7 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
if (retval)
goto exit;
- if (port->tty)
- port->tty->low_latency = 1;
+ port->tty->low_latency = 1;
/* send an open port command */
retval = firm_open(port);
@@ -659,11 +658,14 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
struct list_head *tmp2;
dbg("%s - port %d", __FUNCTION__, port->number);
-
+
+ mutex_lock(&port->serial->disc_mutex);
/* filp is NULL when called from usb_serial_disconnect */
- if (filp && (tty_hung_up_p(filp))) {
+ if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
+ mutex_unlock(&port->serial->disc_mutex);
return;
}
+ mutex_unlock(&port->serial->disc_mutex);
port->tty->closing = 1;
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ee5b42aa536..187dd1e0109 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -66,7 +66,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
{
struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap*) us->iobuf;
struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap*) us->iobuf;
- int res, partial;
+ int res;
+ unsigned int partial;
static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS";
US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 0db488624ab..2ae1e8673b1 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -48,7 +48,6 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/hdreg.h>
-#include <linux/ide.h>
#include <linux/scatterlist.h>
#include <scsi/scsi.h>
@@ -110,6 +109,12 @@
#define REG_STATUS 0x80
#define REG_COMMAND 0x80
+/* ATA registers offset definitions */
+#define ATA_REG_ERROR_OFFSET 1
+#define ATA_REG_LCYL_OFFSET 4
+#define ATA_REG_HCYL_OFFSET 5
+#define ATA_REG_STATUS_OFFSET 7
+
/* ATA error definitions not in <linux/hdreg.h> */
#define ATA_ERROR_MEDIA_CHANGE 0x20
@@ -360,7 +365,7 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
{
struct isd200_info *info = (struct isd200_info *)us->extra;
struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
- unsigned char error = info->ATARegs[IDE_ERROR_OFFSET];
+ unsigned char error = info->ATARegs[ATA_REG_ERROR_OFFSET];
if(error & ATA_ERROR_MEDIA_CHANGE) {
buf->ErrorCode = 0x70 | SENSE_ERRCODE_VALID;
@@ -549,8 +554,8 @@ static int isd200_read_regs( struct us_data *us )
retStatus = ISD200_ERROR;
} else {
memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
- US_DEBUGP(" Got ATA Register[IDE_ERROR_OFFSET] = 0x%x\n",
- info->ATARegs[IDE_ERROR_OFFSET]);
+ US_DEBUGP(" Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+ info->ATARegs[ATA_REG_ERROR_OFFSET]);
}
return retStatus;
@@ -892,7 +897,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
break;
if (!detect) {
- if (regs[IDE_STATUS_OFFSET] & BUSY_STAT ) {
+ if (regs[ATA_REG_STATUS_OFFSET] & BUSY_STAT) {
US_DEBUGP(" %s status is still BSY, try again...\n",mstr);
} else {
US_DEBUGP(" %s status !BSY, continue with next operation\n",mstr);
@@ -902,12 +907,12 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* check for BUSY_STAT and */
/* WRERR_STAT (workaround ATA Zip drive) and */
/* ERR_STAT (workaround for Archos CD-ROM) */
- else if (regs[IDE_STATUS_OFFSET] &
+ else if (regs[ATA_REG_STATUS_OFFSET] &
(BUSY_STAT | WRERR_STAT | ERR_STAT )) {
US_DEBUGP(" Status indicates it is not ready, try again...\n");
}
/* check for DRDY, ATA devices set DRDY after SRST */
- else if (regs[IDE_STATUS_OFFSET] & READY_STAT) {
+ else if (regs[ATA_REG_STATUS_OFFSET] & READY_STAT) {
US_DEBUGP(" Identified ATA device\n");
info->DeviceFlags |= DF_ATA_DEVICE;
info->DeviceHead = master_slave;
@@ -916,8 +921,8 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
/* check Cylinder High/Low to
determine if it is an ATAPI device
*/
- else if ((regs[IDE_HCYL_OFFSET] == 0xEB) &&
- (regs[IDE_LCYL_OFFSET] == 0x14)) {
+ else if (regs[ATA_REG_HCYL_OFFSET] == 0xEB &&
+ regs[ATA_REG_LCYL_OFFSET] == 0x14) {
/* It seems that the RICOH
MP6200A CD/RW drive will
report itself okay as a
@@ -1001,12 +1006,6 @@ static int isd200_manual_enum(struct us_data *us)
return(retStatus);
}
-/*
- * We are the last non IDE user of the legacy IDE ident structures
- * and we thus want to keep a private copy of this function so the
- * driver can be used without the obsolete drivers/ide layer
- */
-
static void isd200_fix_driveid (struct hd_driveid *id)
{
#ifndef __LITTLE_ENDIAN
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 6d6108b3993..fe12737e0e2 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -86,6 +86,14 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
#endif
+/* Reported by Grant Grundler <grundler@parisc-linux.org>
+ * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware.
+ */
+UNUSUAL_DEV( 0x03f0, 0x4002, 0x0001, 0x0001,
+ "HP",
+ "PhotoSmart R707",
+ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
+
/* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
* and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
* for USB floppies that need the SINGLE_LUN enforcement.
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index d53bf6945f0..9b05da6268f 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -39,12 +39,7 @@
#include <linux/spinlock.h>
#ifdef CONFIG_COMPAT
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
-#include <linux/ioctl32.h>
-#define SIS_OLD_CONFIG_COMPAT
-#else
#define SIS_NEW_CONFIG_COMPAT
-#endif
#endif /* CONFIG_COMPAT */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -607,9 +602,6 @@ struct sis_video_info {
int haveXGIROM;
int registered;
int warncount;
-#ifdef SIS_OLD_CONFIG_COMPAT
- int ioctl32registered;
-#endif
int sisvga_engine;
int hwcursor_size;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 37bd24b8d83..93ae747440c 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5805,9 +5805,6 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->pcifunc = PCI_FUNC(pdev->devfn);
ivideo->subsysvendor = pdev->subsystem_vendor;
ivideo->subsysdevice = pdev->subsystem_device;
-#ifdef SIS_OLD_CONFIG_COMPAT
- ivideo->ioctl32registered = 0;
-#endif
#ifndef MODULE
if(sisfb_mode_idx == -1) {
@@ -6420,30 +6417,6 @@ error_3: vfree(ivideo->bios_abase);
ivideo->next = card_list;
card_list = ivideo;
-#ifdef SIS_OLD_CONFIG_COMPAT
- {
- int ret;
- /* Our ioctls are all "32/64bit compatible" */
- ret = register_ioctl32_conversion(FBIO_ALLOC, NULL);
- ret |= register_ioctl32_conversion(FBIO_FREE, NULL);
- ret |= register_ioctl32_conversion(FBIOGET_VBLANK, NULL);
- ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE, NULL);
- ret |= register_ioctl32_conversion(SISFB_GET_INFO, NULL);
- ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET, NULL);
- ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET, NULL);
- ret |= register_ioctl32_conversion(SISFB_SET_LOCK, NULL);
- ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS, NULL);
- ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
- ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
- ret |= register_ioctl32_conversion(SISFB_COMMAND, NULL);
- if(ret)
- printk(KERN_ERR
- "sisfb: Error registering ioctl32 translations\n");
- else
- ivideo->ioctl32registered = 1;
- }
-#endif
-
printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
ivideo->sisfb_accel ? "enabled" : "disabled",
ivideo->sisfb_ypan ?
@@ -6473,27 +6446,6 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
int registered = ivideo->registered;
int modechanged = ivideo->modechanged;
-#ifdef SIS_OLD_CONFIG_COMPAT
- if(ivideo->ioctl32registered) {
- int ret;
- ret = unregister_ioctl32_conversion(FBIO_ALLOC);
- ret |= unregister_ioctl32_conversion(FBIO_FREE);
- ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
- ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
- ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
- ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
- ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
- ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
- ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
- ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
- ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
- ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
- if(ret)
- printk(KERN_ERR
- "sisfb: Error unregistering ioctl32 translations\n");
- }
-#endif
-
/* Unmap */
iounmap(ivideo->mmio_vbase);
iounmap(ivideo->video_vbase);
diff --git a/include/asm-arm/arch-at91/board.h b/include/asm-arm/arch-at91/board.h
index 55b07bd5316..dc189f01c5b 100644
--- a/include/asm-arm/arch-at91/board.h
+++ b/include/asm-arm/arch-at91/board.h
@@ -40,7 +40,8 @@
/* USB Device */
struct at91_udc_data {
u8 vbus_pin; /* high == host powering us */
- u8 pullup_pin; /* high == D+ pulled up */
+ u8 pullup_pin; /* active == D+ pulled up */
+ u8 pullup_active_low; /* true == pullup_pin is active low */
};
extern void __init at91_add_device_udc(struct at91_udc_data *data);
diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
index ff0a95715a0..f191e147ea9 100644
--- a/include/asm-arm/mach/udc_pxa2xx.h
+++ b/include/asm-arm/mach/udc_pxa2xx.h
@@ -19,7 +19,9 @@ struct pxa2xx_udc_mach_info {
* with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
* VBUS IRQ and omit the methods above. Store the GPIO number
* here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+ * Note that sometimes the signals go through inverters...
*/
+ bool gpio_vbus_inverted;
u16 gpio_vbus; /* high == vbus present */
u16 gpio_pullup; /* high == pullup activated */
};
diff --git a/include/linux/aspm.h b/include/linux/aspm.h
new file mode 100644
index 00000000000..f41a6989548
--- /dev/null
+++ b/include/linux/aspm.h
@@ -0,0 +1,44 @@
+/*
+ * aspm.h
+ *
+ * PCI Express ASPM defines and function prototypes
+ *
+ * Copyright (C) 2007 Intel Corp.
+ * Zhang Yanmin (yanmin.zhang@intel.com)
+ * Shaohua Li (shaohua.li@intel.com)
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI Express Specification
+ */
+
+#ifndef LINUX_ASPM_H
+#define LINUX_ASPM_H
+
+#include <linux/pci.h>
+
+#define PCIE_LINK_STATE_L0S 1
+#define PCIE_LINK_STATE_L1 2
+#define PCIE_LINK_STATE_CLKPM 4
+
+#ifdef CONFIG_PCIEASPM
+extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
+extern void pci_disable_link_state(struct pci_dev *pdev, int state);
+#else
+#define pcie_aspm_init_link_state(pdev) do {} while (0)
+#define pcie_aspm_exit_link_state(pdev) do {} while (0)
+#define pcie_aspm_pm_state_change(pdev) do {} while (0)
+#define pci_disable_link_state(pdev, state) do {} while (0)
+#endif
+
+#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
+extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
+extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
+#else
+#define pcie_aspm_create_sysfs_dev_files(pdev) do {} while (0)
+#define pcie_aspm_remove_sysfs_dev_files(pdev) do {} while (0)
+#endif
+#endif /* LINUX_ASPM_H */
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 936ef82ed76..3ba25065fa9 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -48,7 +48,15 @@
#ifdef CONFIG_ACPI
extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
-extern acpi_status pci_osc_support_set(u32 flags);
+extern acpi_status __pci_osc_support_set(u32 flags, const char *hid);
+static inline acpi_status pci_osc_support_set(u32 flags)
+{
+ return __pci_osc_support_set(flags, PCI_ROOT_HID_STRING);
+}
+static inline acpi_status pcie_osc_support_set(u32 flags)
+{
+ return __pci_osc_support_set(flags, PCI_EXPRESS_ROOT_HID_STRING);
+}
#else
#if !defined(AE_ERROR)
typedef u32 acpi_status;
@@ -57,6 +65,7 @@ typedef u32 acpi_status;
static inline acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
{return AE_ERROR;}
static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;}
+static inline acpi_status pcie_osc_support_set(u32 flags) {return AE_ERROR;}
#endif
#endif /* _PCI_ACPI_H_ */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ae1006322f8..4f96f1d94ac 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -28,7 +28,7 @@
* 7:3 = slot
* 2:0 = function
*/
-#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
@@ -66,7 +66,6 @@ enum pci_mmap_state {
#define PCI_DMA_FROMDEVICE 2
#define PCI_DMA_NONE 3
-#define DEVICE_COUNT_COMPATIBLE 4
#define DEVICE_COUNT_RESOURCE 12
typedef int __bitwise pci_power_t;
@@ -129,6 +128,7 @@ struct pci_cap_saved_state {
u32 data[0];
};
+struct pcie_link_state;
/*
* The pci_dev structure is used to describe PCI devices.
*/
@@ -164,13 +164,13 @@ struct pci_dev {
this is D0-D3, D0 being fully functional,
and D3 being off. */
+#ifdef CONFIG_PCIEASPM
+ struct pcie_link_state *link_state; /* ASPM link state. */
+#endif
+
pci_channel_state_t error_state; /* current connectivity state */
struct device dev; /* Generic device interface */
- /* device is compatible with these IDs */
- unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];
- unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];
-
int cfg_size; /* Size of configuration space */
/*
@@ -219,7 +219,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
}
static inline struct pci_cap_saved_state *pci_find_saved_cap(
- struct pci_dev *pci_dev,char cap)
+ struct pci_dev *pci_dev, char cap)
{
struct pci_cap_saved_state *tmp;
struct hlist_node *pos;
@@ -278,13 +278,13 @@ struct pci_bus {
unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
pci_bus_flags_t bus_flags; /* Inherited by child busses */
struct device *bridge;
- struct class_device class_dev;
+ struct device dev;
struct bin_attribute *legacy_io; /* legacy I/O for this bus */
struct bin_attribute *legacy_mem; /* legacy mem */
};
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
-#define to_pci_bus(n) container_of(n, struct pci_bus, class_dev)
+#define to_pci_bus(n) container_of(n, struct pci_bus, dev)
/*
* Error values that may be returned by PCI functions.
@@ -314,8 +314,8 @@ struct pci_raw_ops {
extern struct pci_raw_ops *raw_pci_ops;
struct pci_bus_region {
- unsigned long start;
- unsigned long end;
+ resource_size_t start;
+ resource_size_t end;
};
struct pci_dynids {
@@ -351,11 +351,10 @@ enum pci_ers_result {
};
/* PCI bus error event callbacks */
-struct pci_error_handlers
-{
+struct pci_error_handlers {
/* PCI bus error detected on this device */
pci_ers_result_t (*error_detected)(struct pci_dev *dev,
- enum pci_channel_state error);
+ enum pci_channel_state error);
/* MMIO has been re-enabled, but not DMA */
pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
@@ -390,7 +389,7 @@ struct pci_driver {
struct pci_dynids dynids;
};
-#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
+#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
/**
* PCI_DEVICE - macro used to describe a specific pci device
@@ -448,7 +447,7 @@ extern int no_pci_devices(void);
void pcibios_fixup_bus(struct pci_bus *);
int __must_check pcibios_enable_device(struct pci_dev *, int mask);
-char *pcibios_setup (char *str);
+char *pcibios_setup(char *str);
/* Used only when drivers/pci/setup.c is used */
void pcibios_align_resource(void *, struct resource *, resource_size_t,
@@ -459,8 +458,10 @@ void pcibios_update_irq(struct pci_dev *, int irq);
extern struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(struct pci_bus *bus);
-struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata);
+static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
+ void *sysdata)
{
struct pci_bus *root_bus;
root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
@@ -468,15 +469,18 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
pci_bus_add_devices(root_bus);
return root_bus;
}
-struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
-struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
+struct pci_bus *pci_create_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata);
+struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
+ int busnr);
int pci_scan_slot(struct pci_bus *bus, int devfn);
-struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
+struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn);
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
unsigned int pci_scan_child_bus(struct pci_bus *bus);
int __must_check pci_bus_add_device(struct pci_dev *dev);
void pci_read_bridge_bases(struct pci_bus *child);
-struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
+struct resource *pci_find_parent_resource(const struct pci_dev *dev,
+ struct resource *res);
int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
extern void pci_dev_put(struct pci_dev *dev);
@@ -489,15 +493,19 @@ extern void pci_sort_breadthfirst(void);
/* Generic PCI functions exported to card drivers */
#ifdef CONFIG_PCI_LEGACY
-struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_device(unsigned int vendor,
+ unsigned int device,
+ const struct pci_dev *from);
+struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
+ unsigned int devfn);
#endif /* CONFIG_PCI_LEGACY */
-int pci_find_capability (struct pci_dev *dev, int cap);
-int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
-int pci_find_ext_capability (struct pci_dev *dev, int cap);
-int pci_find_ht_capability (struct pci_dev *dev, int ht_cap);
-int pci_find_next_ht_capability (struct pci_dev *dev, int pos, int ht_cap);
+int pci_find_capability(struct pci_dev *dev, int cap);
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
+int pci_find_ext_capability(struct pci_dev *dev, int cap);
+int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
+int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
+void pcie_wait_pending_transaction(struct pci_dev *dev);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
@@ -505,49 +513,58 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
struct pci_dev *from);
-struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
+struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
unsigned int ss_vendor, unsigned int ss_device,
struct pci_dev *from);
-struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn);
-struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn);
-struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from);
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn);
+struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
int pci_dev_present(const struct pci_device_id *ids);
const struct pci_device_id *pci_find_present(const struct pci_device_id *ids);
-int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
-int pci_bus_read_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
-int pci_bus_read_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
-int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 val);
-int pci_bus_write_config_word (struct pci_bus *bus, unsigned int devfn, int where, u16 val);
-int pci_bus_write_config_dword (struct pci_bus *bus, unsigned int devfn, int where, u32 val);
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 *val);
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 *val);
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *val);
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn,
+ int where, u8 val);
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn,
+ int where, u16 val);
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, u32 val);
static inline int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
{
- return pci_bus_read_config_byte (dev->bus, dev->devfn, where, val);
+ return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
}
static inline int pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
{
- return pci_bus_read_config_word (dev->bus, dev->devfn, where, val);
+ return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
}
-static inline int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val)
+static inline int pci_read_config_dword(struct pci_dev *dev, int where,
+ u32 *val)
{
- return pci_bus_read_config_dword (dev->bus, dev->devfn, where, val);
+ return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
}
static inline int pci_write_config_byte(struct pci_dev *dev, int where, u8 val)
{
- return pci_bus_write_config_byte (dev->bus, dev->devfn, where, val);
+ return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
}
static inline int pci_write_config_word(struct pci_dev *dev, int where, u16 val)
{
- return pci_bus_write_config_word (dev->bus, dev->devfn, where, val);
+ return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
}
-static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val)
+static inline int pci_write_config_dword(struct pci_dev *dev, int where,
+ u32 val)
{
- return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val);
+ return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
}
int __must_check pci_enable_device(struct pci_dev *dev);
-int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
+int __must_check pci_enable_device_io(struct pci_dev *dev);
+int __must_check pci_enable_device_mem(struct pci_dev *dev);
int __must_check pci_reenable_device(struct pci_dev *);
int __must_check pcim_enable_device(struct pci_dev *pdev);
void pcim_pin_device(struct pci_dev *pdev);
@@ -576,14 +593,11 @@ int pcie_set_readrq(struct pci_dev *dev, int rq);
void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
-void pci_restore_bars(struct pci_dev *dev);
int pci_select_bars(struct pci_dev *dev, unsigned long flags);
/* ROM control related routines */
void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
-void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
-void pci_remove_rom(struct pci_dev *pdev);
size_t pci_get_rom_size(void __iomem *rom, size_t size);
/* Power management related routines */
@@ -594,7 +608,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
/* Functions for PCI Hotplug drivers to use */
-int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
+int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap);
/* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
void pci_bus_assign_resources(struct pci_bus *bus);
@@ -631,16 +645,18 @@ static inline int __must_check pci_register_driver(struct pci_driver *driver)
return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
}
-void pci_unregister_driver(struct pci_driver *);
-void pci_remove_behind_bridge(struct pci_dev *);
-struct pci_driver *pci_dev_driver(const struct pci_dev *);
-const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
-int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
+void pci_unregister_driver(struct pci_driver *dev);
+void pci_remove_behind_bridge(struct pci_dev *dev);
+struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
+const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+ struct pci_dev *dev);
+int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
+ int pass);
void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
void *userdata);
int pci_cfg_space_size(struct pci_dev *dev);
-unsigned char pci_bus_max_busnr(struct pci_bus* bus);
+unsigned char pci_bus_max_busnr(struct pci_bus *bus);
/* kmem_cache style wrapper around pci_alloc_consistent() */
@@ -669,19 +685,36 @@ struct msix_entry {
#ifndef CONFIG_PCI_MSI
-static inline int pci_enable_msi(struct pci_dev *dev) {return -1;}
-static inline void pci_disable_msi(struct pci_dev *dev) {}
-static inline int pci_enable_msix(struct pci_dev* dev,
- struct msix_entry *entries, int nvec) {return -1;}
-static inline void pci_disable_msix(struct pci_dev *dev) {}
-static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+static inline int pci_enable_msi(struct pci_dev *dev)
+{
+ return -1;
+}
+
+static inline void pci_disable_msi(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_msix(struct pci_dev *dev,
+ struct msix_entry *entries, int nvec)
+{
+ return -1;
+}
+
+static inline void pci_disable_msix(struct pci_dev *dev)
+{ }
+
+static inline void msi_remove_pci_irq_vectors(struct pci_dev *dev)
+{ }
+
+static inline void pci_restore_msi_state(struct pci_dev *dev)
+{ }
#else
extern int pci_enable_msi(struct pci_dev *dev);
extern void pci_disable_msi(struct pci_dev *dev);
-extern int pci_enable_msix(struct pci_dev* dev,
+extern int pci_enable_msix(struct pci_dev *dev,
struct msix_entry *entries, int nvec);
extern void pci_disable_msix(struct pci_dev *dev);
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+extern void pci_restore_msi_state(struct pci_dev *dev);
#endif
#ifdef CONFIG_HT_IRQ
@@ -702,7 +735,11 @@ extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
extern int pci_domains_supported;
#else
enum { pci_domains_supported = 0 };
-static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+ return 0;
+}
+
static inline int pci_proc_domain(struct pci_bus *bus)
{
return 0;
@@ -716,67 +753,161 @@ static inline int pci_proc_domain(struct pci_bus *bus)
* these as simple inline functions to avoid hair in drivers.
*/
-#define _PCI_NOP(o,s,t) \
- static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \
+#define _PCI_NOP(o, s, t) \
+ static inline int pci_##o##_config_##s(struct pci_dev *dev, \
+ int where, t val) \
{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
-#define _PCI_NOP_ALL(o,x) _PCI_NOP(o,byte,u8 x) \
- _PCI_NOP(o,word,u16 x) \
- _PCI_NOP(o,dword,u32 x)
+
+#define _PCI_NOP_ALL(o, x) _PCI_NOP(o, byte, u8 x) \
+ _PCI_NOP(o, word, u16 x) \
+ _PCI_NOP(o, dword, u32 x)
_PCI_NOP_ALL(read, *)
_PCI_NOP_ALL(write,)
-static inline struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_find_device(unsigned int vendor,
+ unsigned int device,
+ const struct pci_dev *from)
+{
+ return NULL;
+}
-static inline struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
-{ return NULL; }
+static inline struct pci_dev *pci_find_slot(unsigned int bus,
+ unsigned int devfn)
+{
+ return NULL;
+}
static inline struct pci_dev *pci_get_device(unsigned int vendor,
- unsigned int device, struct pci_dev *from)
-{ return NULL; }
+ unsigned int device,
+ struct pci_dev *from)
+{
+ return NULL;
+}
static inline struct pci_dev *pci_get_device_reverse(unsigned int vendor,
- unsigned int device, struct pci_dev *from)
-{ return NULL; }
+ unsigned int device,
+ struct pci_dev *from)
+{
+ return NULL;
+}
-static inline struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device,
-unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_subsys(unsigned int vendor,
+ unsigned int device,
+ unsigned int ss_vendor,
+ unsigned int ss_device,
+ struct pci_dev *from)
+{
+ return NULL;
+}
-static inline struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
-{ return NULL; }
+static inline struct pci_dev *pci_get_class(unsigned int class,
+ struct pci_dev *from)
+{
+ return NULL;
+}
#define pci_dev_present(ids) (0)
#define no_pci_devices() (1)
#define pci_find_present(ids) (NULL)
#define pci_dev_put(dev) do { } while (0)
-static inline void pci_set_master(struct pci_dev *dev) { }
-static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
-static inline void pci_disable_device(struct pci_dev *dev) { }
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; }
-static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
-static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;}
-static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
-static inline void pci_unregister_driver(struct pci_driver *drv) { }
-static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
-static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
-static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
+static inline void pci_set_master(struct pci_dev *dev)
+{ }
+
+static inline int pci_enable_device(struct pci_dev *dev)
+{
+ return -EIO;
+}
+
+static inline void pci_disable_device(struct pci_dev *dev)
+{ }
+
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+ return -EIO;
+}
+
+static inline int pci_assign_resource(struct pci_dev *dev, int i)
+{
+ return -EBUSY;
+}
+
+static inline int __pci_register_driver(struct pci_driver *drv,
+ struct module *owner)
+{
+ return 0;
+}
+
+static inline int pci_register_driver(struct pci_driver *drv)
+{
+ return 0;
+}
+
+static inline void pci_unregister_driver(struct pci_driver *drv)
+{ }
+
+static inline int pci_find_capability(struct pci_dev *dev, int cap)
+{
+ return 0;
+}
+
+static inline int pci_find_next_capability(struct pci_dev *dev, u8 post,
+ int cap)
+{
+ return 0;
+}
+
+static inline int pci_find_ext_capability(struct pci_dev *dev, int cap)
+{
+ return 0;
+}
+
+static inline void pcie_wait_pending_transaction(struct pci_dev *dev)
+{ }
/* Power management related routines */
-static inline int pci_save_state(struct pci_dev *dev) { return 0; }
-static inline int pci_restore_state(struct pci_dev *dev) { return 0; }
-static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) { return 0; }
-static inline pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) { return PCI_D0; }
-static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable) { return 0; }
+static inline int pci_save_state(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static inline int pci_restore_state(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
+{
+ return 0;
+}
+
+static inline pci_power_t pci_choose_state(struct pci_dev *dev,
+ pm_message_t state)
+{
+ return PCI_D0;
+}
+
+static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
+ int enable)
+{
+ return 0;
+}
+
+static inline int pci_request_regions(struct pci_dev *dev, const char *res_name)
+{
+ return -EIO;
+}
-static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
-static inline void pci_release_regions(struct pci_dev *dev) { }
+static inline void pci_release_regions(struct pci_dev *dev)
+{ }
#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
-static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
-static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
+static inline void pci_block_user_cfg_access(struct pci_dev *dev)
+{ }
+
+static inline void pci_unblock_user_cfg_access(struct pci_dev *dev)
+{ }
static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
{ return NULL; }
@@ -797,27 +928,27 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
/* these helpers provide future and backwards compatibility
* for accessing popular PCI BAR info */
-#define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start)
-#define pci_resource_end(dev,bar) ((dev)->resource[(bar)].end)
-#define pci_resource_flags(dev,bar) ((dev)->resource[(bar)].flags)
+#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
+#define pci_resource_end(dev, bar) ((dev)->resource[(bar)].end)
+#define pci_resource_flags(dev, bar) ((dev)->resource[(bar)].flags)
#define pci_resource_len(dev,bar) \
- ((pci_resource_start((dev),(bar)) == 0 && \
- pci_resource_end((dev),(bar)) == \
- pci_resource_start((dev),(bar))) ? 0 : \
- \
- (pci_resource_end((dev),(bar)) - \
- pci_resource_start((dev),(bar)) + 1))
+ ((pci_resource_start((dev), (bar)) == 0 && \
+ pci_resource_end((dev), (bar)) == \
+ pci_resource_start((dev), (bar))) ? 0 : \
+ \
+ (pci_resource_end((dev), (bar)) - \
+ pci_resource_start((dev), (bar)) + 1))
/* Similar to the helpers above, these manipulate per-pci_dev
* driver-specific data. They are really just a wrapper around
* the generic device structure functions of these calls.
*/
-static inline void *pci_get_drvdata (struct pci_dev *pdev)
+static inline void *pci_get_drvdata(struct pci_dev *pdev)
{
return dev_get_drvdata(&pdev->dev);
}
-static inline void pci_set_drvdata (struct pci_dev *pdev, void *data)
+static inline void pci_set_drvdata(struct pci_dev *pdev, void *data)
{
dev_set_drvdata(&pdev->dev, data);
}
@@ -836,7 +967,7 @@ static inline char *pci_name(struct pci_dev *pdev)
*/
#ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
- const struct resource *rsrc, resource_size_t *start,
+ const struct resource *rsrc, resource_size_t *start,
resource_size_t *end)
{
*start = rsrc->start;
@@ -888,9 +1019,9 @@ enum pci_fixup_pass {
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
-void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
+void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
-void __iomem * const * pcim_iomap_table(struct pci_dev *pdev);
+void __iomem * const *pcim_iomap_table(struct pci_dev *pdev);
int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name);
void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask);
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index c1914a8b94a..c0c1223c919 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -395,9 +395,17 @@
#define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
#define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
+#define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */
+#define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */
+#define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */
+#define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */
#define PCI_EXP_LNKCTL 16 /* Link Control */
+#define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */
+#define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */
#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
#define PCI_EXP_LNKSTA 18 /* Link Status */
+#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */
+#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
#define PCI_EXP_SLTCTL 24 /* Slot Control */
#define PCI_EXP_SLTSTA 26 /* Slot Status */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 5fc8ff73b7b..2372e2e6b52 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -162,19 +162,19 @@ struct usb_interface {
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
struct device dev; /* interface specific device info */
- struct device *usb_dev; /* pointer to the usb class's device, if any */
+ struct device *usb_dev;
int pm_usage_cnt; /* usage counter for autosuspend */
};
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
#define interface_to_usbdev(intf) \
container_of(intf->dev.parent, struct usb_device, dev)
-static inline void *usb_get_intfdata (struct usb_interface *intf)
+static inline void *usb_get_intfdata(struct usb_interface *intf)
{
- return dev_get_drvdata (&intf->dev);
+ return dev_get_drvdata(&intf->dev);
}
-static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
+static inline void usb_set_intfdata(struct usb_interface *intf, void *data)
{
dev_set_drvdata(&intf->dev, data);
}
@@ -275,9 +275,10 @@ struct usb_host_config {
int __usb_get_extra_descriptor(char *buffer, unsigned size,
unsigned char type, void **ptr);
-#define usb_get_extra_descriptor(ifpoint,type,ptr)\
- __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
- type,(void**)ptr)
+#define usb_get_extra_descriptor(ifpoint, type, ptr) \
+ __usb_get_extra_descriptor((ifpoint)->extra, \
+ (ifpoint)->extralen, \
+ type, (void **)ptr)
/* ----------------------------------------------------------------------- */
@@ -318,7 +319,7 @@ struct usb_bus {
#ifdef CONFIG_USB_DEVICEFS
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
#endif
- struct class_device *class_dev; /* class device for this bus */
+ struct device *dev; /* device for this bus */
#if defined(CONFIG_USB_MON)
struct mon_bus *mon_bus; /* non-null when associated */
@@ -388,7 +389,7 @@ struct usb_device {
unsigned can_submit:1; /* URBs may be submitted */
unsigned discon_suspended:1; /* Disconnected while suspended */
unsigned have_langid:1; /* whether string_langid is valid */
- unsigned authorized:1; /* Policy has determined we can use it */
+ unsigned authorized:1; /* Policy has said we can use it */
unsigned wusb:1; /* Device is Wireless USB */
int string_langid; /* language ID for strings */
@@ -417,7 +418,10 @@ struct usb_device {
int pm_usage_cnt; /* usage counter for autosuspend */
u32 quirks; /* quirks of the whole device */
- atomic_t urbnum; /* number of URBs submitted for the whole device */
+ atomic_t urbnum; /* number of URBs submitted for
+ the whole device */
+
+ unsigned long active_duration; /* total time device is not suspended */
#ifdef CONFIG_PM
struct delayed_work autosuspend; /* for delayed autosuspends */
@@ -425,6 +429,7 @@ struct usb_device {
unsigned long last_busy; /* time of last use */
int autosuspend_delay; /* in jiffies */
+ unsigned long connect_time; /* time device was first connected */
unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
@@ -498,11 +503,11 @@ static inline void usb_mark_last_busy(struct usb_device *udev)
/*-------------------------------------------------------------------------*/
/* for drivers using iso endpoints */
-extern int usb_get_current_frame_number (struct usb_device *usb_dev);
+extern int usb_get_current_frame_number(struct usb_device *usb_dev);
/* used these for multi-interface device registration */
extern int usb_driver_claim_interface(struct usb_driver *driver,
- struct usb_interface *iface, void* priv);
+ struct usb_interface *iface, void *priv);
/**
* usb_interface_claimed - returns true iff an interface is claimed
@@ -514,7 +519,8 @@ extern int usb_driver_claim_interface(struct usb_driver *driver,
* may need to explicitly claim that lock.
*
*/
-static inline int usb_interface_claimed(struct usb_interface *iface) {
+static inline int usb_interface_claimed(struct usb_interface *iface)
+{
return (iface->dev.driver != NULL);
}
@@ -557,12 +563,11 @@ extern struct usb_host_interface *usb_altnum_to_altsetting(
* USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are
* high speed, and a different one if they are full or low speed.
*/
-static inline int usb_make_path (struct usb_device *dev, char *buf,
- size_t size)
+static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
{
int actual;
- actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name,
- dev->devpath);
+ actual = snprintf(buf, size, "usb-%s-%s", dev->bus->bus_name,
+ dev->devpath);
return (actual >= (int)size) ? -1 : actual;
}
@@ -608,7 +613,8 @@ static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
*
* Returns true if the endpoint is of type OUT, otherwise it returns false.
*/
-static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_dir_out(
+ const struct usb_endpoint_descriptor *epd)
{
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
}
@@ -619,7 +625,8 @@ static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd
*
* Returns true if the endpoint is of type bulk, otherwise it returns false.
*/
-static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_bulk(
+ const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK);
@@ -631,7 +638,8 @@ static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *e
*
* Returns true if the endpoint is of type control, otherwise it returns false.
*/
-static inline int usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_control(
+ const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_CONTROL);
@@ -644,7 +652,8 @@ static inline int usb_endpoint_xfer_control(const struct usb_endpoint_descriptor
* Returns true if the endpoint is of type interrupt, otherwise it returns
* false.
*/
-static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_int(
+ const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT);
@@ -657,7 +666,8 @@ static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *ep
* Returns true if the endpoint is of type isochronous, otherwise it returns
* false.
*/
-static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_xfer_isoc(
+ const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_ISOC);
@@ -670,7 +680,8 @@ static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *e
* Returns true if the endpoint has bulk transfer type and IN direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_bulk_in(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
}
@@ -682,7 +693,8 @@ static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *
* Returns true if the endpoint has bulk transfer type and OUT direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_bulk_out(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
}
@@ -694,7 +706,8 @@ static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor
* Returns true if the endpoint has interrupt transfer type and IN direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_int_in(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
}
@@ -706,7 +719,8 @@ static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *e
* Returns true if the endpoint has interrupt transfer type and OUT direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_int_out(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
}
@@ -718,7 +732,8 @@ static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *
* Returns true if the endpoint has isochronous transfer type and IN direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_isoc_in(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
}
@@ -730,7 +745,8 @@ static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *
* Returns true if the endpoint has isochronous transfer type and OUT direction,
* otherwise it returns false.
*/
-static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+static inline int usb_endpoint_is_isoc_out(
+ const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
}
@@ -761,8 +777,9 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* specific device.
*/
#define USB_DEVICE(vend,prod) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
- .idProduct = (prod)
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
+ .idVendor = (vend), \
+ .idProduct = (prod)
/**
* USB_DEVICE_VER - macro used to describe a specific usb device with a
* version range
@@ -774,10 +791,12 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* This macro is used to create a struct usb_device_id that matches a
* specific device, with a version range.
*/
-#define USB_DEVICE_VER(vend,prod,lo,hi) \
+#define USB_DEVICE_VER(vend, prod, lo, hi) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \
- .idVendor = (vend), .idProduct = (prod), \
- .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bcdDevice_lo = (lo), \
+ .bcdDevice_hi = (hi)
/**
* USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
@@ -789,8 +808,9 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* This macro is used to create a struct usb_device_id that matches a
* specific interface protocol of devices.
*/
-#define USB_DEVICE_INTERFACE_PROTOCOL(vend,prod,pr) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend, prod, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
.idVendor = (vend), \
.idProduct = (prod), \
.bInterfaceProtocol = (pr)
@@ -804,12 +824,14 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* This macro is used to create a struct usb_device_id that matches a
* specific class of devices.
*/
-#define USB_DEVICE_INFO(cl,sc,pr) \
- .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
- .bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
+#define USB_DEVICE_INFO(cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, \
+ .bDeviceClass = (cl), \
+ .bDeviceSubClass = (sc), \
+ .bDeviceProtocol = (pr)
/**
- * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces
+ * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces
* @cl: bInterfaceClass value
* @sc: bInterfaceSubClass value
* @pr: bInterfaceProtocol value
@@ -817,9 +839,11 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* This macro is used to create a struct usb_device_id that matches a
* specific class of interfaces.
*/
-#define USB_INTERFACE_INFO(cl,sc,pr) \
- .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
- .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+#define USB_INTERFACE_INFO(cl, sc, pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \
+ .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr)
/**
* USB_DEVICE_AND_INTERFACE_INFO - macro used to describe a specific usb device
@@ -836,12 +860,14 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
* This is especially useful when explicitly matching devices that have
* vendor specific bDeviceClass values, but standards-compliant interfaces.
*/
-#define USB_DEVICE_AND_INTERFACE_INFO(vend,prod,cl,sc,pr) \
+#define USB_DEVICE_AND_INTERFACE_INFO(vend, prod, cl, sc, pr) \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
| USB_DEVICE_ID_MATCH_DEVICE, \
- .idVendor = (vend), .idProduct = (prod), \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
.bInterfaceClass = (cl), \
- .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr)
/* ----------------------------------------------------------------------- */
@@ -1119,7 +1145,7 @@ typedef void (*usb_complete_t)(struct urb *);
* transferred. It will normally be the same as requested, unless
* either an error was reported or a short read was performed.
* The URB_SHORT_NOT_OK transfer flag may be used to make such
- * short reads be reported as errors.
+ * short reads be reported as errors.
* @setup_packet: Only used for control transfers, this points to eight bytes
* of setup data. Control transfers always start by sending this data
* to the device. Then transfer_buffer is read or written, if needed.
@@ -1138,7 +1164,7 @@ typedef void (*usb_complete_t)(struct urb *);
* @complete: Completion handler. This URB is passed as the parameter to the
* completion function. The completion function may then do what
* it likes with the URB, including resubmitting or freeing it.
- * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
+ * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
* collect the transfer status for each buffer.
*
* This structure identifies USB transfer requests. URBs must be allocated by
@@ -1242,8 +1268,7 @@ typedef void (*usb_complete_t)(struct urb *);
* when the urb is owned by the hcd, that is, since the call to
* usb_submit_urb() till the entry into the completion routine.
*/
-struct urb
-{
+struct urb {
/* private: usb core and host controller only fields in the urb */
struct kref kref; /* reference count of the URB */
void *hcpriv; /* private data for host controller */
@@ -1254,10 +1279,10 @@ struct urb
/* public: documented fields in the urb that can be used by drivers */
struct list_head urb_list; /* list head for use by the urb's
* current owner */
- struct list_head anchor_list; /* the URB may be anchored by the driver */
+ struct list_head anchor_list; /* the URB may be anchored */
struct usb_anchor *anchor;
struct usb_device *dev; /* (in) pointer to associated device */
- struct usb_host_endpoint *ep; /* (internal) pointer to endpoint struct */
+ struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
@@ -1294,14 +1319,14 @@ struct urb
* Initializes a control urb with the proper information needed to submit
* it to a device.
*/
-static inline void usb_fill_control_urb (struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- unsigned char *setup_packet,
- void *transfer_buffer,
- int buffer_length,
- usb_complete_t complete_fn,
- void *context)
+static inline void usb_fill_control_urb(struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ unsigned char *setup_packet,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete_fn,
+ void *context)
{
urb->dev = dev;
urb->pipe = pipe;
@@ -1325,13 +1350,13 @@ static inline void usb_fill_control_urb (struct urb *urb,
* Initializes a bulk urb with the proper information needed to submit it
* to a device.
*/
-static inline void usb_fill_bulk_urb (struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- void *transfer_buffer,
- int buffer_length,
- usb_complete_t complete_fn,
- void *context)
+static inline void usb_fill_bulk_urb(struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete_fn,
+ void *context)
{
urb->dev = dev;
urb->pipe = pipe;
@@ -1359,14 +1384,14 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
* the endpoint interval, and express polling intervals in microframes
* (eight per millisecond) rather than in frames (one per millisecond).
*/
-static inline void usb_fill_int_urb (struct urb *urb,
- struct usb_device *dev,
- unsigned int pipe,
- void *transfer_buffer,
- int buffer_length,
- usb_complete_t complete_fn,
- void *context,
- int interval)
+static inline void usb_fill_int_urb(struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete_fn,
+ void *context,
+ int interval)
{
urb->dev = dev;
urb->pipe = pipe;
@@ -1419,15 +1444,15 @@ static inline int usb_urb_dir_out(struct urb *urb)
return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT;
}
-void *usb_buffer_alloc (struct usb_device *dev, size_t size,
+void *usb_buffer_alloc(struct usb_device *dev, size_t size,
gfp_t mem_flags, dma_addr_t *dma);
-void usb_buffer_free (struct usb_device *dev, size_t size,
+void usb_buffer_free(struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
#if 0
-struct urb *usb_buffer_map (struct urb *urb);
-void usb_buffer_dmasync (struct urb *urb);
-void usb_buffer_unmap (struct urb *urb);
+struct urb *usb_buffer_map(struct urb *urb);
+void usb_buffer_dmasync(struct urb *urb);
+void usb_buffer_unmap(struct urb *urb);
#endif
struct scatterlist;
@@ -1499,7 +1524,7 @@ struct usb_sg_request {
int status;
size_t bytes;
- /*
+ /*
* members below are private: to usbcore,
* and are not provided for driver access!
*/
@@ -1517,18 +1542,18 @@ struct usb_sg_request {
struct completion complete;
};
-int usb_sg_init (
+int usb_sg_init(
struct usb_sg_request *io,
struct usb_device *dev,
- unsigned pipe,
+ unsigned pipe,
unsigned period,
struct scatterlist *sg,
int nents,
size_t length,
gfp_t mem_flags
);
-void usb_sg_cancel (struct usb_sg_request *io);
-void usb_sg_wait (struct usb_sg_request *io);
+void usb_sg_cancel(struct usb_sg_request *io);
+void usb_sg_wait(struct usb_sg_request *io);
/* ----------------------------------------------------------------------- */
@@ -1585,21 +1610,21 @@ static inline unsigned int __create_pipe(struct usb_device *dev,
/* Create various pipes... */
#define usb_sndctrlpipe(dev,endpoint) \
- ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+ ((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))
#define usb_rcvctrlpipe(dev,endpoint) \
- ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+ ((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndisocpipe(dev,endpoint) \
- ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+ ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
#define usb_rcvisocpipe(dev,endpoint) \
- ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+ ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndbulkpipe(dev,endpoint) \
- ((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+ ((PIPE_BULK << 30) | __create_pipe(dev, endpoint))
#define usb_rcvbulkpipe(dev,endpoint) \
- ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+ ((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev,endpoint) \
- ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
+ ((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
#define usb_rcvintpipe(dev,endpoint) \
- ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+ ((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
/*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 6ce42bf9f74..b8cba1dcb2c 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,6 +1,7 @@
-unifdef-y += audio.h
-unifdef-y += cdc.h
-unifdef-y += ch9.h
-unifdef-y += gadgetfs.h
-unifdef-y += midi.h
+header-y += audio.h
+header-y += cdc.h
+header-y += ch9.h
+header-y += gadgetfs.h
+header-y += midi.h
+unifdef-y += g_printer.h
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 6bd235994dc..2dfeef16b22 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -27,13 +27,13 @@
/* 4.3.2 Class-Specific AC Interface Descriptor */
struct usb_ac_header_descriptor {
- __u8 bLength; // 8+n
- __u8 bDescriptorType; // USB_DT_CS_INTERFACE
- __u8 bDescriptorSubtype; // USB_MS_HEADER
- __le16 bcdADC; // 0x0100
- __le16 wTotalLength; // includes Unit and Terminal desc.
- __u8 bInCollection; // n
- __u8 baInterfaceNr[]; // [n]
+ __u8 bLength; /* 8+n */
+ __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
+ __u8 bDescriptorSubtype; /* USB_MS_HEADER */
+ __le16 bcdADC; /* 0x0100 */
+ __le16 wTotalLength; /* includes Unit and Terminal desc. */
+ __u8 bInCollection; /* n */
+ __u8 baInterfaceNr[]; /* [n] */
} __attribute__ ((packed));
#define USB_DT_AC_HEADER_SIZE(n) (8+(n))
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index 2204ae22c38..94ee4ecf056 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -29,16 +29,16 @@
* Class-Specific descriptors ... there are a couple dozen of them
*/
-#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
-#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
-#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
-#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
+#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
+#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
#define USB_CDC_COUNTRY_TYPE 0x07
-#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */
-#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
+#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */
+#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
#define USB_CDC_WHCM_TYPE 0x11
-#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
-#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
+#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
#define USB_CDC_DMM_TYPE 0x14
#define USB_CDC_OBEX_TYPE 0x15
diff --git a/include/linux/usb/g_printer.h b/include/linux/usb/g_printer.h
new file mode 100644
index 00000000000..0c5ea1e3eb9
--- /dev/null
+++ b/include/linux/usb/g_printer.h
@@ -0,0 +1,31 @@
+/*
+ * g_printer.h -- Header file for USB Printer gadget driver
+ *
+ * Copyright (C) 2007 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
+ */
+
+
+#define PRINTER_NOT_ERROR 0x08
+#define PRINTER_SELECTED 0x10
+#define PRINTER_PAPER_EMPTY 0x20
+
+/* The 'g' code is also used by gadgetfs ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+#define GADGET_GET_PRINTER_STATUS _IOR('g', 0x21, unsigned char)
+#define GADGET_SET_PRINTER_STATUS _IOWR('g', 0x22, unsigned char)
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index c1527c2ef3c..aa3047ff00d 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -70,9 +70,10 @@ struct usb_ep;
*
* Bulk endpoints can use any size buffers, and can also be used for interrupt
* transfers. interrupt-only endpoints can be much less functional.
+ *
+ * NOTE: this is analagous to 'struct urb' on the host side, except that
+ * it's thinner and promotes more pre-allocation.
*/
- // NOTE this is analagous to 'struct urb' on the host side,
- // except that it's thinner and promotes more pre-allocation.
struct usb_request {
void *buf;
@@ -168,10 +169,10 @@ struct usb_ep {
*
* returns zero, or a negative error code.
*/
-static inline int
-usb_ep_enable (struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+static inline int usb_ep_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
{
- return ep->ops->enable (ep, desc);
+ return ep->ops->enable(ep, desc);
}
/**
@@ -186,10 +187,9 @@ usb_ep_enable (struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
*
* returns zero, or a negative error code.
*/
-static inline int
-usb_ep_disable (struct usb_ep *ep)
+static inline int usb_ep_disable(struct usb_ep *ep)
{
- return ep->ops->disable (ep);
+ return ep->ops->disable(ep);
}
/**
@@ -206,10 +206,10 @@ usb_ep_disable (struct usb_ep *ep)
*
* Returns the request, or null if one could not be allocated.
*/
-static inline struct usb_request *
-usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
+static inline struct usb_request *usb_ep_alloc_request(struct usb_ep *ep,
+ gfp_t gfp_flags)
{
- return ep->ops->alloc_request (ep, gfp_flags);
+ return ep->ops->alloc_request(ep, gfp_flags);
}
/**
@@ -221,10 +221,10 @@ usb_ep_alloc_request (struct usb_ep *ep, gfp_t gfp_flags)
* Caller guarantees the request is not queued, and that it will
* no longer be requeued (or otherwise used).
*/
-static inline void
-usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
+static inline void usb_ep_free_request(struct usb_ep *ep,
+ struct usb_request *req)
{
- ep->ops->free_request (ep, req);
+ ep->ops->free_request(ep, req);
}
/**
@@ -281,10 +281,10 @@ usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
* report errors; errors will also be
* reported when the usb peripheral is disconnected.
*/
-static inline int
-usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
+static inline int usb_ep_queue(struct usb_ep *ep,
+ struct usb_request *req, gfp_t gfp_flags)
{
- return ep->ops->queue (ep, req, gfp_flags);
+ return ep->ops->queue(ep, req, gfp_flags);
}
/**
@@ -301,9 +301,9 @@ usb_ep_queue (struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags)
* restrictions prevent drivers from supporting configuration changes,
* even to configuration zero (a "chapter 9" requirement).
*/
-static inline int usb_ep_dequeue (struct usb_ep *ep, struct usb_request *req)
+static inline int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
- return ep->ops->dequeue (ep, req);
+ return ep->ops->dequeue(ep, req);
}
/**
@@ -327,10 +327,9 @@ static inline int usb_ep_dequeue (struct usb_ep *ep, struct usb_request *req)
* transfer requests are still queued, or if the controller hardware
* (usually a FIFO) still holds bytes that the host hasn't collected.
*/
-static inline int
-usb_ep_set_halt (struct usb_ep *ep)
+static inline int usb_ep_set_halt(struct usb_ep *ep)
{
- return ep->ops->set_halt (ep, 1);
+ return ep->ops->set_halt(ep, 1);
}
/**
@@ -346,10 +345,9 @@ usb_ep_set_halt (struct usb_ep *ep)
* Note that some hardware can't support this request (like pxa2xx_udc),
* and accordingly can't correctly implement interface altsettings.
*/
-static inline int
-usb_ep_clear_halt (struct usb_ep *ep)
+static inline int usb_ep_clear_halt(struct usb_ep *ep)
{
- return ep->ops->set_halt (ep, 0);
+ return ep->ops->set_halt(ep, 0);
}
/**
@@ -367,11 +365,10 @@ usb_ep_clear_halt (struct usb_ep *ep)
* errno if the endpoint doesn't use a FIFO or doesn't support such
* precise handling.
*/
-static inline int
-usb_ep_fifo_status (struct usb_ep *ep)
+static inline int usb_ep_fifo_status(struct usb_ep *ep)
{
if (ep->ops->fifo_status)
- return ep->ops->fifo_status (ep);
+ return ep->ops->fifo_status(ep);
else
return -EOPNOTSUPP;
}
@@ -385,11 +382,10 @@ usb_ep_fifo_status (struct usb_ep *ep)
* must never be used except when endpoint is not being used for any
* protocol translation.
*/
-static inline void
-usb_ep_fifo_flush (struct usb_ep *ep)
+static inline void usb_ep_fifo_flush(struct usb_ep *ep)
{
if (ep->ops->fifo_flush)
- ep->ops->fifo_flush (ep);
+ ep->ops->fifo_flush(ep);
}
@@ -469,10 +465,10 @@ struct usb_gadget {
struct device dev;
};
-static inline void set_gadget_data (struct usb_gadget *gadget, void *data)
- { dev_set_drvdata (&gadget->dev, data); }
-static inline void *get_gadget_data (struct usb_gadget *gadget)
- { return dev_get_drvdata (&gadget->dev); }
+static inline void set_gadget_data(struct usb_gadget *gadget, void *data)
+ { dev_set_drvdata(&gadget->dev, data); }
+static inline void *get_gadget_data(struct usb_gadget *gadget)
+ { return dev_get_drvdata(&gadget->dev); }
/* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */
#define gadget_for_each_ep(tmp,gadget) \
@@ -511,7 +507,6 @@ static inline int gadget_is_otg(struct usb_gadget *g)
#endif
}
-
/**
* usb_gadget_frame_number - returns the current frame number
* @gadget: controller that reports the frame number
@@ -519,9 +514,9 @@ static inline int gadget_is_otg(struct usb_gadget *g)
* Returns the usb frame number, normally eleven bits from a SOF packet,
* or negative errno if this device doesn't support this capability.
*/
-static inline int usb_gadget_frame_number (struct usb_gadget *gadget)
+static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
{
- return gadget->ops->get_frame (gadget);
+ return gadget->ops->get_frame(gadget);
}
/**
@@ -537,11 +532,11 @@ static inline int usb_gadget_frame_number (struct usb_gadget *gadget)
* even if OTG isn't otherwise in use. OTG devices may also start
* remote wakeup even when hosts don't explicitly enable it.
*/
-static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
+static inline int usb_gadget_wakeup(struct usb_gadget *gadget)
{
if (!gadget->ops->wakeup)
return -EOPNOTSUPP;
- return gadget->ops->wakeup (gadget);
+ return gadget->ops->wakeup(gadget);
}
/**
@@ -553,12 +548,11 @@ static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
*
* returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_set_selfpowered (struct usb_gadget *gadget)
+static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
{
if (!gadget->ops->set_selfpowered)
return -EOPNOTSUPP;
- return gadget->ops->set_selfpowered (gadget, 1);
+ return gadget->ops->set_selfpowered(gadget, 1);
}
/**
@@ -571,12 +565,11 @@ usb_gadget_set_selfpowered (struct usb_gadget *gadget)
*
* returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_clear_selfpowered (struct usb_gadget *gadget)
+static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget)
{
if (!gadget->ops->set_selfpowered)
return -EOPNOTSUPP;
- return gadget->ops->set_selfpowered (gadget, 0);
+ return gadget->ops->set_selfpowered(gadget, 0);
}
/**
@@ -591,12 +584,11 @@ usb_gadget_clear_selfpowered (struct usb_gadget *gadget)
*
* Returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_vbus_connect(struct usb_gadget *gadget)
+static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget)
{
if (!gadget->ops->vbus_session)
return -EOPNOTSUPP;
- return gadget->ops->vbus_session (gadget, 1);
+ return gadget->ops->vbus_session(gadget, 1);
}
/**
@@ -611,12 +603,11 @@ usb_gadget_vbus_connect(struct usb_gadget *gadget)
*
* Returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
{
if (!gadget->ops->vbus_draw)
return -EOPNOTSUPP;
- return gadget->ops->vbus_draw (gadget, mA);
+ return gadget->ops->vbus_draw(gadget, mA);
}
/**
@@ -629,12 +620,11 @@ usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
*
* Returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
+static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
{
if (!gadget->ops->vbus_session)
return -EOPNOTSUPP;
- return gadget->ops->vbus_session (gadget, 0);
+ return gadget->ops->vbus_session(gadget, 0);
}
/**
@@ -648,12 +638,11 @@ usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
*
* Returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_connect (struct usb_gadget *gadget)
+static inline int usb_gadget_connect(struct usb_gadget *gadget)
{
if (!gadget->ops->pullup)
return -EOPNOTSUPP;
- return gadget->ops->pullup (gadget, 1);
+ return gadget->ops->pullup(gadget, 1);
}
/**
@@ -671,16 +660,14 @@ usb_gadget_connect (struct usb_gadget *gadget)
*
* Returns zero on success, else negative errno.
*/
-static inline int
-usb_gadget_disconnect (struct usb_gadget *gadget)
+static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
{
if (!gadget->ops->pullup)
return -EOPNOTSUPP;
- return gadget->ops->pullup (gadget, 0);
+ return gadget->ops->pullup(gadget, 0);
}
-
/*-------------------------------------------------------------------------*/
/**
@@ -764,7 +751,7 @@ struct usb_gadget_driver {
void (*suspend)(struct usb_gadget *);
void (*resume)(struct usb_gadget *);
- // FIXME support safe rmmod
+ /* FIXME support safe rmmod */
struct device_driver driver;
};
@@ -790,7 +777,7 @@ struct usb_gadget_driver {
* the bind() functions will be in init sections.
* This function must be called in a context that can sleep.
*/
-int usb_gadget_register_driver (struct usb_gadget_driver *driver);
+int usb_gadget_register_driver(struct usb_gadget_driver *driver);
/**
* usb_gadget_unregister_driver - unregister a gadget driver
@@ -805,7 +792,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver);
* will in in exit sections, so may not be linked in some kernels.
* This function must be called in a context that can sleep.
*/
-int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
/*-------------------------------------------------------------------------*/
@@ -838,7 +825,7 @@ struct usb_gadget_strings {
};
/* put descriptor for string with that id into buf (buflen >= 256) */
-int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
+int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf);
/*-------------------------------------------------------------------------*/
@@ -856,10 +843,10 @@ int usb_gadget_config_buf(const struct usb_config_descriptor *config,
/* utility wrapping a simple endpoint selection policy */
-extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,
+extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
struct usb_endpoint_descriptor *) __devinit;
-extern void usb_ep_autoconfig_reset (struct usb_gadget *) __devinit;
+extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
#endif /* __KERNEL__ */
diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
index e8654c33872..c291ab1af74 100644
--- a/include/linux/usb/gadgetfs.h
+++ b/include/linux/usb/gadgetfs.h
@@ -36,7 +36,7 @@ enum usb_gadgetfs_event_type {
GADGETFS_DISCONNECT,
GADGETFS_SETUP,
GADGETFS_SUSPEND,
- // and likely more !
+ /* and likely more ! */
};
/* NOTE: this structure must stay the same size and layout on
@@ -44,21 +44,28 @@ enum usb_gadgetfs_event_type {
*/
struct usb_gadgetfs_event {
union {
- // NOP, DISCONNECT, SUSPEND: nothing
- // ... some hardware can't report disconnection
+ /* NOP, DISCONNECT, SUSPEND: nothing
+ * ... some hardware can't report disconnection
+ */
- // CONNECT: just the speed
+ /* CONNECT: just the speed */
enum usb_device_speed speed;
- // SETUP: packet; DATA phase i/o precedes next event
- // (setup.bmRequestType & USB_DIR_IN) flags direction
- // ... includes SET_CONFIGURATION, SET_INTERFACE
+ /* SETUP: packet; DATA phase i/o precedes next event
+ *(setup.bmRequestType & USB_DIR_IN) flags direction
+ * ... includes SET_CONFIGURATION, SET_INTERFACE
+ */
struct usb_ctrlrequest setup;
} u;
enum usb_gadgetfs_event_type type;
};
+/* The 'g' code is also used by printer gadget ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+
/* endpoint ioctls */
/* IN transfers may be reported to the gadget driver as complete
@@ -68,14 +75,14 @@ struct usb_gadgetfs_event {
* THIS returns how many bytes are "unclaimed" in the endpoint fifo
* (needed for precise fault handling, when the hardware allows it)
*/
-#define GADGETFS_FIFO_STATUS _IO('g',1)
+#define GADGETFS_FIFO_STATUS _IO('g', 1)
/* discards any unclaimed data in the fifo. */
-#define GADGETFS_FIFO_FLUSH _IO('g',2)
+#define GADGETFS_FIFO_FLUSH _IO('g', 2)
/* resets endpoint halt+toggle; used to implement set_interface.
* some hardware (like pxa2xx) can't support this.
*/
-#define GADGETFS_CLEAR_HALT _IO('g',3)
+#define GADGETFS_CLEAR_HALT _IO('g', 3)
#endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/linux/usb/iowarrior.h b/include/linux/usb/iowarrior.h
index cbbe020a4f5..de6f380e17a 100644
--- a/include/linux/usb/iowarrior.h
+++ b/include/linux/usb/iowarrior.h
@@ -14,14 +14,23 @@
this information.
*/
struct iowarrior_info {
- __u32 vendor; /* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
- __u32 product; /* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_XXXXX) */
- __u8 serial[9]; /* the serial number of our chip (if a serial-number is not available this is empty string) */
- __u32 revision; /* revision number of the chip */
- __u32 speed; /* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
- __u32 power; /* power consumption of the device in mA */
- __u32 if_num; /* the number of the endpoint */
- __u32 report_size; /* size of the data-packets on this interface */
+ /* vendor id : supposed to be USB_VENDOR_ID_CODEMERCS in all cases */
+ __u32 vendor;
+ /* product id : depends on type of chip (USB_DEVICE_ID_CODEMERCS_X) */
+ __u32 product;
+ /* the serial number of our chip (if a serial-number is not available
+ * this is empty string) */
+ __u8 serial[9];
+ /* revision number of the chip */
+ __u32 revision;
+ /* USB-speed of the device (0=UNKNOWN, 1=LOW, 2=FULL 3=HIGH) */
+ __u32 speed;
+ /* power consumption of the device in mA */
+ __u32 power;
+ /* the number of the endpoint */
+ __u32 if_num;
+ /* size of the data-packets on this interface */
+ __u32 report_size;
};
/*
diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h
index 436dd8a2b64..67d2826f34f 100644
--- a/include/linux/usb/isp116x.h
+++ b/include/linux/usb/isp116x.h
@@ -25,5 +25,5 @@ struct isp116x_platform_data {
300ns delay between access to ADDR_REG and DATA_REG
OE, WE MUST NOT be changed during these intervals
*/
- void (*delay) (struct device * dev, int delay);
+ void (*delay) (struct device *dev, int delay);
};
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
index 11a97d5ffd3..80624c56292 100644
--- a/include/linux/usb/midi.h
+++ b/include/linux/usb/midi.h
@@ -47,9 +47,9 @@ struct usb_ms_header_descriptor {
/* 6.1.2.2 MIDI IN Jack Descriptor */
struct usb_midi_in_jack_descriptor {
__u8 bLength;
- __u8 bDescriptorType; // USB_DT_CS_INTERFACE
- __u8 bDescriptorSubtype; // USB_MS_MIDI_IN_JACK
- __u8 bJackType; // USB_MS_EMBEDDED/EXTERNAL
+ __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
+ __u8 bDescriptorSubtype; /* USB_MS_MIDI_IN_JACK */
+ __u8 bJackType; /* USB_MS_EMBEDDED/EXTERNAL */
__u8 bJackID;
__u8 iJack;
} __attribute__ ((packed));
@@ -64,12 +64,12 @@ struct usb_midi_source_pin {
/* 6.1.2.3 MIDI OUT Jack Descriptor */
struct usb_midi_out_jack_descriptor {
__u8 bLength;
- __u8 bDescriptorType; // USB_DT_CS_INTERFACE
- __u8 bDescriptorSubtype; // USB_MS_MIDI_OUT_JACK
- __u8 bJackType; // USB_MS_EMBEDDED/EXTERNAL
+ __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
+ __u8 bDescriptorSubtype; /* USB_MS_MIDI_OUT_JACK */
+ __u8 bJackType; /* USB_MS_EMBEDDED/EXTERNAL */
__u8 bJackID;
- __u8 bNrInputPins; // p
- struct usb_midi_source_pin pins[]; // [p]
+ __u8 bNrInputPins; /* p */
+ struct usb_midi_source_pin pins[]; /* [p] */
/*__u8 iJack; -- ommitted due to variable-sized pins[] */
} __attribute__ ((packed));
@@ -90,11 +90,11 @@ struct usb_midi_out_jack_descriptor_##p { \
/* 6.2.2 Class-Specific MS Bulk Data Endpoint Descriptor */
struct usb_ms_endpoint_descriptor {
- __u8 bLength; // 4+n
- __u8 bDescriptorType; // USB_DT_CS_ENDPOINT
- __u8 bDescriptorSubtype; // USB_MS_GENERAL
- __u8 bNumEmbMIDIJack; // n
- __u8 baAssocJackID[]; // [n]
+ __u8 bLength; /* 4+n */
+ __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */
+ __u8 bDescriptorSubtype; /* USB_MS_GENERAL */
+ __u8 bNumEmbMIDIJack; /* n */
+ __u8 baAssocJackID[]; /* [n] */
} __attribute__ ((packed));
#define USB_DT_MS_ENDPOINT_SIZE(n) (4 + (n))
diff --git a/include/linux/usb/net2280.h b/include/linux/usb/net2280.h
index c602f884f18..ec897cb844a 100644
--- a/include/linux/usb/net2280.h
+++ b/include/linux/usb/net2280.h
@@ -37,7 +37,7 @@
/* main registers, BAR0 + 0x0000 */
struct net2280_regs {
- // offset 0x0000
+ /* offset 0x0000 */
u32 devinit;
#define LOCAL_CLOCK_FREQUENCY 8
#define FORCE_PCI_RESET 7
@@ -61,7 +61,7 @@ struct net2280_regs {
#define EEPROM_WRITE_DATA 0
u32 eeclkfreq;
u32 _unused0;
- // offset 0x0010
+ /* offset 0x0010 */
u32 pciirqenb0; /* interrupt PCI master ... */
#define SETUP_PACKET_INTERRUPT_ENABLE 7
@@ -131,7 +131,7 @@ struct net2280_regs {
#define RESUME_INTERRUPT_ENABLE 1
#define SOF_INTERRUPT_ENABLE 0
- // offset 0x0020
+ /* offset 0x0020 */
u32 _unused1;
u32 usbirqenb1;
#define USB_INTERRUPT_ENABLE 31
@@ -195,7 +195,7 @@ struct net2280_regs {
#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
#define RESUME_INTERRUPT 1
#define SOF_INTERRUPT 0
- // offset 0x0030
+ /* offset 0x0030 */
u32 idxaddr;
u32 idxdata;
u32 fifoctl;
@@ -204,7 +204,7 @@ struct net2280_regs {
#define PCI_BASE2_SELECT 2
#define FIFO_CONFIGURATION_SELECT 0
u32 _unused2;
- // offset 0x0040
+ /* offset 0x0040 */
u32 memaddr;
#define START 28
#define DIRECTION 27
@@ -213,7 +213,7 @@ struct net2280_regs {
u32 memdata0;
u32 memdata1;
u32 _unused3;
- // offset 0x0050
+ /* offset 0x0050 */
u32 gpioctl;
#define GPIO3_LED_SELECT 12
#define GPIO3_INTERRUPT_ENABLE 11
@@ -237,7 +237,7 @@ struct net2280_regs {
/* usb control, BAR0 + 0x0080 */
struct net2280_usb_regs {
- // offset 0x0080
+ /* offset 0x0080 */
u32 stdrsp;
#define STALL_UNSUPPORTED_REQUESTS 31
#define SET_TEST_MODE 16
@@ -275,7 +275,7 @@ struct net2280_usb_regs {
#define PME_WAKEUP_ENABLE 2
#define DEVICE_REMOTE_WAKEUP_ENABLE 1
#define SELF_POWERED_STATUS 0
- // offset 0x0090
+ /* offset 0x0090 */
u32 usbstat;
#define HIGH_SPEED 7
#define FULL_SPEED 6
@@ -291,7 +291,7 @@ struct net2280_usb_regs {
#define TERMINATION_SELECT 0
u32 setup0123;
u32 setup4567;
- // offset 0x0090
+ /* offset 0x0090 */
u32 _unused0;
u32 ouraddr;
#define FORCE_IMMEDIATE 7
@@ -301,7 +301,7 @@ struct net2280_usb_regs {
/* pci control, BAR0 + 0x0100 */
struct net2280_pci_regs {
- // offset 0x0100
+ /* offset 0x0100 */
u32 pcimstctl;
#define PCI_ARBITER_PARK_SELECT 13
#define PCI_MULTI LEVEL_ARBITER 12
@@ -331,7 +331,7 @@ struct net2280_pci_regs {
* that can be loaded into some of these registers.
*/
struct net2280_dma_regs { /* [11.7] */
- // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
+ /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
u32 dmactl;
#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
#define DMA_CLEAR_COUNT_ENABLE 21
@@ -355,7 +355,7 @@ struct net2280_dma_regs { /* [11.7] */
#define DMA_ABORT 1
#define DMA_START 0
u32 _unused0 [2];
- // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
+ /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
u32 dmacount;
#define VALID_BIT 31
#define DMA_DIRECTION 30
@@ -371,9 +371,9 @@ struct net2280_dma_regs { /* [11.7] */
/* dedicated endpoint registers, BAR0 + 0x0200 */
struct net2280_dep_regs { /* [11.8] */
- // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
+ /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
u32 dep_cfg;
- // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
+ /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
u32 dep_rsp;
u32 _unused [2];
} __attribute__ ((packed));
@@ -383,7 +383,7 @@ struct net2280_dep_regs { /* [11.8] */
* ep0 reserved for control; E and F have only 64 bytes of fifo
*/
struct net2280_ep_regs { /* [11.9] */
- // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
+ /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
u32 ep_cfg;
#define ENDPOINT_BYTE_COUNT 16
#define ENDPOINT_ENABLE 10
@@ -435,7 +435,7 @@ struct net2280_ep_regs { /* [11.9] */
#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
#define DATA_OUT_PING_TOKEN_INTERRUPT 1
#define DATA_IN_TOKEN_INTERRUPT 0
- // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
+ /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
u32 ep_avail;
u32 ep_data;
u32 _unused0 [2];
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 9897f7a818c..e007074ebe4 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -1,4 +1,4 @@
-// include/linux/usb/otg.h
+/* USB OTG (On The Go) defines */
/*
* These APIs may be used between USB controllers. USB device drivers
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 488ce128885..21b4a1c6f58 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -20,7 +20,8 @@
#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
-#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
+/* The maximum number of ports one device can grab at once */
+#define MAX_NUM_PORTS 8
/* parity check flag */
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
@@ -61,29 +62,29 @@
* ports of a device.
*/
struct usb_serial_port {
- struct usb_serial * serial;
- struct tty_struct * tty;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
spinlock_t lock;
struct mutex mutex;
unsigned char number;
- unsigned char * interrupt_in_buffer;
- struct urb * interrupt_in_urb;
+ unsigned char *interrupt_in_buffer;
+ struct urb *interrupt_in_urb;
__u8 interrupt_in_endpointAddress;
- unsigned char * interrupt_out_buffer;
+ unsigned char *interrupt_out_buffer;
int interrupt_out_size;
- struct urb * interrupt_out_urb;
+ struct urb *interrupt_out_urb;
__u8 interrupt_out_endpointAddress;
- unsigned char * bulk_in_buffer;
+ unsigned char *bulk_in_buffer;
int bulk_in_size;
- struct urb * read_urb;
+ struct urb *read_urb;
__u8 bulk_in_endpointAddress;
- unsigned char * bulk_out_buffer;
+ unsigned char *bulk_out_buffer;
int bulk_out_size;
- struct urb * write_urb;
+ struct urb *write_urb;
int write_urb_busy;
__u8 bulk_out_endpointAddress;
@@ -92,17 +93,19 @@ struct usb_serial_port {
int open_count;
char throttled;
char throttle_req;
+ char console;
struct device dev;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
/* get and set the port private data pointer helper functions */
-static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+static inline void *usb_get_serial_port_data(struct usb_serial_port *port)
{
return dev_get_drvdata(&port->dev);
}
-static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+static inline void usb_set_serial_port_data(struct usb_serial_port *port,
+ void *data)
{
dev_set_drvdata(&port->dev, data);
}
@@ -125,9 +128,10 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
* usb_set_serial_data() to access this.
*/
struct usb_serial {
- struct usb_device * dev;
- struct usb_serial_driver * type;
- struct usb_interface * interface;
+ struct usb_device *dev;
+ struct usb_serial_driver *type;
+ struct usb_interface *interface;
+ unsigned char disconnected;
unsigned char minor;
unsigned char num_ports;
unsigned char num_port_pointers;
@@ -135,29 +139,30 @@ struct usb_serial {
char num_interrupt_out;
char num_bulk_in;
char num_bulk_out;
- struct usb_serial_port * port[MAX_NUM_PORTS];
+ struct usb_serial_port *port[MAX_NUM_PORTS];
struct kref kref;
- void * private;
+ struct mutex disc_mutex;
+ void *private;
};
#define to_usb_serial(d) container_of(d, struct usb_serial, kref)
#define NUM_DONT_CARE 99
/* get and set the serial private data pointer helper functions */
-static inline void *usb_get_serial_data (struct usb_serial *serial)
+static inline void *usb_get_serial_data(struct usb_serial *serial)
{
return serial->private;
}
-static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
{
serial->private = data;
}
/**
* usb_serial_driver - describes a usb serial driver
- * @description: pointer to a string that describes this driver. This string used
- * in the syslog messages when a device is inserted or removed.
+ * @description: pointer to a string that describes this driver. This string
+ * used in the syslog messages when a device is inserted or removed.
* @id_table: pointer to a list of usb_device_id structures that define all
* of the devices this structure can support.
* @num_interrupt_in: If a device doesn't have this many interrupt-in
@@ -218,82 +223,91 @@ struct usb_serial_driver {
struct usb_driver *usb_driver;
struct usb_dynids dynids;
- int (*probe) (struct usb_serial *serial, const struct usb_device_id *id);
- int (*attach) (struct usb_serial *serial);
+ int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);
+ int (*attach)(struct usb_serial *serial);
int (*calc_num_ports) (struct usb_serial *serial);
- void (*shutdown) (struct usb_serial *serial);
+ void (*shutdown)(struct usb_serial *serial);
- int (*port_probe) (struct usb_serial_port *port);
- int (*port_remove) (struct usb_serial_port *port);
+ int (*port_probe)(struct usb_serial_port *port);
+ int (*port_remove)(struct usb_serial_port *port);
- int (*suspend) (struct usb_serial *serial, pm_message_t message);
- int (*resume) (struct usb_serial *serial);
+ int (*suspend)(struct usb_serial *serial, pm_message_t message);
+ int (*resume)(struct usb_serial *serial);
/* serial function calls */
- int (*open) (struct usb_serial_port *port, struct file * filp);
- void (*close) (struct usb_serial_port *port, struct file * filp);
- int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count);
- int (*write_room) (struct usb_serial_port *port);
- int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
- void (*set_termios) (struct usb_serial_port *port, struct ktermios * old);
- void (*break_ctl) (struct usb_serial_port *port, int break_state);
- int (*chars_in_buffer) (struct usb_serial_port *port);
- void (*throttle) (struct usb_serial_port *port);
- void (*unthrottle) (struct usb_serial_port *port);
- int (*tiocmget) (struct usb_serial_port *port, struct file *file);
- int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+ int (*open)(struct usb_serial_port *port, struct file *filp);
+ void (*close)(struct usb_serial_port *port, struct file *filp);
+ int (*write)(struct usb_serial_port *port, const unsigned char *buf,
+ int count);
+ int (*write_room)(struct usb_serial_port *port);
+ int (*ioctl)(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg);
+ void (*set_termios)(struct usb_serial_port *port, struct ktermios *old);
+ void (*break_ctl)(struct usb_serial_port *port, int break_state);
+ int (*chars_in_buffer)(struct usb_serial_port *port);
+ void (*throttle)(struct usb_serial_port *port);
+ void (*unthrottle)(struct usb_serial_port *port);
+ int (*tiocmget)(struct usb_serial_port *port, struct file *file);
+ int (*tiocmset)(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
void (*read_int_callback)(struct urb *urb);
void (*write_int_callback)(struct urb *urb);
void (*read_bulk_callback)(struct urb *urb);
void (*write_bulk_callback)(struct urb *urb);
};
-#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver)
+#define to_usb_serial_driver(d) \
+ container_of(d, struct usb_serial_driver, driver)
extern int usb_serial_register(struct usb_serial_driver *driver);
extern void usb_serial_deregister(struct usb_serial_driver *driver);
extern void usb_serial_port_softint(struct usb_serial_port *port);
-extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
+extern int usb_serial_probe(struct usb_interface *iface,
+ const struct usb_device_id *id);
extern void usb_serial_disconnect(struct usb_interface *iface);
extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
extern int usb_serial_resume(struct usb_interface *intf);
-extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
-extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
+extern int ezusb_writememory(struct usb_serial *serial, int address,
+ unsigned char *data, int length, __u8 bRequest);
+extern int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit);
/* USB Serial console functions */
#ifdef CONFIG_USB_SERIAL_CONSOLE
-extern void usb_serial_console_init (int debug, int minor);
-extern void usb_serial_console_exit (void);
+extern void usb_serial_console_init(int debug, int minor);
+extern void usb_serial_console_exit(void);
extern void usb_serial_console_disconnect(struct usb_serial *serial);
#else
-static inline void usb_serial_console_init (int debug, int minor) { }
-static inline void usb_serial_console_exit (void) { }
+static inline void usb_serial_console_init(int debug, int minor) { }
+static inline void usb_serial_console_exit(void) { }
static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
#endif
/* Functions needed by other parts of the usbserial core */
-extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
+extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
extern void usb_serial_put(struct usb_serial *serial);
-extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
-extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
-extern int usb_serial_generic_resume (struct usb_serial *serial);
-extern int usb_serial_generic_write_room (struct usb_serial_port *port);
-extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
-extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
-extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
-extern void usb_serial_generic_throttle (struct usb_serial_port *port);
-extern void usb_serial_generic_unthrottle (struct usb_serial_port *port);
-extern void usb_serial_generic_shutdown (struct usb_serial *serial);
-extern int usb_serial_generic_register (int debug);
-extern void usb_serial_generic_deregister (void);
-
-extern int usb_serial_bus_register (struct usb_serial_driver *device);
-extern void usb_serial_bus_deregister (struct usb_serial_driver *device);
+extern int usb_serial_generic_open(struct usb_serial_port *port,
+ struct file *filp);
+extern int usb_serial_generic_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+extern void usb_serial_generic_close(struct usb_serial_port *port,
+ struct file *filp);
+extern int usb_serial_generic_resume(struct usb_serial *serial);
+extern int usb_serial_generic_write_room(struct usb_serial_port *port);
+extern int usb_serial_generic_chars_in_buffer(struct usb_serial_port *port);
+extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
+extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
+extern void usb_serial_generic_throttle(struct usb_serial_port *port);
+extern void usb_serial_generic_unthrottle(struct usb_serial_port *port);
+extern void usb_serial_generic_shutdown(struct usb_serial *serial);
+extern int usb_serial_generic_register(int debug);
+extern void usb_serial_generic_deregister(void);
+
+extern int usb_serial_bus_register(struct usb_serial_driver *device);
+extern void usb_serial_bus_deregister(struct usb_serial_driver *device);
extern struct usb_serial_driver usb_serial_generic_device;
extern struct bus_type usb_serial_bus_type;
@@ -307,16 +321,22 @@ static inline void usb_serial_debug_data(int debug,
int i;
if (debug) {
- dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size);
+ dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ",
+ function, size);
for (i = 0; i < size; ++i)
- printk ("%.2x ", data[i]);
- printk ("\n");
+ printk("%.2x ", data[i]);
+ printk("\n");
}
}
/* Use our own dbg macro */
#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
+#define dbg(format, arg...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , \
+ ## arg); \
+ } while (0)
diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
index 397ee3b3d7f..877373da410 100644
--- a/include/linux/usb/sl811.h
+++ b/include/linux/usb/sl811.h
@@ -19,8 +19,8 @@ struct sl811_platform_data {
/* pulse sl811 nRST (probably with a GPIO) */
void (*reset)(struct device *dev);
- // some boards need something like these:
- // int (*check_overcurrent)(struct device *dev);
- // void (*clock_enable)(struct device *dev, int is_on);
+ /* some boards need something like these: */
+ /* int (*check_overcurrent)(struct device *dev); */
+ /* void (*clock_enable)(struct device *dev, int is_on); */
};
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index a417b09b8b3..cee0623b3c7 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -80,10 +80,9 @@ enum { US_DO_ALL_FLAGS };
#define US_SC_UFI 0x04 /* Floppy */
#define US_SC_8070 0x05 /* Removable media */
#define US_SC_SCSI 0x06 /* Transparent */
-#define US_SC_ISD200 0x07 /* ISD200 ATA */
-#define US_SC_MIN US_SC_RBC
-#define US_SC_MAX US_SC_ISD200
+#define US_SC_LOCKABLE 0x07 /* Password-protected */
+#define US_SC_ISD200 0xf0 /* ISD200 ATA */
#define US_SC_DEVICE 0xff /* Use device's value */
/* Protocols */
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 8ca5a7fbc9e..17cb108b7db 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -104,7 +104,7 @@ struct usbdevfs_urb {
int error_count;
unsigned int signr; /* signal to be sent on completion,
or 0 if none should be sent. */
- void *usercontext;
+ void __user *usercontext;
struct usbdevfs_iso_packet_desc iso_frame_desc[0];
};
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index c1d76552446..7c2da88db4e 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -101,6 +101,10 @@ void softlockup_tick(void)
now = get_timestamp(this_cpu);
+ /* Wake up the high-prio watchdog task every second: */
+ if (now > (touch_timestamp + 1))
+ wake_up_process(per_cpu(watchdog_task, this_cpu));
+
/* Warn about unreasonable delays: */
if (now <= (touch_timestamp + softlockup_thresh))
return;
@@ -191,11 +195,11 @@ static void check_hung_uninterruptible_tasks(int this_cpu)
read_lock(&tasklist_lock);
do_each_thread(g, t) {
if (!--max_count)
- break;
+ goto unlock;
if (t->state & TASK_UNINTERRUPTIBLE)
check_hung_task(t, now);
} while_each_thread(g, t);
-
+ unlock:
read_unlock(&tasklist_lock);
}
@@ -218,14 +222,19 @@ static int watchdog(void *__bind_cpu)
* debug-printout triggers in softlockup_tick().
*/
while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
touch_softlockup_watchdog();
- msleep_interruptible(10000);
+ schedule();
+
+ if (kthread_should_stop())
+ break;
if (this_cpu != check_cpu)
continue;
if (sysctl_hung_task_timeout_secs)
check_hung_uninterruptible_tasks(this_cpu);
+
}
return 0;
@@ -259,13 +268,6 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
wake_up_process(per_cpu(watchdog_task, hotcpu));
break;
#ifdef CONFIG_HOTPLUG_CPU
- case CPU_UP_CANCELED:
- case CPU_UP_CANCELED_FROZEN:
- if (!per_cpu(watchdog_task, hotcpu))
- break;
- /* Unbind so it can run. Fall thru. */
- kthread_bind(per_cpu(watchdog_task, hotcpu),
- any_online_cpu(cpu_online_map));
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
if (hotcpu == check_cpu) {
@@ -275,6 +277,14 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
check_cpu = any_online_cpu(temp_cpu_online_map);
}
break;
+
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
+ if (!per_cpu(watchdog_task, hotcpu))
+ break;
+ /* Unbind so it can run. Fall thru. */
+ kthread_bind(per_cpu(watchdog_task, hotcpu),
+ any_online_cpu(cpu_online_map));
case CPU_DEAD:
case CPU_DEAD_FROZEN:
p = per_cpu(watchdog_task, hotcpu);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index d802b5afae8..9ddf944cce2 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -155,7 +155,7 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
* Some modules (visor) have empty slots as placeholder for
* run-time specification that results in catch-all alias
*/
- if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
+ if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
return;
/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */