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

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (128 commits)
  USB: fix codingstyle issues in drivers/usb/core/*.c
  USB: fix codingstyle issues in drivers/usb/core/message.c
  USB: fix codingstyle issues in drivers/usb/core/hcd-pci.c
  USB: fix codingstyle issues in drivers/usb/core/devio.c
  USB: fix codingstyle issues in drivers/usb/core/devices.c
  USB: fix codingstyle issues in drivers/usb/core/*.h
  USB: fix codingstyle issues in include/linux/usb/
  USB: fix codingstyle issues in include/linux/usb.h
  USB: mark USB drivers as being GPL only
  USB: use a real vendor and product id for root hubs
  USB: mount options: fix usbfs
  USB: Fix usb_serial_driver structure for Kobil cardreader driver.
  usb: ehci should use u16 for isochronous intervals
  usb: ehci, remove false clear-reset path
  USB: Use menuconfig objects
  usb: ohci-sm501 driver
  usb: dma bounce buffer support
  USB: last abuses of intfdata in close for usb-serial drivers
  USB: kl5kusb105 don't flush to logically disconnected devices
  USB: oti6858: cleanup
  ...
This commit is contained in:
Linus Torvalds 2008-02-02 14:28:57 +11:00
commit b6cf160c4b
150 changed files with 8196 additions and 2680 deletions

View file

@ -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/

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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,
};
/*

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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));

View file

@ -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,
};
/*

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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 */

View file

@ -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;

View file

@ -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;
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;
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;

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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);
if (urb->transfer_buffer_length != 0
&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
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);
}
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);
/*-------------------------------------------------------------------------*/

View file

@ -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.

View file

@ -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);

View file

@ -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 */

View file

@ -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)

View file

@ -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 ()
* 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)
*
* 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.
* Context: !in_interrupt ()
*
* 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.
* 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 ()
* 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)
*
* 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.
* Context: !in_interrupt ()
*
* 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.
* This function sends a simple bulk message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* 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.
* 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);

View file

@ -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)

View file

@ -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) &&

View file

@ -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 */
@ -248,6 +248,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)
{
@ -365,12 +400,26 @@ 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;
}
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);
@ -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) \

View file

@ -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);

View file

@ -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");

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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"

View file

@ -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)
/*-------------------------------------------------------------------------*/

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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,

View file

@ -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;

View file

@ -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)
/*-------------------------------------------------------------------------*/

1592
drivers/usb/gadget/printer.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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 */

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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

View file

@ -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,
};
/*-------------------------------------------------------------------------*/

View file

@ -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 struct debug_buffer *alloc_buffer(struct usb_bus *bus,
ssize_t (*fill_func)(struct debug_buffer *))
{
struct debug_buffer *buf;
buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
if (buf) {
buf->bus = bus;
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 ehci_hcd *ehci)
{
struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
int retval;
struct usb_bus *bus = &ehci_to_hcd(ehci)->self;
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);
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)
{
struct class_device *cldev = ehci_to_hcd(ehci)->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(ehci->debug_registers);
debugfs_remove(ehci->debug_periodic);
debugfs_remove(ehci->debug_async);
debugfs_remove(ehci->debug_dir);
}
#endif /* STUB_DEBUG_FILES */

View file

@ -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)

View file

@ -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);
#endif
#ifdef PCI_DRIVER
pci_unregister_driver(&PCI_DRIVER);
#endif
return retval;
}
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);
clean1:
#endif
#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);

View file

@ -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);
}

View file

@ -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
},
};

View file

@ -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",
};

View file

@ -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,
};
/*-------------------------------------------------------------------------*/

View file

@ -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,
},
};

View file

@ -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)

View file

@ -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)

View file

@ -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);
}
/*-------------------------------------------------------------------------*/

View file

@ -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;

View file

@ -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;
@ -126,6 +126,14 @@ struct ehci_hcd { /* one per controller */
# define COUNT(x) do { (x)++; } while (0)
#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
};
@ -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)
{

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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);

143
drivers/usb/host/ohci-sh.c Normal file
View file

@ -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,
},
};

View file

@ -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",
},
};

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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,

View file

@ -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));

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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]);

View file

@ -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;
}

View file

@ -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 (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);
if ((cflag & CBAUD) != B0 ) {
/* 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 {

View file

@ -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)

View file

@ -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);
}
/*

View file

@ -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;

View file

@ -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 */

View file

@ -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");
}

Some files were not shown because too many files have changed in this diff Show more