diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-22 15:36:23 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-22 15:36:23 -0800 |
commit | b171e4fc69b3d2ef67d2f02597c818315ecc4b88 (patch) | |
tree | df9ea6631c8dd70d8af25c8421dcbae3d6f7df67 /usb | |
parent | e82bcd05071353092ac327e3e9b4014cd393b26f (diff) | |
download | patches-b171e4fc69b3d2ef67d2f02597c818315ecc4b88.tar.gz |
remove usb patches that went into mainline (2.6.16-git3)
Diffstat (limited to 'usb')
81 files changed, 0 insertions, 28912 deletions
diff --git a/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch b/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch deleted file mode 100644 index a7910af76c86f..0000000000000 --- a/usb/cypress_m8-add-support-for-the-nokia-ca42-version-2-cable.patch +++ /dev/null @@ -1,182 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Wed Mar 1 15:19:12 2006 -Message-ID: <4405CFA4.3010604@austin.rr.com> -From: Lonnie Mendez <lmendez19@austin.rr.com> -To: linux-usb-devel@lists.sourceforge.net -Subject: USB: cypress_m8: add support for the Nokia ca42-version 2 cable -Date: Wed, 01 Mar 2006 10:45:24 -0600 - -This patch adds support for the Nokia ca42 version 2 cable to the -cypress_m8 driver. The device was tested by others with this patch and -found to be compatible with the cypress_m8 driver. A special note -should be taken that this cable seems to vary in the type of chipset -used. This patch supports the cable with product id 0x4101. - -Signed-off-by: Lonnie Mendez <lmendez19@austin.rr.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/usb/serial/cypress_m8.c | 70 ++++++++++++++++++++++++++++++++++++++++ - drivers/usb/serial/cypress_m8.h | 5 ++ - 2 files changed, 75 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.c -+++ gregkh-2.6/drivers/usb/serial/cypress_m8.c -@@ -98,10 +98,16 @@ static struct usb_device_id id_table_cyp - { } /* Terminating entry */ - }; - -+static struct usb_device_id id_table_nokiaca42v2 [] = { -+ { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, -+ { } /* Terminating entry */ -+}; -+ - static struct usb_device_id id_table_combined [] = { - { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) }, - { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, - { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, -+ { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, - { } /* Terminating entry */ - }; - -@@ -149,6 +155,7 @@ struct cypress_buf { - /* function prototypes for the Cypress USB to serial device */ - static int cypress_earthmate_startup (struct usb_serial *serial); - static int cypress_hidcom_startup (struct usb_serial *serial); -+static int cypress_ca42v2_startup (struct usb_serial *serial); - static void cypress_shutdown (struct usb_serial *serial); - static int cypress_open (struct usb_serial_port *port, struct file *filp); - static void cypress_close (struct usb_serial_port *port, struct file *filp); -@@ -235,6 +242,34 @@ static struct usb_serial_driver cypress_ - .write_int_callback = cypress_write_int_callback, - }; - -+static struct usb_serial_driver cypress_ca42v2_device = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "nokiaca42v2", -+ }, -+ .description = "Nokia CA-42 V2 Adapter", -+ .id_table = id_table_nokiaca42v2, -+ .num_interrupt_in = 1, -+ .num_interrupt_out = 1, -+ .num_bulk_in = NUM_DONT_CARE, -+ .num_bulk_out = NUM_DONT_CARE, -+ .num_ports = 1, -+ .attach = cypress_ca42v2_startup, -+ .shutdown = cypress_shutdown, -+ .open = cypress_open, -+ .close = cypress_close, -+ .write = cypress_write, -+ .write_room = cypress_write_room, -+ .ioctl = cypress_ioctl, -+ .set_termios = cypress_set_termios, -+ .tiocmget = cypress_tiocmget, -+ .tiocmset = cypress_tiocmset, -+ .chars_in_buffer = cypress_chars_in_buffer, -+ .throttle = cypress_throttle, -+ .unthrottle = cypress_unthrottle, -+ .read_int_callback = cypress_read_int_callback, -+ .write_int_callback = cypress_write_int_callback, -+}; - - /***************************************************************************** - * Cypress serial helper functions -@@ -286,6 +321,12 @@ static int cypress_serial_control (struc - __FUNCTION__); - new_baudrate = priv->baud_rate; - } -+ } else if (priv->chiptype == CT_CA42V2) { -+ if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { -+ err("%s - failed setting baud rate, unsupported speed", -+ __FUNCTION__); -+ new_baudrate = priv->baud_rate; -+ } - } else if (priv->chiptype == CT_GENERIC) { - if ( (new_baudrate = mask_to_rate(baud_mask)) == -1) { - err("%s - failed setting baud rate, unsupported speed", -@@ -499,6 +540,25 @@ static int cypress_hidcom_startup (struc - } /* cypress_hidcom_startup */ - - -+static int cypress_ca42v2_startup (struct usb_serial *serial) -+{ -+ struct cypress_private *priv; -+ -+ dbg("%s", __FUNCTION__); -+ -+ if (generic_startup(serial)) { -+ dbg("%s - Failed setting up port %d", __FUNCTION__, -+ serial->port[0]->number); -+ return 1; -+ } -+ -+ priv = usb_get_serial_port_data(serial->port[0]); -+ priv->chiptype = CT_CA42V2; -+ -+ return 0; -+} /* cypress_ca42v2_startup */ -+ -+ - static void cypress_shutdown (struct usb_serial *serial) - { - struct cypress_private *priv; -@@ -943,6 +1003,10 @@ static void cypress_set_termios (struct - *(tty->termios) = tty_std_termios; - tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | - CLOCAL; -+ } else if (priv->chiptype == CT_CA42V2) { -+ *(tty->termios) = tty_std_termios; -+ tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | -+ CLOCAL; - } - priv->termios_initialized = 1; - } -@@ -1541,6 +1605,9 @@ static int __init cypress_init(void) - retval = usb_serial_register(&cypress_hidcom_device); - if (retval) - goto failed_hidcom_register; -+ retval = usb_serial_register(&cypress_ca42v2_device); -+ if (retval) -+ goto failed_ca42v2_register; - retval = usb_register(&cypress_driver); - if (retval) - goto failed_usb_register; -@@ -1549,6 +1616,8 @@ static int __init cypress_init(void) - return 0; - failed_usb_register: - usb_deregister(&cypress_driver); -+failed_ca42v2_register: -+ usb_serial_deregister(&cypress_ca42v2_device); - failed_hidcom_register: - usb_serial_deregister(&cypress_hidcom_device); - failed_em_register: -@@ -1565,6 +1634,7 @@ static void __exit cypress_exit (void) - usb_deregister (&cypress_driver); - usb_serial_deregister (&cypress_earthmate_device); - usb_serial_deregister (&cypress_hidcom_device); -+ usb_serial_deregister (&cypress_ca42v2_device); - } - - ---- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.h -+++ gregkh-2.6/drivers/usb/serial/cypress_m8.h -@@ -18,6 +18,10 @@ - /* Cypress HID->COM RS232 Adapter */ - #define VENDOR_ID_CYPRESS 0x04b4 - #define PRODUCT_ID_CYPHIDCOM 0x5500 -+ -+/* Nokia CA-42 USB to serial cable */ -+#define VENDOR_ID_DAZZLE 0x07d0 -+#define PRODUCT_ID_CA42 0x4101 - /* End of device listing */ - - /* Used for setting / requesting serial line settings */ -@@ -34,6 +38,7 @@ - - #define CT_EARTHMATE 0x01 - #define CT_CYPHIDCOM 0x02 -+#define CT_CA42V2 0x03 - #define CT_GENERIC 0x0F - /* End of chiptype definitions */ - diff --git a/usb/navman-usb-serial.patch b/usb/navman-usb-serial.patch deleted file mode 100644 index 95cdafd762909..0000000000000 --- a/usb/navman-usb-serial.patch +++ /dev/null @@ -1,202 +0,0 @@ -From foo@baz Tue Apr 9 12:12:43 2002 -Date: Fri, 17 Mar 2006 17:40:08 -0800 (PST) -From: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB serial: add navman driver - -Thanks to Warren Lewis <wlewis@scn.org> for the information needed to -write the driver and for testing it out. - -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/serial/Kconfig | 7 + - drivers/usb/serial/Makefile | 1 - drivers/usb/serial/navman.c | 157 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 165 insertions(+) - ---- usb-2.6.orig/drivers/usb/serial/Kconfig -+++ usb-2.6/drivers/usb/serial/Kconfig -@@ -403,6 +403,13 @@ config USB_SERIAL_MCT_U232 - To compile this driver as a module, choose M here: the - module will be called mct_u232. - -+config USB_SERIAL_NAVMAN -+ tristate "USB Navman GPS device" -+ depends on USB_SERIAL -+ help -+ To compile this driver as a module, choose M here: the -+ module will be called navman. -+ - config USB_SERIAL_PL2303 - tristate "USB Prolific 2303 Single Port Serial Driver" - depends on USB_SERIAL ---- usb-2.6.orig/drivers/usb/serial/Makefile -+++ usb-2.6/drivers/usb/serial/Makefile -@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += - obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o - obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o - obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o -+obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o - obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o - obj-$(CONFIG_USB_SERIAL_OPTION) += option.o - obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o ---- /dev/null -+++ usb-2.6/drivers/usb/serial/navman.c -@@ -0,0 +1,157 @@ -+/* -+ * Navman Serial USB driver -+ * -+ * Copyright (C) 2006 Greg Kroah-Hartman <gregkh@suse.de> -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/tty.h> -+#include <linux/tty_flip.h> -+#include <linux/module.h> -+#include <linux/usb.h> -+#include "usb-serial.h" -+ -+static int debug; -+ -+static struct usb_device_id id_table [] = { -+ { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ -+ { }, -+}; -+MODULE_DEVICE_TABLE(usb, id_table); -+ -+static struct usb_driver navman_driver = { -+ .name = "navman", -+ .probe = usb_serial_probe, -+ .disconnect = usb_serial_disconnect, -+ .id_table = id_table, -+ .no_dynamic_id = 1, -+}; -+ -+static void navman_read_int_callback(struct urb *urb, struct pt_regs *regs) -+{ -+ struct usb_serial_port *port = urb->context; -+ unsigned char *data = urb->transfer_buffer; -+ struct tty_struct *tty; -+ int result; -+ -+ switch (urb->status) { -+ case 0: -+ /* success */ -+ break; -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ /* this urb is terminated, clean up */ -+ dbg("%s - urb shutting down with status: %d", -+ __FUNCTION__, urb->status); -+ return; -+ default: -+ dbg("%s - nonzero urb status received: %d", -+ __FUNCTION__, urb->status); -+ goto exit; -+ } -+ -+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, -+ urb->actual_length, data); -+ -+ tty = port->tty; -+ if (tty && urb->actual_length) { -+ tty_buffer_request_room(tty, urb->actual_length); -+ tty_insert_flip_string(tty, data, urb->actual_length); -+ tty_flip_buffer_push(tty); -+ } -+ -+exit: -+ result = usb_submit_urb(urb, GFP_ATOMIC); -+ if (result) -+ dev_err(&urb->dev->dev, -+ "%s - Error %d submitting interrupt urb\n", -+ __FUNCTION__, result); -+} -+ -+static int navman_open(struct usb_serial_port *port, struct file *filp) -+{ -+ int result = 0; -+ -+ dbg("%s - port %d", __FUNCTION__, port->number); -+ -+ if (port->interrupt_in_urb) { -+ dbg("%s - adding interrupt input for treo", __FUNCTION__); -+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); -+ if (result) -+ dev_err(&port->dev, -+ "%s - failed submitting interrupt urb, error %d\n", -+ __FUNCTION__, result); -+ } -+ return result; -+} -+ -+static void navman_close(struct usb_serial_port *port, struct file *filp) -+{ -+ dbg("%s - port %d", __FUNCTION__, port->number); -+ -+ if (port->interrupt_in_urb) -+ usb_kill_urb(port->interrupt_in_urb); -+} -+ -+static int navman_write(struct usb_serial_port *port, -+ const unsigned char *buf, int count) -+{ -+ dbg("%s - port %d", __FUNCTION__, port->number); -+ -+ /* -+ * This device can't write any data, only read from the device -+ * so we just silently eat all data sent to us and say it was -+ * successfully sent. -+ * Evil, I know, but do you have a better idea? -+ */ -+ -+ return count; -+} -+ -+static struct usb_serial_driver navman_device = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "navman", -+ }, -+ .id_table = id_table, -+ .num_interrupt_in = NUM_DONT_CARE, -+ .num_bulk_in = NUM_DONT_CARE, -+ .num_bulk_out = NUM_DONT_CARE, -+ .num_ports = 1, -+ .open = navman_open, -+ .close = navman_close, -+ .write = navman_write, -+ .read_int_callback = navman_read_int_callback, -+}; -+ -+static int __init navman_init(void) -+{ -+ int retval; -+ -+ retval = usb_serial_register(&navman_device); -+ if (retval) -+ return retval; -+ retval = usb_register(&navman_driver); -+ if (retval) -+ usb_serial_deregister(&navman_device); -+ return retval; -+} -+ -+static void __exit navman_exit(void) -+{ -+ usb_deregister(&navman_driver); -+ usb_serial_deregister(&navman_device); -+} -+ -+module_init(navman_init); -+module_exit(navman_exit); -+MODULE_LICENSE("GPL"); -+ -+module_param(debug, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/usb/omninet_debug.patch b/usb/omninet_debug.patch deleted file mode 100644 index 6264231528f44..0000000000000 --- a/usb/omninet_debug.patch +++ /dev/null @@ -1,55 +0,0 @@ -From foo@baz Tue Apr 9 12:12:43 2002 -Date: Mon, 20 Mar 2006 17:28:39 -0500 -From: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: omninet: fix up debugging comments - -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- ---- gregkh-2.6.orig/drivers/usb/serial/omninet.c -+++ gregkh-2.6/drivers/usb/serial/omninet.c -@@ -204,7 +204,7 @@ static void omninet_read_bulk_callback ( - int i; - int result; - --// dbg("omninet_read_bulk_callback"); -+ dbg("%s - port %d", __FUNCTION__, port->number); - - if (urb->status) { - dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); -@@ -250,7 +250,7 @@ static int omninet_write (struct usb_ser - - int result; - --// dbg("omninet_write port %d", port->number); -+ dbg("%s - port %d", __FUNCTION__, port->number); - - if (count == 0) { - dbg("%s - write request of 0 bytes", __FUNCTION__); -@@ -302,7 +302,7 @@ static int omninet_write_room (struct us - if (wport->write_urb_busy) - room = wport->bulk_out_size - OMNINET_HEADERLEN; - --// dbg("omninet_write_room returns %d", room); -+ dbg("%s - returns %d", __FUNCTION__, room); - - return (room); - } -@@ -312,7 +312,7 @@ static void omninet_write_bulk_callback - /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ - struct usb_serial_port *port = (struct usb_serial_port *) urb->context; - --// dbg("omninet_write_bulk_callback, port %0x\n", port); -+ dbg("%s - port %0x\n", __FUNCTION__, port->number); - - port->write_urb_busy = 0; - if (urb->status) { -@@ -321,8 +321,6 @@ static void omninet_write_bulk_callback - } - - schedule_work(&port->work); -- --// dbg("omninet_write_bulk_callback, tty %0x\n", tty); - } - - diff --git a/usb/recognize-three-more-usb-peripheral-controllers.patch b/usb/recognize-three-more-usb-peripheral-controllers.patch deleted file mode 100644 index 9878029d095e6..0000000000000 --- a/usb/recognize-three-more-usb-peripheral-controllers.patch +++ /dev/null @@ -1,106 +0,0 @@ -From david-b@pacbell.net Wed Jan 25 08:57:17 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: [patch 2.6.16-rc1] recognize three more usb peripheral controllers -Date: Wed, 25 Jan 2006 08:45:59 -0800 -Cc: "Kamat, Nishant" <nskamat@ti.com>, Kevin Hilman <khilman@mvista.com>, Tony Lindgren <tony@atomide.com> -Message-Id: <200601250845.59331.david-b@pacbell.net> - -This adds declarations for three USB peripheral controllers: - - - Two high speed USB cores that can be licensed from Mentor Graphics - to be integrated into silicon: - - * "musbhsfc" is for peripherals only, as found in for example the - IBM/AMCC 44EP processors. - - * "musbhdrc" is OTG-capable (dual role), and is found in various - products including OMAP 2430 and the new DaVinci SOCs. - - The "musbh" standing for "Mentor USB Highspeed", the rest standing - for "Function Controller" or "Dual Role Controller" (OTG-capable). - - - The full speed controller on the FreeScale MPC8272. - -Adding these definitions just allows gadget driver code to handle any -controller-specific logic; controller drivers are quite separate. - - -Signed-off-by: David Brownell <david-b@pacbell.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/ether.c | 8 ++++++++ - drivers/usb/gadget/gadget_chips.h | 30 ++++++++++++++++++++++++++++-- - 2 files changed, 36 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/ether.c -+++ gregkh-2.6/drivers/usb/gadget/ether.c -@@ -253,6 +253,14 @@ MODULE_PARM_DESC(host_addr, "Host Ethern - #define DEV_CONFIG_CDC - #endif - -+#ifdef CONFIG_USB_GADGET_MUSBHSFC -+#define DEV_CONFIG_CDC -+#endif -+ -+#ifdef CONFIG_USB_GADGET_MUSBHDRC -+#define DEV_CONFIG_CDC -+#endif -+ - - /* For CDC-incapable hardware, choose the simple cdc subset. - * Anything that talks bulk (without notable bugs) can do this. ---- gregkh-2.6.orig/drivers/usb/gadget/gadget_chips.h -+++ gregkh-2.6/drivers/usb/gadget/gadget_chips.h -@@ -3,9 +3,9 @@ - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * -- * This could eventually work like the ARM mach_is_*() stuff, driven by -+ * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. -- * (And avoiding the runtime comparisons in typical one-choice cases.) -+ * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - */ -@@ -93,6 +93,26 @@ - #define gadget_is_imx(g) 0 - #endif - -+/* Mentor high speed function controller */ -+#ifdef CONFIG_USB_GADGET_MUSBHSFC -+#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) -+#else -+#define gadget_is_musbhsfc(g) 0 -+#endif -+ -+/* Mentor high speed "dual role" controller, peripheral mode */ -+#ifdef CONFIG_USB_GADGET_MUSBHDRC -+#define gadget_is_musbhdrc(g) !strcmp("musbhdrc_udc", (g)->name) -+#else -+#define gadget_is_musbhdrc(g) 0 -+#endif -+ -+#ifdef CONFIG_USB_GADGET_MPC8272 -+#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name) -+#else -+#define gadget_is_mpc8272(g) 0 -+#endif -+ - // CONFIG_USB_GADGET_SX2 - // CONFIG_USB_GADGET_AU1X00 - // ... -@@ -143,5 +163,11 @@ static inline int usb_gadget_controller_ - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; -+ else if (gadget_is_musbhsfc(gadget)) -+ return 0x15; -+ else if (gadget_is_musbhdrc(gadget)) -+ return 0x16; -+ else if (gadget_is_mpc8272(gadget)) -+ return 0x17; - return -ENOENT; - } diff --git a/usb/ub-use-kzalloc.patch b/usb/ub-use-kzalloc.patch deleted file mode 100644 index 52091cbb74b54..0000000000000 --- a/usb/ub-use-kzalloc.patch +++ /dev/null @@ -1,63 +0,0 @@ -From zaitcev@redhat.com Mon Feb 13 20:36:09 2006 -Date: Mon, 13 Feb 2006 20:35:57 -0800 -From: Pete Zaitcev <zaitcev@redhat.com> -To: Greg KH <greg@kroah.com> -Cc: zaitcev@redhat.com -Subject: ub: use kzalloc -Message-Id: <20060213203557.4892cf5a.zaitcev@redhat.com> - -Switch from kmalloc+memset to kzalloc. - -Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/block/ub.c | 12 ++++-------- - 1 file changed, 4 insertions(+), 8 deletions(-) - ---- gregkh-2.6.orig/drivers/block/ub.c -+++ gregkh-2.6/drivers/block/ub.c -@@ -2007,9 +2007,8 @@ static int ub_sync_tur(struct ub_dev *sc - init_completion(&compl); - - rc = -ENOMEM; -- if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) -+ if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) - goto err_alloc; -- memset(cmd, 0, ALLOC_SIZE); - - cmd->cdb[0] = TEST_UNIT_READY; - cmd->cdb_len = 6; -@@ -2062,9 +2061,8 @@ static int ub_sync_read_cap(struct ub_de - init_completion(&compl); - - rc = -ENOMEM; -- if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) -+ if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) - goto err_alloc; -- memset(cmd, 0, ALLOC_SIZE); - p = (char *)cmd + sizeof(struct ub_scsi_cmd); - - cmd->cdb[0] = 0x25; -@@ -2405,9 +2403,8 @@ static int ub_probe(struct usb_interface - return -ENXIO; - - rc = -ENOMEM; -- if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) -+ if ((sc = kzalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) - goto err_core; -- memset(sc, 0, sizeof(struct ub_dev)); - sc->lock = ub_next_lock(); - INIT_LIST_HEAD(&sc->luns); - usb_init_urb(&sc->work_urb); -@@ -2524,9 +2521,8 @@ static int ub_probe_lun(struct ub_dev *s - int rc; - - rc = -ENOMEM; -- if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) -+ if ((lun = kzalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) - goto err_alloc; -- memset(lun, 0, sizeof(struct ub_lun)); - lun->num = lnum; - - rc = -ENOSR; diff --git a/usb/uhci-don-t-log-short-transfers.patch b/usb/uhci-don-t-log-short-transfers.patch deleted file mode 100644 index 1b0ed73980c59..0000000000000 --- a/usb/uhci-don-t-log-short-transfers.patch +++ /dev/null @@ -1,37 +0,0 @@ -From stern@rowland.harvard.edu Tue Dec 20 07:01:47 2005 -Date: Tue, 20 Dec 2005 09:58:08 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -Subject: [PATCH] UHCI: Don't log short transfers -Message-ID: <Pine.LNX.4.44L0.0512200953140.5250-100000@iolanthe.rowland.org> - -Even when the URB_SHORT_NOT_OK flag is set, a short transfer shouldn't -generate a debugging log message. Especially not one with the confusing -claim that the transfer "failed with status 0". This patch (as627) -fixes that behavior in uhci-hcd. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-q.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -922,7 +922,6 @@ static int uhci_result_common(struct uhc - td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - --err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", -@@ -934,6 +933,7 @@ err: - lprintk(errbuf); - } - } -+err: - - /* Note that the queue has stopped and save the next toggle value */ - urbp->qh->element = UHCI_PTR_TERM; diff --git a/usb/uhci-hcd-fix-mistaken-usage-of-list_prepare_entry.patch b/usb/uhci-hcd-fix-mistaken-usage-of-list_prepare_entry.patch deleted file mode 100644 index e387d350f101e..0000000000000 --- a/usb/uhci-hcd-fix-mistaken-usage-of-list_prepare_entry.patch +++ /dev/null @@ -1,29 +0,0 @@ -From stern@rowland.harvard.edu Tue Jan 31 07:03:01 2006 -Date: Tue, 31 Jan 2006 10:02:55 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com>, Andrew Morton <akpm@osdl.org> -cc: Arnaud Patard <arnaud.patard@rtp-net.org> -Subject: [PATCH] uhci-hcd: fix mistaken usage of list_prepare_entry -Message-ID: <Pine.LNX.4.44L0.0601310958570.5380-100000@iolanthe.rowland.org> - -A recent update to the uhci-hcd driver invoked the list_prepare_entry -macro incorrectly. This patch (as646) corrects it. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-q.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -259,7 +259,7 @@ static void uhci_fixup_toggles(struct uh - /* Fix up the toggle for the URBs in the queue. Normally this - * loop won't run more than once: When an error or short transfer - * occurs, the queue usually gets emptied. */ -- list_prepare_entry(urbp, &qh->queue, node); -+ urbp = list_prepare_entry(urbp, &qh->queue, node); - list_for_each_entry_continue(urbp, &qh->queue, node) { - - /* If the first TD has the right toggle value, we don't diff --git a/usb/uhci-improve-debugging-code.patch b/usb/uhci-improve-debugging-code.patch deleted file mode 100644 index 77ede9e35bcb8..0000000000000 --- a/usb/uhci-improve-debugging-code.patch +++ /dev/null @@ -1,285 +0,0 @@ -From stern@rowland.harvard.edu Sat Dec 17 15:14:04 2005 -Date: Sat, 17 Dec 2005 18:03:37 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -Subject: [PATCH 4/4] UHCI: improve debugging code -Message-ID: <Pine.LNX.4.44L0.0512171732300.14730-100000@netrider.rowland.org> - -This patch (as626) makes some improvements to the debugging code in -uhci-hcd. The main change is that now the code won't get compiled if -CONFIG_USB_DEBUG isn't set. But there are other changes too, like -adding a missing .owner field and printing a debugging dump if the -controller dies. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-debug.c | 36 ++++++++++++++++++++----- - drivers/usb/host/uhci-hcd.c | 60 +++++++++++++++++++++++++++--------------- - drivers/usb/host/uhci-hcd.h | 1 - drivers/usb/host/uhci-q.c | 12 -------- - 4 files changed, 70 insertions(+), 39 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c -+++ gregkh-2.6/drivers/usb/host/uhci-debug.c -@@ -17,10 +17,13 @@ - - #include "uhci-hcd.h" - --static struct dentry *uhci_debugfs_root = NULL; -+#define uhci_debug_operations (* (struct file_operations *) NULL) -+static struct dentry *uhci_debugfs_root; -+ -+#ifdef DEBUG - - /* Handle REALLY large printks so we don't overflow buffers */ --static inline void lprintk(char *buf) -+static void lprintk(char *buf) - { - char *p; - -@@ -196,7 +199,6 @@ static int uhci_show_qh(struct uhci_qh * - return out - buf; - } - --#ifdef CONFIG_PROC_FS - static const char * const qh_names[] = { - "skel_unlink_qh", "skel_iso_qh", - "skel_int128_qh", "skel_int64_qh", -@@ -393,12 +395,13 @@ static int uhci_sprint_schedule(struct u - return out - buf; - } - -+#ifdef CONFIG_DEBUG_FS -+ - #define MAX_OUTPUT (64 * 1024) - - struct uhci_debug { - int size; - char *data; -- struct uhci_hcd *uhci; - }; - - static int uhci_debug_open(struct inode *inode, struct file *file) -@@ -419,8 +422,10 @@ static int uhci_debug_open(struct inode - goto out; - } - -+ up->size = 0; - spin_lock_irqsave(&uhci->lock, flags); -- up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); -+ if (uhci->is_initialized) -+ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); - spin_unlock_irqrestore(&uhci->lock, flags); - - file->private_data = up; -@@ -472,15 +477,32 @@ static int uhci_debug_release(struct ino - return 0; - } - -+#undef uhci_debug_operations - static struct file_operations uhci_debug_operations = { -+ .owner = THIS_MODULE, - .open = uhci_debug_open, - .llseek = uhci_debug_lseek, - .read = uhci_debug_read, - .release = uhci_debug_release, - }; - --#else /* CONFIG_DEBUG_FS */ -+#endif /* CONFIG_DEBUG_FS */ - --#define uhci_debug_operations (* (struct file_operations *) NULL) -+#else /* DEBUG */ -+ -+static inline void lprintk(char *buf) -+{} -+ -+static inline int uhci_show_qh(struct uhci_qh *qh, char *buf, -+ int len, int space) -+{ -+ return 0; -+} -+ -+static inline int uhci_sprint_schedule(struct uhci_hcd *uhci, -+ char *buf, int len) -+{ -+ return 0; -+} - - #endif ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c -@@ -68,12 +68,16 @@ Alan Stern" - * debug = 3, show all TDs in URBs when dumping - */ - #ifdef DEBUG -+#define DEBUG_CONFIGURED 1 - static int debug = 1; --#else --static int debug = 0; --#endif - module_param(debug, int, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(debug, "Debug level"); -+ -+#else -+#define DEBUG_CONFIGURED 0 -+#define debug 0 -+#endif -+ - static char *errbuf; - #define ERRBUF_LEN (32 * 1024) - -@@ -338,6 +342,12 @@ static irqreturn_t uhci_irq(struct usb_h - dev_err(uhci_dev(uhci), - "host controller halted, " - "very bad!\n"); -+ if (debug > 1 && errbuf) { -+ /* Print the schedule for debugging */ -+ uhci_sprint_schedule(uhci, -+ errbuf, ERRBUF_LEN); -+ lprintk(errbuf); -+ } - hc_died(uhci); - - /* Force a callback in case there are -@@ -376,6 +386,14 @@ static void release_uhci(struct uhci_hcd - { - int i; - -+ if (DEBUG_CONFIGURED) { -+ spin_lock_irq(&uhci->lock); -+ uhci->is_initialized = 0; -+ spin_unlock_irq(&uhci->lock); -+ -+ debugfs_remove(uhci->dentry); -+ } -+ - for (i = 0; i < UHCI_NUM_SKELQH; i++) - uhci_free_qh(uhci, uhci->skelqh[i]); - -@@ -390,8 +408,6 @@ static void release_uhci(struct uhci_hcd - dma_free_coherent(uhci_dev(uhci), - UHCI_NUMFRAMES * sizeof(*uhci->frame), - uhci->frame, uhci->frame_dma_handle); -- -- debugfs_remove(uhci->dentry); - } - - static int uhci_reset(struct usb_hcd *hcd) -@@ -474,17 +490,6 @@ static int uhci_start(struct usb_hcd *hc - - hcd->uses_new_polling = 1; - -- dentry = debugfs_create_file(hcd->self.bus_name, -- S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, -- &uhci_debug_operations); -- if (!dentry) { -- dev_err(uhci_dev(uhci), -- "couldn't create uhci debugfs entry\n"); -- retval = -ENOMEM; -- goto err_create_debug_entry; -- } -- uhci->dentry = dentry; -- - uhci->fsbr = 0; - uhci->fsbrtimeout = 0; - -@@ -495,6 +500,19 @@ static int uhci_start(struct usb_hcd *hc - - init_waitqueue_head(&uhci->waitqh); - -+ if (DEBUG_CONFIGURED) { -+ dentry = debugfs_create_file(hcd->self.bus_name, -+ S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, -+ uhci, &uhci_debug_operations); -+ if (!dentry) { -+ dev_err(uhci_dev(uhci), "couldn't create uhci " -+ "debugfs entry\n"); -+ retval = -ENOMEM; -+ goto err_create_debug_entry; -+ } -+ uhci->dentry = dentry; -+ } -+ - uhci->frame = dma_alloc_coherent(uhci_dev(uhci), - UHCI_NUMFRAMES * sizeof(*uhci->frame), - &uhci->frame_dma_handle, 0); -@@ -609,6 +627,7 @@ static int uhci_start(struct usb_hcd *hc - mb(); - - configure_hc(uhci); -+ uhci->is_initialized = 1; - start_rh(uhci); - return 0; - -@@ -872,16 +891,15 @@ static int __init uhci_hcd_init(void) - if (usb_disabled()) - return -ENODEV; - -- if (debug) { -+ if (DEBUG_CONFIGURED) { - errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); - if (!errbuf) - goto errbuf_failed; -+ uhci_debugfs_root = debugfs_create_dir("uhci", NULL); -+ if (!uhci_debugfs_root) -+ goto debug_failed; - } - -- uhci_debugfs_root = debugfs_create_dir("uhci", NULL); -- if (!uhci_debugfs_root) -- goto debug_failed; -- - uhci_up_cachep = kmem_cache_create("uhci_urb_priv", - sizeof(struct urb_priv), 0, 0, NULL, NULL); - if (!uhci_up_cachep) ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h -@@ -411,6 +411,7 @@ struct uhci_hcd { - unsigned int hc_inaccessible:1; /* HC is suspended or dead */ - unsigned int working_RD:1; /* Suspended root hub doesn't - need to be polled */ -+ unsigned int is_initialized:1; /* Data structure is usable */ - - /* Support for port suspend/resume/reset */ - unsigned long port_c_suspend; /* Bit-arrays of ports */ ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -736,7 +736,6 @@ err: - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); -- - lprintk(errbuf); - } - } -@@ -924,26 +923,17 @@ td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - - err: -- /* -- * Enable this chunk of code if you want to see some more debugging. -- * But be careful, it has the tendancy to starve out khubd and prevent -- * disconnects from happening successfully if you have a slow debug -- * log interface (like a serial console. -- */ --#if 0 - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", - __FUNCTION__, status); - -- if (errbuf) { -+ if (debug > 1 && errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); -- - lprintk(errbuf); - } - } --#endif - - /* Note that the queue has stopped and save the next toggle value */ - urbp->qh->element = UHCI_PTR_TERM; diff --git a/usb/uhci-remove-main-list-of-urbs.patch b/usb/uhci-remove-main-list-of-urbs.patch deleted file mode 100644 index 576b0b0cd447e..0000000000000 --- a/usb/uhci-remove-main-list-of-urbs.patch +++ /dev/null @@ -1,927 +0,0 @@ -From stern@rowland.harvard.edu Sat Dec 17 15:13:57 2005 -Date: Sat, 17 Dec 2005 18:02:38 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -Subject: [PATCH 3/4] UHCI: remove main list of URBs -Message-ID: <Pine.LNX.4.44L0.0512171728000.14730-100000@netrider.rowland.org> - -As part of reorienting uhci-hcd away from URBs and toward endpoint -queues, this patch (as625) eliminates the driver's main list of URBs. -The list wsa used mainly in checking for URB completions; now the driver -goes through the list of active endpoints and checks the members of the -queues. - -As a side effect, I had to remove the code that looks for FSBR timeouts. -For now, FSBR will remain on so long as any URBs on a full-speed control -or bulk queue request it, even if the queue isn't advancing. A later -patch can add more intelligent handling. This isn't a huge drawback; -it's pretty rare for an URB to get stuck for more than a fraction of a -second. (And it will help the people trying to use those insane HP USB -devices.) - - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-debug.c | 1 - drivers/usb/host/uhci-hcd.c | 2 - drivers/usb/host/uhci-hcd.h | 15 - drivers/usb/host/uhci-q.c | 633 ++++++++++++++++++------------------------ - 4 files changed, 280 insertions(+), 371 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c -+++ gregkh-2.6/drivers/usb/host/uhci-debug.c -@@ -114,7 +114,6 @@ static int uhci_show_urbp(struct urb_pri - } - - out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); -- out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : "")); - - if (urbp->urb->status != -EINPROGRESS) - out += sprintf(out, " Status=%d", urbp->urb->status); ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c -@@ -491,8 +491,6 @@ static int uhci_start(struct usb_hcd *hc - spin_lock_init(&uhci->lock); - - INIT_LIST_HEAD(&uhci->td_remove_list); -- INIT_LIST_HEAD(&uhci->urb_list); -- INIT_LIST_HEAD(&uhci->complete_list); - INIT_LIST_HEAD(&uhci->idle_qh_list); - - init_waitqueue_head(&uhci->waitqh); ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h -@@ -132,6 +132,10 @@ struct uhci_qh { - - unsigned int unlink_frame; /* When the QH was unlinked */ - int state; /* QH_STATE_xxx; see above */ -+ -+ unsigned int initial_toggle:1; /* Endpoint's current toggle value */ -+ unsigned int needs_fixup:1; /* Must fix the TD toggle values */ -+ unsigned int is_stopped:1; /* Queue was stopped by an error */ - } __attribute__((aligned(16))); - - /* -@@ -384,6 +388,7 @@ struct uhci_hcd { - - struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ - struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */ -+ struct uhci_qh *next_qh; /* Next QH to scan */ - - spinlock_t lock; - -@@ -413,16 +418,10 @@ struct uhci_hcd { - unsigned long resuming_ports; - unsigned long ports_timeout; /* Time to stop signalling */ - -- /* Main list of URBs currently controlled by this HC */ -- struct list_head urb_list; -- - /* List of TDs that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; - unsigned int td_remove_age; /* Age in frames */ - -- /* List of URBs awaiting completion callback */ -- struct list_head complete_list; -- - struct list_head idle_qh_list; /* Where the idle QHs live */ - - int rh_numports; /* Number of root-hub ports */ -@@ -448,7 +447,6 @@ static inline struct usb_hcd *uhci_to_hc - * Private per-URB data - */ - struct urb_priv { -- struct list_head urb_list; - struct list_head node; /* Node in the QH's urbp list */ - - struct urb *urb; -@@ -456,10 +454,7 @@ struct urb_priv { - struct uhci_qh *qh; /* QH for this URB */ - struct list_head td_list; - -- unsigned long fsbrtime; /* In jiffies */ -- - unsigned fsbr : 1; /* URB turned on FSBR */ -- unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ - unsigned short_transfer : 1; /* URB got a short transfer, no - * need to rescan */ - }; ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -151,53 +151,6 @@ static void uhci_unlink_isochronous_tds( - wmb(); - } - --/* -- * Remove an URB's TDs from the hardware schedule -- */ --static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci, -- struct urb *urb, int status) --{ -- struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; -- -- /* Isochronous TDs get unlinked directly from the frame list */ -- if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -- uhci_unlink_isochronous_tds(uhci, urb); -- return; -- } -- -- /* If the URB isn't first on its queue, adjust the link pointer -- * of the last TD in the previous URB. */ -- if (urbp->node.prev != &urbp->qh->queue) { -- struct urb_priv *purbp; -- struct uhci_td *ptd, *ltd; -- -- if (status == -EINPROGRESS) -- status = 0; -- purbp = list_entry(urbp->node.prev, struct urb_priv, node); -- ptd = list_entry(purbp->td_list.prev, struct uhci_td, -- list); -- ltd = list_entry(urbp->td_list.prev, struct uhci_td, -- list); -- ptd->link = ltd->link; -- } -- -- /* If the URB completed with an error, then the QH element certainly -- * points to one of the URB's TDs. If it completed normally then -- * the QH element has certainly moved on to the next URB. And if -- * the URB is still in progress then it must have been dequeued. -- * The QH element either hasn't reached it yet or is somewhere in -- * the middle. If the URB wasn't first we can assume that it -- * hasn't started yet (see above): Otherwise all the preceding URBs -- * would have completed and been removed from the queue, so this one -- * _would_ be first. -- * -- * If the QH element is inside this URB, clear it. It will be -- * set properly when the QH is activated. -- */ -- if (status < 0) -- urbp->qh->element = UHCI_PTR_TERM; --} -- - static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, - struct usb_device *udev, struct usb_host_endpoint *hep) - { -@@ -251,6 +204,90 @@ static void uhci_free_qh(struct uhci_hcd - } - - /* -+ * When the currently executing URB is dequeued, save its current toggle value -+ */ -+static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb) -+{ -+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; -+ struct uhci_td *td; -+ -+ /* If the QH element pointer is UHCI_PTR_TERM then then currently -+ * executing URB has already been unlinked, so this one isn't it. */ -+ if (qh_element(qh) == UHCI_PTR_TERM || -+ qh->queue.next != &urbp->node) -+ return; -+ qh->element = UHCI_PTR_TERM; -+ -+ /* Only bulk and interrupt pipes have to worry about toggles */ -+ if (!(usb_pipetype(urb->pipe) == PIPE_BULK || -+ usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) -+ return; -+ -+ /* Find the first active TD; that's the device's toggle state */ -+ list_for_each_entry(td, &urbp->td_list, list) { -+ if (td_status(td) & TD_CTRL_ACTIVE) { -+ qh->needs_fixup = 1; -+ qh->initial_toggle = uhci_toggle(td_token(td)); -+ return; -+ } -+ } -+ -+ WARN_ON(1); -+} -+ -+/* -+ * Fix up the data toggles for URBs in a queue, when one of them -+ * terminates early (short transfer, error, or dequeued). -+ */ -+static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) -+{ -+ struct urb_priv *urbp = NULL; -+ struct uhci_td *td; -+ unsigned int toggle = qh->initial_toggle; -+ unsigned int pipe; -+ -+ /* Fixups for a short transfer start with the second URB in the -+ * queue (the short URB is the first). */ -+ if (skip_first) -+ urbp = list_entry(qh->queue.next, struct urb_priv, node); -+ -+ /* When starting with the first URB, if the QH element pointer is -+ * still valid then we know the URB's toggles are okay. */ -+ else if (qh_element(qh) != UHCI_PTR_TERM) -+ toggle = 2; -+ -+ /* Fix up the toggle for the URBs in the queue. Normally this -+ * loop won't run more than once: When an error or short transfer -+ * occurs, the queue usually gets emptied. */ -+ list_prepare_entry(urbp, &qh->queue, node); -+ list_for_each_entry_continue(urbp, &qh->queue, node) { -+ -+ /* If the first TD has the right toggle value, we don't -+ * need to change any toggles in this URB */ -+ td = list_entry(urbp->td_list.next, struct uhci_td, list); -+ if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) { -+ td = list_entry(urbp->td_list.next, struct uhci_td, -+ list); -+ toggle = uhci_toggle(td_token(td)) ^ 1; -+ -+ /* Otherwise all the toggles in the URB have to be switched */ -+ } else { -+ list_for_each_entry(td, &urbp->td_list, list) { -+ td->token ^= __constant_cpu_to_le32( -+ TD_TOKEN_TOGGLE); -+ toggle ^= 1; -+ } -+ } -+ } -+ -+ wmb(); -+ pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe; -+ usb_settoggle(qh->udev, usb_pipeendpoint(pipe), -+ usb_pipeout(pipe), toggle); -+ qh->needs_fixup = 0; -+} -+ -+/* - * Put a QH on the schedule in both hardware and software - */ - static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -@@ -276,6 +313,9 @@ static void uhci_activate_qh(struct uhci - - /* Move the QH from its old list to the end of the appropriate - * skeleton's list */ -+ if (qh == uhci->next_qh) -+ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, -+ node); - list_move_tail(&qh->node, &qh->skel->node); - - /* Link it into the schedule */ -@@ -310,6 +350,9 @@ static void uhci_unlink_qh(struct uhci_h - uhci_set_next_interrupt(uhci); - - /* Move the QH from its old list to the end of the unlinking list */ -+ if (qh == uhci->next_qh) -+ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, -+ node); - list_move_tail(&qh->node, &uhci->skel_unlink_qh->node); - } - -@@ -323,6 +366,9 @@ static void uhci_make_qh_idle(struct uhc - { - WARN_ON(qh->state == QH_STATE_ACTIVE); - -+ if (qh == uhci->next_qh) -+ uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, -+ node); - list_move(&qh->node, &uhci->idle_qh_list); - qh->state = QH_STATE_IDLE; - -@@ -344,11 +390,9 @@ static inline struct urb_priv *uhci_allo - - urbp->urb = urb; - urb->hcpriv = urbp; -- urbp->fsbrtime = jiffies; - - INIT_LIST_HEAD(&urbp->node); - INIT_LIST_HEAD(&urbp->td_list); -- INIT_LIST_HEAD(&urbp->urb_list); - - return urbp; - } -@@ -373,9 +417,6 @@ static void uhci_free_urb_priv(struct uh - { - struct uhci_td *td, *tmp; - -- if (!list_empty(&urbp->urb_list)) -- dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n", -- urbp->urb); - if (!list_empty(&urbp->node)) - dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", - urbp->urb); -@@ -453,71 +494,6 @@ static int uhci_map_status(int status, i - } - - /* -- * Fix up the data toggles for URBs in a queue, when one of them -- * terminates early (short transfer, error, or dequeued). -- */ --static void uhci_fixup_toggles(struct urb *urb) --{ -- struct list_head *head; -- struct uhci_td *td; -- struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; -- int prevactive = 0; -- unsigned int toggle = 0; -- struct urb_priv *turbp, *list_end; -- -- /* -- * We need to find out what the last successful toggle was so -- * we can update the data toggles for the following transfers. -- * -- * There are 2 ways the last successful completed TD is found: -- * -- * 1) The TD is NOT active and the actual length < expected length -- * 2) The TD is NOT active and it's the last TD in the chain -- * -- * and a third way the first uncompleted TD is found: -- * -- * 3) The TD is active and the previous TD is NOT active -- */ -- head = &urbp->td_list; -- list_for_each_entry(td, head, list) { -- unsigned int ctrlstat = td_status(td); -- -- if (!(ctrlstat & TD_CTRL_ACTIVE) && -- (uhci_actual_length(ctrlstat) < -- uhci_expected_length(td_token(td)) || -- td->list.next == head)) -- toggle = uhci_toggle(td_token(td)) ^ 1; -- else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) -- toggle = uhci_toggle(td_token(td)); -- -- prevactive = ctrlstat & TD_CTRL_ACTIVE; -- } -- -- /* -- * Fix up the toggle for the following URBs in the queue. -- * -- * We can stop as soon as we find an URB with toggles set correctly, -- * because then all the following URBs will be correct also. -- */ -- list_end = list_entry(&urbp->qh->queue, struct urb_priv, node); -- turbp = urbp; -- while ((turbp = list_entry(turbp->node.next, struct urb_priv, node)) -- != list_end) { -- td = list_entry(turbp->td_list.next, struct uhci_td, list); -- if (uhci_toggle(td_token(td)) == toggle) -- return; -- -- list_for_each_entry(td, &turbp->td_list, list) { -- td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE); -- toggle ^= 1; -- } -- } -- -- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe), toggle); --} -- --/* - * Control transfers - */ - static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, -@@ -765,6 +741,9 @@ err: - } - } - -+ /* Note that the queue has stopped */ -+ urbp->qh->element = UHCI_PTR_TERM; -+ urbp->qh->is_stopped = 1; - return ret; - } - -@@ -927,7 +906,10 @@ static int uhci_result_common(struct uhc - */ - if (!urbp->short_transfer) { - urbp->short_transfer = 1; -- uhci_fixup_toggles(urb); -+ urbp->qh->initial_toggle = -+ uhci_toggle(td_token(td)) ^ 1; -+ uhci_fixup_toggles(urbp->qh, 1); -+ - td = list_entry(urbp->td_list.prev, - struct uhci_td, list); - urbp->qh->element = td->link; -@@ -962,6 +944,13 @@ err: - } - } - #endif -+ -+ /* Note that the queue has stopped and save the next toggle value */ -+ urbp->qh->element = UHCI_PTR_TERM; -+ urbp->qh->is_stopped = 1; -+ urbp->qh->needs_fixup = 1; -+ urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^ -+ (ret == -EREMOTEIO); - return ret; - } - -@@ -995,76 +984,39 @@ static inline int uhci_submit_interrupt( - /* - * Isochronous transfers - */ --static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) --{ -- struct urb *last_urb = NULL; -- struct urb_priv *up; -- int ret = 0; -- -- list_for_each_entry(up, &uhci->urb_list, urb_list) { -- struct urb *u = up->urb; -- -- /* look for pending URBs with identical pipe handle */ -- if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && -- (u->status == -EINPROGRESS) && (u != urb)) { -- if (!last_urb) -- *start = u->start_frame; -- last_urb = u; -- } -- } -- -- if (last_urb) { -- *end = (last_urb->start_frame + last_urb->number_of_packets * -- last_urb->interval) & (UHCI_NUMFRAMES-1); -- ret = 0; -- } else -- ret = -1; /* no previous urb found */ -- -- return ret; --} -- --static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) -+static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { -- int limits; -- unsigned int start = 0, end = 0; -+ struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ -+ int i, frame; -+ unsigned long destination, status; -+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - - if (urb->number_of_packets > 900) /* 900? Why? */ - return -EFBIG; - -- limits = isochronous_find_limits(uhci, urb, &start, &end); -+ status = TD_CTRL_ACTIVE | TD_CTRL_IOS; -+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - -+ /* Figure out the starting frame number */ - if (urb->transfer_flags & URB_ISO_ASAP) { -- if (limits) { -+ if (list_empty(&qh->queue)) { - uhci_get_current_frame_number(uhci); -- urb->start_frame = (uhci->frame_number + 10) -- & (UHCI_NUMFRAMES - 1); -- } else -- urb->start_frame = end; -+ urb->start_frame = (uhci->frame_number + 10); -+ -+ } else { /* Go right after the last one */ -+ struct urb *last_urb; -+ -+ last_urb = list_entry(qh->queue.prev, -+ struct urb_priv, node)->urb; -+ urb->start_frame = (last_urb->start_frame + -+ last_urb->number_of_packets * -+ last_urb->interval); -+ } - } else { -- urb->start_frame &= (UHCI_NUMFRAMES - 1); - /* FIXME: Sanity check */ - } -- -- return 0; --} -- --/* -- * Isochronous transfers -- */ --static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, -- struct uhci_qh *qh) --{ -- struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ -- int i, ret, frame; -- unsigned long destination, status; -- struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; -- -- status = TD_CTRL_ACTIVE | TD_CTRL_IOS; -- destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); -- -- ret = isochronous_find_start(uhci, urb); -- if (ret) -- return ret; -+ urb->start_frame &= (UHCI_NUMFRAMES - 1); - - for (i = 0; i < urb->number_of_packets; i++) { - td = uhci_alloc_td(uhci); -@@ -1203,7 +1155,6 @@ static int uhci_urb_enqueue(struct usb_h - /* Add this URB to the QH */ - urbp->qh = qh; - list_add_tail(&urbp->node, &qh->queue); -- list_add_tail(&urbp->urb_list, &uhci->urb_list); - - /* If the new URB is the first and only one on this QH then either - * the QH is new and idle or else it's unlinked and waiting to -@@ -1224,49 +1175,66 @@ done: - return ret; - } - -+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -+{ -+ struct uhci_hcd *uhci = hcd_to_uhci(hcd); -+ unsigned long flags; -+ struct urb_priv *urbp; -+ -+ spin_lock_irqsave(&uhci->lock, flags); -+ urbp = urb->hcpriv; -+ if (!urbp) /* URB was never linked! */ -+ goto done; -+ -+ /* Remove Isochronous TDs from the frame list ASAP */ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) -+ uhci_unlink_isochronous_tds(uhci, urb); -+ uhci_unlink_qh(uhci, urbp->qh); -+ -+done: -+ spin_unlock_irqrestore(&uhci->lock, flags); -+ return 0; -+} -+ - /* -- * Return the result of a transfer -+ * Finish unlinking an URB and give it back - */ --static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) -+static void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh, -+ struct urb *urb, struct pt_regs *regs) -+__releases(uhci->lock) -+__acquires(uhci->lock) - { -- int status; -- int okay_to_giveback = 0; - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - -- switch (usb_pipetype(urb->pipe)) { -- case PIPE_CONTROL: -- status = uhci_result_control(uhci, urb); -- break; -- case PIPE_ISOCHRONOUS: -- status = uhci_result_isochronous(uhci, urb); -- break; -- default: /* PIPE_BULK or PIPE_INTERRUPT */ -- status = uhci_result_common(uhci, urb); -- break; -- } -+ /* Isochronous TDs get unlinked directly from the frame list */ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) -+ uhci_unlink_isochronous_tds(uhci, urb); - -- spin_lock(&urb->lock); -- if (urb->status == -EINPROGRESS) { /* Not yet dequeued */ -- if (status != -EINPROGRESS) { /* URB has completed */ -- urb->status = status; -+ /* If the URB isn't first on its queue, adjust the link pointer -+ * of the last TD in the previous URB. */ -+ else if (qh->queue.next != &urbp->node) { -+ struct urb_priv *purbp; -+ struct uhci_td *ptd, *ltd; - -- /* If the URB got a real error (as opposed to -- * simply being dequeued), we don't have to -- * unlink the QH. Fix this later... */ -- if (status < 0) -- uhci_unlink_qh(uhci, urbp->qh); -- else -- okay_to_giveback = 1; -- } -- } else { /* Already dequeued */ -- if (urbp->qh->state == QH_STATE_UNLINKING && -- uhci->frame_number + uhci->is_stopped != -- urbp->qh->unlink_frame) -- okay_to_giveback = 1; -+ purbp = list_entry(urbp->node.prev, struct urb_priv, node); -+ ptd = list_entry(purbp->td_list.prev, struct uhci_td, -+ list); -+ ltd = list_entry(urbp->td_list.prev, struct uhci_td, -+ list); -+ ptd->link = ltd->link; - } -- spin_unlock(&urb->lock); -- if (!okay_to_giveback) -- return; -+ -+ /* Take the URB off the QH's queue. If the queue is now empty, -+ * this is a perfect time for a toggle fixup. */ -+ list_del_init(&urbp->node); -+ if (list_empty(&qh->queue) && qh->needs_fixup) { -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe), qh->initial_toggle); -+ qh->needs_fixup = 0; -+ } -+ -+ uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ -+ uhci_free_urb_priv(uhci, urbp); - - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: -@@ -1277,122 +1245,107 @@ static void uhci_transfer_result(struct - case PIPE_INTERRUPT: - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Make sure we don't release if we have a queued URB */ -- if (list_empty(&urbp->qh->queue) && urb->bandwidth) -+ if (list_empty(&qh->queue) && urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 0); - else - /* bandwidth was passed on to queued URB, */ - /* so don't let usb_unlink_urb() release it */ - urb->bandwidth = 0; -- /* Falls through */ -- case PIPE_BULK: -- if (status < 0) -- uhci_fixup_toggles(urb); -- break; -- default: /* PIPE_CONTROL */ - break; - } - -- /* Take the URB's TDs off the hardware schedule */ -- uhci_remove_tds_from_schedule(uhci, urb, status); -- -- /* Take the URB off the QH's queue and see if the QH is now unused */ -- list_del_init(&urbp->node); -- if (list_empty(&urbp->qh->queue)) -- uhci_unlink_qh(uhci, urbp->qh); -+ spin_unlock(&uhci->lock); -+ usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, regs); -+ spin_lock(&uhci->lock); - -- uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ -+ /* If the queue is now empty, we can unlink the QH and give up its -+ * reserved bandwidth. */ -+ if (list_empty(&qh->queue)) { -+ uhci_unlink_qh(uhci, qh); - -- /* Queue it for giving back */ -- list_move_tail(&urbp->urb_list, &uhci->complete_list); -+ /* Bandwidth stuff not yet implemented */ -+ } - } - - /* -- * Check out the QHs waiting to be fully unlinked -+ * Scan the URBs in a QH's queue - */ --static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci) --{ -- struct uhci_qh *qh, *tmp; -+#define QH_FINISHED_UNLINKING(qh) \ -+ (qh->state == QH_STATE_UNLINKING && \ -+ uhci->frame_number + uhci->is_stopped != qh->unlink_frame) - -- list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) { -- -- /* If the queue is empty and the QH is fully unlinked then -- * it can become IDLE. */ -- if (list_empty(&qh->queue)) { -- if (uhci->frame_number + uhci->is_stopped != -- qh->unlink_frame) -- uhci_make_qh_idle(uhci, qh); -- -- /* If none of the QH's URBs have been dequeued then the QH -- * should be re-activated. */ -- } else { -- struct urb_priv *urbp; -- int any_dequeued = 0; -- -- list_for_each_entry(urbp, &qh->queue, node) { -- if (urbp->urb->status != -EINPROGRESS) { -- any_dequeued = 1; -- break; -- } -- } -- if (!any_dequeued) -- uhci_activate_qh(uhci, qh); -- } -- } --} -- --static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -+static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, -+ struct pt_regs *regs) - { -- struct uhci_hcd *uhci = hcd_to_uhci(hcd); -- unsigned long flags; - struct urb_priv *urbp; -+ struct urb *urb; -+ int status; - -- spin_lock_irqsave(&uhci->lock, flags); -- urbp = urb->hcpriv; -- if (!urbp) /* URB was never linked! */ -- goto done; -- -- /* Remove Isochronous TDs from the frame list ASAP */ -- if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) -- uhci_unlink_isochronous_tds(uhci, urb); -- uhci_unlink_qh(uhci, urbp->qh); -- --done: -- spin_unlock_irqrestore(&uhci->lock, flags); -- return 0; --} -+ while (!list_empty(&qh->queue)) { -+ urbp = list_entry(qh->queue.next, struct urb_priv, node); -+ urb = urbp->urb; -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ status = uhci_result_control(uhci, urb); -+ break; -+ case PIPE_ISOCHRONOUS: -+ status = uhci_result_isochronous(uhci, urb); -+ break; -+ default: /* PIPE_BULK or PIPE_INTERRUPT */ -+ status = uhci_result_common(uhci, urb); -+ break; -+ } -+ if (status == -EINPROGRESS) -+ break; - --static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) --{ -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; -- struct list_head *head; -- struct uhci_td *td; -- int count = 0; -+ spin_lock(&urb->lock); -+ if (urb->status == -EINPROGRESS) /* Not dequeued */ -+ urb->status = status; -+ else -+ status = -ECONNRESET; -+ spin_unlock(&urb->lock); - -- uhci_dec_fsbr(uhci, urb); -+ /* Dequeued but completed URBs can't be given back unless -+ * the QH is stopped or has finished unlinking. */ -+ if (status == -ECONNRESET && -+ !(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) -+ return; - -- urbp->fsbr_timeout = 1; -+ uhci_giveback_urb(uhci, qh, urb, regs); -+ if (qh->is_stopped) -+ break; -+ } - -- /* -- * Ideally we would want to fix qh->element as well, but it's -- * read/write by the HC, so that can introduce a race. It's not -- * really worth the hassle -- */ -+ /* If the QH is neither stopped nor finished unlinking (normal case), -+ * our work here is done. */ -+ restart: -+ if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh))) -+ return; - -- head = &urbp->td_list; -- list_for_each_entry(td, head, list) { -- /* -- * Make sure we don't do the last one (since it'll have the -- * TERM bit set) as well as we skip every so many TDs to -- * make sure it doesn't hog the bandwidth -- */ -- if (td->list.next != head && (count % DEPTH_INTERVAL) == -- (DEPTH_INTERVAL - 1)) -- td->link |= UHCI_PTR_DEPTH; -+ /* Otherwise give back each of the dequeued URBs */ -+ list_for_each_entry(urbp, &qh->queue, node) { -+ urb = urbp->urb; -+ if (urb->status != -EINPROGRESS) { -+ uhci_save_toggle(qh, urb); -+ uhci_giveback_urb(uhci, qh, urb, regs); -+ goto restart; -+ } -+ } -+ qh->is_stopped = 0; - -- count++; -+ /* There are no more dequeued URBs. If there are still URBs on the -+ * queue, the QH can now be re-activated. */ -+ if (!list_empty(&qh->queue)) { -+ if (qh->needs_fixup) -+ uhci_fixup_toggles(qh, 0); -+ uhci_activate_qh(uhci, qh); - } - -- return 0; -+ /* The queue is empty. The QH can become idle if it is fully -+ * unlinked. */ -+ else if (QH_FINISHED_UNLINKING(qh)) -+ uhci_make_qh_idle(uhci, qh); - } - - static void uhci_free_pending_tds(struct uhci_hcd *uhci) -@@ -1406,36 +1359,13 @@ static void uhci_free_pending_tds(struct - } - } - --static void --uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) --__releases(uhci->lock) --__acquires(uhci->lock) --{ -- struct uhci_hcd *uhci = hcd_to_uhci(hcd); -- -- uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv)); -- -- spin_unlock(&uhci->lock); -- usb_hcd_giveback_urb(hcd, urb, regs); -- spin_lock(&uhci->lock); --} -- --static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs) --{ -- struct urb_priv *urbp, *tmp; -- -- list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) { -- struct urb *urb = urbp->urb; -- -- list_del_init(&urbp->urb_list); -- uhci_finish_urb(uhci_to_hcd(uhci), urb, regs); -- } --} -- --/* Process events in the schedule, but only in one thread at a time */ -+/* -+ * Process events in the schedule, but only in one thread at a time -+ */ - static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) - { -- struct urb_priv *urbp, *tmp; -+ int i; -+ struct uhci_qh *qh; - - /* Don't allow re-entrant calls */ - if (uhci->scan_in_progress) { -@@ -1452,26 +1382,24 @@ static void uhci_scan_schedule(struct uh - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) - uhci_free_pending_tds(uhci); - -- /* Walk the list of pending URBs to see which ones completed -- * (must be _safe because uhci_transfer_result() dequeues URBs) */ -- list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { -- struct urb *urb = urbp->urb; -- -- /* Checks the status and does all of the magic necessary */ -- uhci_transfer_result(uhci, urb); -+ /* Go through all the QH queues and process the URBs in each one */ -+ for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { -+ uhci->next_qh = list_entry(uhci->skelqh[i]->node.next, -+ struct uhci_qh, node); -+ while ((qh = uhci->next_qh) != uhci->skelqh[i]) { -+ uhci->next_qh = list_entry(qh->node.next, -+ struct uhci_qh, node); -+ uhci_scan_qh(uhci, qh, regs); -+ } - } -- uhci_finish_completion(uhci, regs); -- -- /* If the controller is stopped, we can finish these off right now */ -- if (uhci->is_stopped) -- uhci_free_pending_tds(uhci); - - if (uhci->need_rescan) - goto rescan; - uhci->scan_in_progress = 0; - -- /* Check out the QHs waiting for unlinking */ -- uhci_scan_unlinking_qhs(uhci); -+ /* If the controller is stopped, we can finish these off right now */ -+ if (uhci->is_stopped) -+ uhci_free_pending_tds(uhci); - - if (list_empty(&uhci->td_remove_list) && - list_empty(&uhci->skel_unlink_qh->node)) -@@ -1482,19 +1410,8 @@ static void uhci_scan_schedule(struct uh - - static void check_fsbr(struct uhci_hcd *uhci) - { -- struct urb_priv *up; -- -- list_for_each_entry(up, &uhci->urb_list, urb_list) { -- struct urb *u = up->urb; -- -- spin_lock(&u->lock); -- -- /* Check if the FSBR timed out */ -- if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) -- uhci_fsbr_timeout(uhci, u); -- -- spin_unlock(&u->lock); -- } -+ /* For now, don't scan URBs for FSBR timeouts. -+ * Add it back in later... */ - - /* Really disable FSBR */ - if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { diff --git a/usb/uhci-use-dummy-tds.patch b/usb/uhci-use-dummy-tds.patch deleted file mode 100644 index 16b02efed5462..0000000000000 --- a/usb/uhci-use-dummy-tds.patch +++ /dev/null @@ -1,320 +0,0 @@ -From stern@rowland.harvard.edu Sat Dec 17 15:13:52 2005 -Date: Sat, 17 Dec 2005 18:00:12 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -Subject: [PATCH 2/4] UHCI: use dummy TDs -Message-ID: <Pine.LNX.4.44L0.0512171722380.14730-100000@netrider.rowland.org> - -This patch (as624) fixes a hardware race in uhci-hcd by adding a dummy -TD to the end of each endpoint's queue. Without the dummy the host -controller will effectively turn off the queue when it reaches the end, -which happens asynchronously. This leads to a potential problem when -new transfer descriptors are added to the end of the queue; they may -never get used. - -With a dummy TD present the controller never turns off the queue; -instead it just stops at the dummy and leaves the queue on but inactive. -When new TDs are added to the end of the queue, the first new one gets -written over the dummy. Thus there's never any question about whether -the queue is running or needs to be restarted. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-debug.c | 5 + - drivers/usb/host/uhci-hcd.h | 1 - drivers/usb/host/uhci-q.c | 138 +++++++++++++++++++++++------------------- - 3 files changed, 83 insertions(+), 61 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c -+++ gregkh-2.6/drivers/usb/host/uhci-debug.c -@@ -189,6 +189,11 @@ static int uhci_show_qh(struct uhci_qh * - space, "", nurbs); - } - -+ if (qh->udev) { -+ out += sprintf(out, "%*s Dummy TD\n", space, ""); -+ out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); -+ } -+ - return out - buf; - } - ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h -@@ -128,6 +128,7 @@ struct uhci_qh { - struct usb_device *udev; - struct list_head queue; /* Queue of urbps for this QH */ - struct uhci_qh *skel; /* Skeleton for this QH */ -+ struct uhci_td *dummy_td; /* Dummy TD to end the queue */ - - unsigned int unlink_frame; /* When the QH was unlinked */ - int state; /* QH_STATE_xxx; see above */ ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -48,10 +48,6 @@ static struct uhci_td *uhci_alloc_td(str - return NULL; - - td->dma_handle = dma_handle; -- -- td->link = UHCI_PTR_TERM; -- td->buffer = 0; -- - td->frame = -1; - - INIT_LIST_HEAD(&td->list); -@@ -221,6 +217,11 @@ static struct uhci_qh *uhci_alloc_qh(str - INIT_LIST_HEAD(&qh->node); - - if (udev) { /* Normal QH */ -+ qh->dummy_td = uhci_alloc_td(uhci); -+ if (!qh->dummy_td) { -+ dma_pool_free(uhci->qh_pool, qh, dma_handle); -+ return NULL; -+ } - qh->state = QH_STATE_IDLE; - qh->hep = hep; - qh->udev = udev; -@@ -244,6 +245,7 @@ static void uhci_free_qh(struct uhci_hcd - if (qh->udev) { - qh->hep->hcpriv = NULL; - usb_put_dev(qh->udev); -+ uhci_free_td(uhci, qh->dummy_td); - } - dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); - } -@@ -531,22 +533,20 @@ static int uhci_submit_control(struct uh - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - -- /* 3 errors */ -- status = TD_CTRL_ACTIVE | uhci_maxerr(3); -+ /* 3 errors, dummy TD remains inactive */ -+ status = uhci_maxerr(3); - if (urb->dev->speed == USB_SPEED_LOW) - status |= TD_CTRL_LS; - - /* - * Build the TD for the control request setup packet - */ -- td = uhci_alloc_td(uhci); -- if (!td) -- return -ENOMEM; -- -+ td = qh->dummy_td; - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(8), - urb->setup_dma); - plink = &td->link; -+ status |= TD_CTRL_ACTIVE; - - /* - * If direction is "send", change the packet ID from SETUP (0x2D) -@@ -568,7 +568,7 @@ static int uhci_submit_control(struct uh - - td = uhci_alloc_td(uhci); - if (!td) -- return -ENOMEM; -+ goto nomem; - *plink = cpu_to_le32(td->dma_handle); - - /* Alternate Data0/1 (start with Data1) */ -@@ -588,7 +588,7 @@ static int uhci_submit_control(struct uh - */ - td = uhci_alloc_td(uhci); - if (!td) -- return -ENOMEM; -+ goto nomem; - *plink = cpu_to_le32(td->dma_handle); - - /* -@@ -608,6 +608,20 @@ static int uhci_submit_control(struct uh - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status | TD_CTRL_IOC, - destination | uhci_explen(0), 0); -+ plink = &td->link; -+ -+ /* -+ * Build the new dummy TD and activate the old one -+ */ -+ td = uhci_alloc_td(uhci); -+ if (!td) -+ goto nomem; -+ *plink = cpu_to_le32(td->dma_handle); -+ -+ uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); -+ wmb(); -+ qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); -+ qh->dummy_td = td; - - /* Low-speed transfers get a different queue, and won't hog the bus. - * Also, some devices enumerate better without FSBR; the easiest way -@@ -620,8 +634,12 @@ static int uhci_submit_control(struct uh - qh->skel = uhci->skel_fs_control_qh; - uhci_inc_fsbr(uhci, urb); - } -- - return 0; -+ -+nomem: -+ /* Remove the dummy TD from the td_list so it doesn't get freed */ -+ uhci_remove_td_from_urb(qh->dummy_td); -+ return -ENOMEM; - } - - /* -@@ -761,16 +779,19 @@ static int uhci_submit_common(struct uhc - int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); - int len = urb->transfer_buffer_length; - dma_addr_t data = urb->transfer_dma; -- __le32 *plink, fake_link; -+ __le32 *plink; -+ unsigned int toggle; - - if (len < 0) - return -EINVAL; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); -+ toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe)); - -- /* 3 errors */ -- status = TD_CTRL_ACTIVE | uhci_maxerr(3); -+ /* 3 errors, dummy TD remains inactive */ -+ status = uhci_maxerr(3); - if (urb->dev->speed == USB_SPEED_LOW) - status |= TD_CTRL_LS; - if (usb_pipein(urb->pipe)) -@@ -779,7 +800,8 @@ static int uhci_submit_common(struct uhc - /* - * Build the DATA TDs - */ -- plink = &fake_link; -+ plink = NULL; -+ td = qh->dummy_td; - do { /* Allow zero length packets */ - int pktsze = maxsze; - -@@ -789,24 +811,23 @@ static int uhci_submit_common(struct uhc - status &= ~TD_CTRL_SPD; - } - -- td = uhci_alloc_td(uhci); -- if (!td) -- return -ENOMEM; -- *plink = cpu_to_le32(td->dma_handle); -- -+ if (plink) { -+ td = uhci_alloc_td(uhci); -+ if (!td) -+ goto nomem; -+ *plink = cpu_to_le32(td->dma_handle); -+ } - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, -- destination | uhci_explen(pktsze) | -- (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), -- data); -+ destination | uhci_explen(pktsze) | -+ (toggle << TD_TOKEN_TOGGLE_SHIFT), -+ data); - plink = &td->link; -+ status |= TD_CTRL_ACTIVE; - - data += pktsze; - len -= maxsze; -- -- usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe)); -+ toggle ^= 1; - } while (len > 0); - - /* -@@ -821,17 +842,17 @@ static int uhci_submit_common(struct uhc - urb->transfer_buffer_length > 0) { - td = uhci_alloc_td(uhci); - if (!td) -- return -ENOMEM; -+ goto nomem; - *plink = cpu_to_le32(td->dma_handle); - - uhci_add_td_to_urb(urb, td); -- uhci_fill_td(td, status, destination | uhci_explen(0) | -- (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), -- data); -+ uhci_fill_td(td, status, -+ destination | uhci_explen(0) | -+ (toggle << TD_TOKEN_TOGGLE_SHIFT), -+ data); -+ plink = &td->link; - -- usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe)); -+ toggle ^= 1; - } - - /* Set the interrupt-on-completion flag on the last packet. -@@ -842,7 +863,27 @@ static int uhci_submit_common(struct uhc - * flag setting. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); - -+ /* -+ * Build the new dummy TD and activate the old one -+ */ -+ td = uhci_alloc_td(uhci); -+ if (!td) -+ goto nomem; -+ *plink = cpu_to_le32(td->dma_handle); -+ -+ uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); -+ wmb(); -+ qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); -+ qh->dummy_td = td; -+ -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe), toggle); - return 0; -+ -+nomem: -+ /* Remove the dummy TD from the td_list so it doesn't get freed */ -+ uhci_remove_td_from_urb(qh->dummy_td); -+ return -ENOMEM; - } - - /* -@@ -1169,31 +1210,6 @@ static int uhci_urb_enqueue(struct usb_h - * become idle, so we can activate it right away. */ - if (qh->queue.next == &urbp->node) - uhci_activate_qh(uhci, qh); -- -- /* If the QH is already active, we have a race with the hardware. -- * This won't get fixed until dummy TDs are added. */ -- else if (qh->state == QH_STATE_ACTIVE) { -- -- /* If the URB isn't first on its queue, adjust the link pointer -- * of the last TD in the previous URB. */ -- if (urbp->node.prev != &urbp->qh->queue) { -- struct urb_priv *purbp = list_entry(urbp->node.prev, -- struct urb_priv, node); -- struct uhci_td *ptd = list_entry(purbp->td_list.prev, -- struct uhci_td, list); -- struct uhci_td *td = list_entry(urbp->td_list.next, -- struct uhci_td, list); -- -- ptd->link = cpu_to_le32(td->dma_handle); -- -- } -- if (qh_element(qh) == UHCI_PTR_TERM) { -- struct uhci_td *td = list_entry(urbp->td_list.next, -- struct uhci_td, list); -- -- qh->element = cpu_to_le32(td->dma_handle); -- } -- } - goto done; - - err_submit_failed: diff --git a/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch b/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch deleted file mode 100644 index ed3417ac5b96c..0000000000000 --- a/usb/uhci-use-one-qh-per-endpoint-not-per-urb.patch +++ /dev/null @@ -1,2397 +0,0 @@ -From stern@rowland.harvard.edu Sat Dec 17 15:13:30 2005 -Date: Sat, 17 Dec 2005 17:58:46 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -Subject: [PATCH 1/4] UHCI: use one QH per endpoint, not per URB -Message-ID: <Pine.LNX.4.44L0.0512171718340.14730-100000@netrider.rowland.org> - -This patch (as623) changes the uhci-hcd driver to make it use one QH per -device endpoint, instead of a QH per URB as it does now. Numerous areas -of the code are affected by this. For example, the distinction between -"queued" URBs and non-"queued" URBs no longer exists; all URBs belong to -a queue and some just happen to be at the queue's head. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-debug.c | 320 +++---------- - drivers/usb/host/uhci-hcd.c | 65 +- - drivers/usb/host/uhci-hcd.h | 183 ++++--- - drivers/usb/host/uhci-q.c | 987 +++++++++++++++++++----------------------- - 4 files changed, 689 insertions(+), 866 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-debug.c -+++ gregkh-2.6/drivers/usb/host/uhci-debug.c -@@ -90,13 +90,60 @@ static int uhci_show_td(struct uhci_td * - return out - buf; - } - --static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) -+static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) - { - char *out = buf; -- struct urb_priv *urbp; -- struct list_head *head, *tmp; - struct uhci_td *td; -- int i = 0, checked = 0, prevactive = 0; -+ int i, nactive, ninactive; -+ -+ if (len < 200) -+ return 0; -+ -+ out += sprintf(out, "urb_priv [%p] ", urbp); -+ out += sprintf(out, "urb [%p] ", urbp->urb); -+ out += sprintf(out, "qh [%p] ", urbp->qh); -+ out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); -+ out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), -+ (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); -+ -+ switch (usb_pipetype(urbp->urb->pipe)) { -+ case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break; -+ case PIPE_INTERRUPT: out += sprintf(out, "INT"); break; -+ case PIPE_BULK: out += sprintf(out, "BLK"); break; -+ case PIPE_CONTROL: out += sprintf(out, "CTL"); break; -+ } -+ -+ out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : "")); -+ out += sprintf(out, "%s", (urbp->fsbr_timeout ? " FSBR_TO" : "")); -+ -+ if (urbp->urb->status != -EINPROGRESS) -+ out += sprintf(out, " Status=%d", urbp->urb->status); -+ out += sprintf(out, "\n"); -+ -+ i = nactive = ninactive = 0; -+ list_for_each_entry(td, &urbp->td_list, list) { -+ if (++i <= 10 || debug > 2) { -+ out += sprintf(out, "%*s%d: ", space + 2, "", i); -+ out += uhci_show_td(td, out, len - (out - buf), 0); -+ } else { -+ if (td_status(td) & TD_CTRL_ACTIVE) -+ ++nactive; -+ else -+ ++ninactive; -+ } -+ } -+ if (nactive + ninactive > 0) -+ out += sprintf(out, "%*s[skipped %d inactive and %d active " -+ "TDs]\n", -+ space, "", ninactive, nactive); -+ -+ return out - buf; -+} -+ -+static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) -+{ -+ char *out = buf; -+ int i, nurbs; - __le32 element = qh_element(qh); - - /* Try to make sure there's enough memory */ -@@ -118,86 +165,36 @@ static int uhci_show_qh(struct uhci_qh * - if (!(element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH))) - out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); - -- if (!qh->urbp) { -- out += sprintf(out, "%*s urbp == NULL\n", space, ""); -- goto out; -- } -- -- urbp = qh->urbp; -- -- head = &urbp->td_list; -- tmp = head->next; -- -- td = list_entry(tmp, struct uhci_td, list); -- -- if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) -- out += sprintf(out, "%*s Element != First TD\n", space, ""); -- -- while (tmp != head) { -- struct uhci_td *td = list_entry(tmp, struct uhci_td, list); -- -- tmp = tmp->next; -- -- out += sprintf(out, "%*s%d: ", space + 2, "", i++); -- out += uhci_show_td(td, out, len - (out - buf), 0); -- -- if (i > 10 && !checked && prevactive && tmp != head && -- debug <= 2) { -- struct list_head *ntmp = tmp; -- struct uhci_td *ntd = td; -- int active = 1, ni = i; -- -- checked = 1; -- -- while (ntmp != head && ntmp->next != head && active) { -- ntd = list_entry(ntmp, struct uhci_td, list); -- -- ntmp = ntmp->next; -- -- active = td_status(ntd) & TD_CTRL_ACTIVE; -- -- ni++; -- } -- -- if (active && ni > i) { -- out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i); -- tmp = ntmp; -- td = ntd; -- i = ni; -- } -+ if (list_empty(&qh->queue)) { -+ out += sprintf(out, "%*s queue is empty\n", space, ""); -+ } else { -+ struct urb_priv *urbp = list_entry(qh->queue.next, -+ struct urb_priv, node); -+ struct uhci_td *td = list_entry(urbp->td_list.next, -+ struct uhci_td, list); -+ -+ if (cpu_to_le32(td->dma_handle) != (element & ~UHCI_PTR_BITS)) -+ out += sprintf(out, "%*s Element != First TD\n", -+ space, ""); -+ i = nurbs = 0; -+ list_for_each_entry(urbp, &qh->queue, node) { -+ if (++i <= 10) -+ out += uhci_show_urbp(urbp, out, -+ len - (out - buf), space + 2); -+ else -+ ++nurbs; - } -- -- prevactive = td_status(td) & TD_CTRL_ACTIVE; -- } -- -- if (list_empty(&urbp->queue_list) || urbp->queued) -- goto out; -- -- out += sprintf(out, "%*sQueued QHs:\n", -space, "--"); -- -- head = &urbp->queue_list; -- tmp = head->next; -- -- while (tmp != head) { -- struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, -- queue_list); -- tmp = tmp->next; -- -- out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space); -+ if (nurbs > 0) -+ out += sprintf(out, "%*s Skipped %d URBs\n", -+ space, "", nurbs); - } - --out: - return out - buf; - } - --#define show_frame_num() \ -- if (!shown) { \ -- shown = 1; \ -- out += sprintf(out, "- Frame %d\n", i); \ -- } -- - #ifdef CONFIG_PROC_FS - static const char * const qh_names[] = { -+ "skel_unlink_qh", "skel_iso_qh", - "skel_int128_qh", "skel_int64_qh", - "skel_int32_qh", "skel_int16_qh", - "skel_int8_qh", "skel_int4_qh", -@@ -206,12 +203,6 @@ static const char * const qh_names[] = { - "skel_bulk_qh", "skel_term_qh" - }; - --#define show_qh_name() \ -- if (!shown) { \ -- shown = 1; \ -- out += sprintf(out, "- %s\n", qh_names[i]); \ -- } -- - static int uhci_show_sc(int port, unsigned short status, char *buf, int len) - { - char *out = buf; -@@ -321,139 +312,29 @@ static int uhci_show_status(struct uhci_ - return out - buf; - } - --static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len) --{ -- struct list_head *tmp; -- char *out = buf; -- int count = 0; -- -- if (len < 200) -- return 0; -- -- out += sprintf(out, "urb_priv [%p] ", urbp); -- out += sprintf(out, "urb [%p] ", urbp->urb); -- out += sprintf(out, "qh [%p] ", urbp->qh); -- out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); -- out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); -- -- switch (usb_pipetype(urbp->urb->pipe)) { -- case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break; -- case PIPE_INTERRUPT: out += sprintf(out, "INT "); break; -- case PIPE_BULK: out += sprintf(out, "BLK "); break; -- case PIPE_CONTROL: out += sprintf(out, "CTL "); break; -- } -- -- out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : "")); -- out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : "")); -- -- if (urbp->urb->status != -EINPROGRESS) -- out += sprintf(out, "Status=%d ", urbp->urb->status); -- //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); -- -- count = 0; -- list_for_each(tmp, &urbp->td_list) -- count++; -- out += sprintf(out, "TDs=%d ",count); -- -- if (urbp->queued) -- out += sprintf(out, "queued\n"); -- else { -- count = 0; -- list_for_each(tmp, &urbp->queue_list) -- count++; -- out += sprintf(out, "queued URBs=%d\n", count); -- } -- -- return out - buf; --} -- --static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len) --{ -- char *out = buf; -- struct list_head *head, *tmp; -- int count; -- -- out += sprintf(out, "Main list URBs:"); -- if (list_empty(&uhci->urb_list)) -- out += sprintf(out, " Empty\n"); -- else { -- out += sprintf(out, "\n"); -- count = 0; -- head = &uhci->urb_list; -- tmp = head->next; -- while (tmp != head) { -- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); -- -- out += sprintf(out, " %d: ", ++count); -- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); -- tmp = tmp->next; -- } -- } -- -- out += sprintf(out, "Remove list URBs:"); -- if (list_empty(&uhci->urb_remove_list)) -- out += sprintf(out, " Empty\n"); -- else { -- out += sprintf(out, "\n"); -- count = 0; -- head = &uhci->urb_remove_list; -- tmp = head->next; -- while (tmp != head) { -- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); -- -- out += sprintf(out, " %d: ", ++count); -- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); -- tmp = tmp->next; -- } -- } -- -- out += sprintf(out, "Complete list URBs:"); -- if (list_empty(&uhci->complete_list)) -- out += sprintf(out, " Empty\n"); -- else { -- out += sprintf(out, "\n"); -- count = 0; -- head = &uhci->complete_list; -- tmp = head->next; -- while (tmp != head) { -- struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); -- -- out += sprintf(out, " %d: ", ++count); -- out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); -- tmp = tmp->next; -- } -- } -- -- return out - buf; --} -- - static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) - { -- unsigned long flags; - char *out = buf; - int i, j; - struct uhci_qh *qh; - struct uhci_td *td; - struct list_head *tmp, *head; - -- spin_lock_irqsave(&uhci->lock, flags); -- - out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); - out += sprintf(out, "HC status\n"); - out += uhci_show_status(uhci, out, len - (out - buf)); -+ if (debug <= 1) -+ return out - buf; - - out += sprintf(out, "Frame List\n"); - for (i = 0; i < UHCI_NUMFRAMES; ++i) { -- int shown = 0; - td = uhci->frame_cpu[i]; - if (!td) - continue; - -- if (td->dma_handle != (dma_addr_t)uhci->frame[i]) { -- show_frame_num(); -+ out += sprintf(out, "- Frame %d\n", i); \ -+ if (td->dma_handle != (dma_addr_t)uhci->frame[i]) - out += sprintf(out, " frame list does not match td->dma_handle!\n"); -- } -- show_frame_num(); - - head = &td->fl_list; - tmp = head; -@@ -467,14 +348,11 @@ static int uhci_sprint_schedule(struct u - out += sprintf(out, "Skeleton QHs\n"); - - for (i = 0; i < UHCI_NUM_SKELQH; ++i) { -- int shown = 0; -+ int cnt = 0; - - qh = uhci->skelqh[i]; -- -- if (debug > 1) { -- show_qh_name(); -- out += uhci_show_qh(qh, out, len - (out - buf), 4); -- } -+ out += sprintf(out, "- %s\n", qh_names[i]); \ -+ out += uhci_show_qh(qh, out, len - (out - buf), 4); - - /* Last QH is the Terminating QH, it's different */ - if (i == UHCI_NUM_SKELQH - 1) { -@@ -487,44 +365,27 @@ static int uhci_sprint_schedule(struct u - continue; - } - -- j = (i < 7) ? 7 : i+1; /* Next skeleton */ -- if (list_empty(&qh->list)) { -- if (i < UHCI_NUM_SKELQH - 1) { -- if (qh->link != -- (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) { -- show_qh_name(); -- out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); -- } -- } -- -- continue; -- } -- -- show_qh_name(); -- -- head = &qh->list; -+ j = (i < 9) ? 9 : i+1; /* Next skeleton */ -+ head = &qh->node; - tmp = head->next; - - while (tmp != head) { -- qh = list_entry(tmp, struct uhci_qh, list); -- -+ qh = list_entry(tmp, struct uhci_qh, node); - tmp = tmp->next; -- -- out += uhci_show_qh(qh, out, len - (out - buf), 4); -+ if (++cnt <= 10) -+ out += uhci_show_qh(qh, out, -+ len - (out - buf), 4); - } -+ if ((cnt -= 10) > 0) -+ out += sprintf(out, " Skipped %d QHs\n", cnt); - -- if (i < UHCI_NUM_SKELQH - 1) { -+ if (i > 1 && i < UHCI_NUM_SKELQH - 1) { - if (qh->link != - (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) - out += sprintf(out, " last QH not linked to next skeleton!\n"); - } - } - -- if (debug > 2) -- out += uhci_show_lists(uhci, out, len - (out - buf)); -- -- spin_unlock_irqrestore(&uhci->lock, flags); -- - return out - buf; - } - -@@ -541,6 +402,7 @@ static int uhci_debug_open(struct inode - struct uhci_hcd *uhci = inode->u.generic_ip; - struct uhci_debug *up; - int ret = -ENOMEM; -+ unsigned long flags; - - lock_kernel(); - up = kmalloc(sizeof(*up), GFP_KERNEL); -@@ -553,7 +415,9 @@ static int uhci_debug_open(struct inode - goto out; - } - -+ spin_lock_irqsave(&uhci->lock, flags); - up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); -+ spin_unlock_irqrestore(&uhci->lock, flags); - - file->private_data = up; - ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.c -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.c -@@ -54,7 +54,7 @@ - /* - * Version Information - */ --#define DRIVER_VERSION "v2.3" -+#define DRIVER_VERSION "v3.0" - #define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ - Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ - Alan Stern" -@@ -489,15 +489,11 @@ static int uhci_start(struct usb_hcd *hc - uhci->fsbrtimeout = 0; - - spin_lock_init(&uhci->lock); -- INIT_LIST_HEAD(&uhci->qh_remove_list); - - INIT_LIST_HEAD(&uhci->td_remove_list); -- -- INIT_LIST_HEAD(&uhci->urb_remove_list); -- - INIT_LIST_HEAD(&uhci->urb_list); -- - INIT_LIST_HEAD(&uhci->complete_list); -+ INIT_LIST_HEAD(&uhci->idle_qh_list); - - init_waitqueue_head(&uhci->waitqh); - -@@ -540,7 +536,7 @@ static int uhci_start(struct usb_hcd *hc - } - - for (i = 0; i < UHCI_NUM_SKELQH; i++) { -- uhci->skelqh[i] = uhci_alloc_qh(uhci); -+ uhci->skelqh[i] = uhci_alloc_qh(uhci, NULL, NULL); - if (!uhci->skelqh[i]) { - dev_err(uhci_dev(uhci), "unable to allocate QH\n"); - goto err_alloc_skelqh; -@@ -557,13 +553,17 @@ static int uhci_start(struct usb_hcd *hc - uhci->skel_int16_qh->link = - uhci->skel_int8_qh->link = - uhci->skel_int4_qh->link = -- uhci->skel_int2_qh->link = -- cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; -- uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH; -- -- uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; -- uhci->skel_fs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH; -- uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH; -+ uhci->skel_int2_qh->link = UHCI_PTR_QH | -+ cpu_to_le32(uhci->skel_int1_qh->dma_handle); -+ -+ uhci->skel_int1_qh->link = UHCI_PTR_QH | -+ cpu_to_le32(uhci->skel_ls_control_qh->dma_handle); -+ uhci->skel_ls_control_qh->link = UHCI_PTR_QH | -+ cpu_to_le32(uhci->skel_fs_control_qh->dma_handle); -+ uhci->skel_fs_control_qh->link = UHCI_PTR_QH | -+ cpu_to_le32(uhci->skel_bulk_qh->dma_handle); -+ uhci->skel_bulk_qh->link = UHCI_PTR_QH | -+ cpu_to_le32(uhci->skel_term_qh->dma_handle); - - /* This dummy TD is to work around a bug in Intel PIIX controllers */ - uhci_fill_td(uhci->term_td, 0, uhci_explen(0) | -@@ -589,15 +589,15 @@ static int uhci_start(struct usb_hcd *hc - - /* - * ffs (Find First bit Set) does exactly what we need: -- * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6], -- * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc. -- * ffs > 6 => not on any high-period queue, so use -- * skel_int1_qh = skelqh[7]. -+ * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], -+ * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. -+ * ffs >= 7 => not on any high-period queue, so use -+ * skel_int1_qh = skelqh[9]. - * Add UHCI_NUMFRAMES to insure at least one bit is set. - */ -- irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES); -- if (irq < 0) -- irq = 7; -+ irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES); -+ if (irq <= 1) -+ irq = 9; - - /* Only place we don't use the frame list routines */ - uhci->frame[i] = UHCI_PTR_QH | -@@ -767,13 +767,30 @@ static int uhci_resume(struct usb_hcd *h - } - #endif - --/* Wait until all the URBs for a particular device/endpoint are gone */ -+/* Wait until a particular device/endpoint's QH is idle, and free it */ - static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, -- struct usb_host_endpoint *ep) -+ struct usb_host_endpoint *hep) - { - struct uhci_hcd *uhci = hcd_to_uhci(hcd); -+ struct uhci_qh *qh; -+ -+ spin_lock_irq(&uhci->lock); -+ qh = (struct uhci_qh *) hep->hcpriv; -+ if (qh == NULL) -+ goto done; - -- wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list)); -+ while (qh->state != QH_STATE_IDLE) { -+ ++uhci->num_waiting; -+ spin_unlock_irq(&uhci->lock); -+ wait_event_interruptible(uhci->waitqh, -+ qh->state == QH_STATE_IDLE); -+ spin_lock_irq(&uhci->lock); -+ --uhci->num_waiting; -+ } -+ -+ uhci_free_qh(uhci, qh); -+done: -+ spin_unlock_irq(&uhci->lock); - } - - static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) ---- gregkh-2.6.orig/drivers/usb/host/uhci-hcd.h -+++ gregkh-2.6/drivers/usb/host/uhci-hcd.h -@@ -28,8 +28,9 @@ - #define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ - #define USBSTS_ERROR 0x0002 /* Interrupt due to error */ - #define USBSTS_RD 0x0004 /* Resume Detect */ --#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ --#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -+#define USBSTS_HSE 0x0008 /* Host System Error: PCI problems */ -+#define USBSTS_HCPE 0x0010 /* Host Controller Process Error: -+ * the schedule is buggy */ - #define USBSTS_HCH 0x0020 /* HC Halted */ - - /* Interrupt enable register */ -@@ -47,7 +48,8 @@ - /* USB port status and control registers */ - #define USBPORTSC1 16 - #define USBPORTSC2 18 --#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -+#define USBPORTSC_CCS 0x0001 /* Current Connect Status -+ * ("device present") */ - #define USBPORTSC_CSC 0x0002 /* Connect Status Change */ - #define USBPORTSC_PE 0x0004 /* Port Enable */ - #define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -@@ -71,15 +73,16 @@ - #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ - #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ - --#define UHCI_PTR_BITS cpu_to_le32(0x000F) --#define UHCI_PTR_TERM cpu_to_le32(0x0001) --#define UHCI_PTR_QH cpu_to_le32(0x0002) --#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) --#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) -+#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) -+#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) -+#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) -+#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) -+#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) - - #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ - #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ --#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ -+#define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames -+ * can be scheduled */ - - - /* -@@ -87,38 +90,54 @@ - */ - - /* -- * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is -- * used with one URB, and qh->element (updated by the HC) is either: -- * - the next unprocessed TD for the URB, or -- * - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or -- * - the QH for the next URB queued to the same endpoint. -+ * One role of a QH is to hold a queue of TDs for some endpoint. One QH goes -+ * with each endpoint, and qh->element (updated by the HC) is either: -+ * - the next unprocessed TD in the endpoint's queue, or -+ * - UHCI_PTR_TERM (when there's no more traffic for this endpoint). - * - * The other role of a QH is to serve as a "skeleton" framelist entry, so we - * can easily splice a QH for some endpoint into the schedule at the right - * place. Then qh->element is UHCI_PTR_TERM. - * -- * In the frame list, qh->link maintains a list of QHs seen by the HC: -+ * In the schedule, qh->link maintains a list of QHs seen by the HC: - * skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ... -- */ -+ * -+ * qh->node is the software equivalent of qh->link. The differences -+ * are that the software list is doubly-linked and QHs in the UNLINKING -+ * state are on the software list but not the hardware schedule. -+ * -+ * For bookkeeping purposes we maintain QHs even for Isochronous endpoints, -+ * but they never get added to the hardware schedule. -+ */ -+#define QH_STATE_IDLE 1 /* QH is not being used */ -+#define QH_STATE_UNLINKING 2 /* QH has been removed from the -+ * schedule but the hardware may -+ * still be using it */ -+#define QH_STATE_ACTIVE 3 /* QH is on the schedule */ -+ - struct uhci_qh { - /* Hardware fields */ -- __le32 link; /* Next queue */ -- __le32 element; /* Queue element pointer */ -+ __le32 link; /* Next QH in the schedule */ -+ __le32 element; /* Queue element (TD) pointer */ - - /* Software fields */ - dma_addr_t dma_handle; - -- struct urb_priv *urbp; -+ struct list_head node; /* Node in the list of QHs */ -+ struct usb_host_endpoint *hep; /* Endpoint information */ -+ struct usb_device *udev; -+ struct list_head queue; /* Queue of urbps for this QH */ -+ struct uhci_qh *skel; /* Skeleton for this QH */ - -- struct list_head list; -- struct list_head remove_list; -+ unsigned int unlink_frame; /* When the QH was unlinked */ -+ int state; /* QH_STATE_xxx; see above */ - } __attribute__((aligned(16))); - - /* - * We need a special accessor for the element pointer because it is - * subject to asynchronous updates by the controller. - */ --static __le32 inline qh_element(struct uhci_qh *qh) { -+static inline __le32 qh_element(struct uhci_qh *qh) { - __le32 element = qh->element; - - barrier(); -@@ -149,11 +168,13 @@ static __le32 inline qh_element(struct u - #define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ - - #define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ -- TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) -+ TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \ -+ TD_CTRL_BITSTUFF) - - #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) - #define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000) --#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ -+#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & \ -+ TD_CTRL_ACTLEN_MASK) /* 1-based */ - - /* - * for TD <info>: (a.k.a. Token) -@@ -163,7 +184,7 @@ static __le32 inline qh_element(struct u - #define TD_TOKEN_TOGGLE_SHIFT 19 - #define TD_TOKEN_TOGGLE (1 << 19) - #define TD_TOKEN_EXPLEN_SHIFT 21 --#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ -+#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n-1 */ - #define TD_TOKEN_PID_MASK 0xFF - - #define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \ -@@ -187,7 +208,7 @@ static __le32 inline qh_element(struct u - * sw space after the TD entry. - * - * td->link points to either another TD (not necessarily for the same urb or -- * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs). -+ * even the same endpoint), or nothing (PTR_TERM), or a QH. - */ - struct uhci_td { - /* Hardware fields */ -@@ -210,7 +231,7 @@ struct uhci_td { - * We need a special accessor for the control/status word because it is - * subject to asynchronous updates by the controller. - */ --static u32 inline td_status(struct uhci_td *td) { -+static inline u32 td_status(struct uhci_td *td) { - __le32 status = td->status; - - barrier(); -@@ -223,17 +244,14 @@ static u32 inline td_status(struct uhci_ - */ - - /* -- * The UHCI driver places Interrupt, Control and Bulk into QHs both -- * to group together TDs for one transfer, and also to facilitate queuing -- * of URBs. To make it easy to insert entries into the schedule, we have -- * a skeleton of QHs for each predefined Interrupt latency, low-speed -- * control, full-speed control and terminating QH (see explanation for -- * the terminating QH below). -+ * The UHCI driver uses QHs with Interrupt, Control and Bulk URBs for -+ * automatic queuing. To make it easy to insert entries into the schedule, -+ * we have a skeleton of QHs for each predefined Interrupt latency, -+ * low-speed control, full-speed control, bulk, and terminating QH -+ * (see explanation for the terminating QH below). - * - * When we want to add a new QH, we add it to the end of the list for the -- * skeleton QH. -- * -- * For instance, the queue can look like this: -+ * skeleton QH. For instance, the schedule list can look like this: - * - * skel int128 QH - * dev 1 interrupt QH -@@ -256,26 +274,31 @@ static u32 inline td_status(struct uhci_ - * - To loop back to the full-speed control queue for full-speed bandwidth - * reclamation. - * -- * Isochronous transfers are stored before the start of the skeleton -- * schedule and don't use QHs. While the UHCI spec doesn't forbid the -- * use of QHs for Isochronous, it doesn't use them either. And the spec -- * says that queues never advance on an error completion status, which -- * makes them totally unsuitable for Isochronous transfers. -- */ -- --#define UHCI_NUM_SKELQH 12 --#define skel_int128_qh skelqh[0] --#define skel_int64_qh skelqh[1] --#define skel_int32_qh skelqh[2] --#define skel_int16_qh skelqh[3] --#define skel_int8_qh skelqh[4] --#define skel_int4_qh skelqh[5] --#define skel_int2_qh skelqh[6] --#define skel_int1_qh skelqh[7] --#define skel_ls_control_qh skelqh[8] --#define skel_fs_control_qh skelqh[9] --#define skel_bulk_qh skelqh[10] --#define skel_term_qh skelqh[11] -+ * There's a special skeleton QH for Isochronous QHs. It never appears -+ * on the schedule, and Isochronous TDs go on the schedule before the -+ * the skeleton QHs. The hardware accesses them directly rather than -+ * through their QH, which is used only for bookkeeping purposes. -+ * While the UHCI spec doesn't forbid the use of QHs for Isochronous, -+ * it doesn't use them either. And the spec says that queues never -+ * advance on an error completion status, which makes them totally -+ * unsuitable for Isochronous transfers. -+ */ -+ -+#define UHCI_NUM_SKELQH 14 -+#define skel_unlink_qh skelqh[0] -+#define skel_iso_qh skelqh[1] -+#define skel_int128_qh skelqh[2] -+#define skel_int64_qh skelqh[3] -+#define skel_int32_qh skelqh[4] -+#define skel_int16_qh skelqh[5] -+#define skel_int8_qh skelqh[6] -+#define skel_int4_qh skelqh[7] -+#define skel_int2_qh skelqh[8] -+#define skel_int1_qh skelqh[9] -+#define skel_ls_control_qh skelqh[10] -+#define skel_fs_control_qh skelqh[11] -+#define skel_bulk_qh skelqh[12] -+#define skel_term_qh skelqh[13] - - /* - * Search tree for determining where <interval> fits in the skelqh[] -@@ -293,21 +316,21 @@ static inline int __interval_to_skel(int - if (interval < 16) { - if (interval < 4) { - if (interval < 2) -- return 7; /* int1 for 0-1 ms */ -- return 6; /* int2 for 2-3 ms */ -+ return 9; /* int1 for 0-1 ms */ -+ return 8; /* int2 for 2-3 ms */ - } - if (interval < 8) -- return 5; /* int4 for 4-7 ms */ -- return 4; /* int8 for 8-15 ms */ -+ return 7; /* int4 for 4-7 ms */ -+ return 6; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) -- return 3; /* int16 for 16-31 ms */ -- return 2; /* int32 for 32-63 ms */ -+ return 5; /* int16 for 16-31 ms */ -+ return 4; /* int32 for 32-63 ms */ - } - if (interval < 128) -- return 1; /* int64 for 64-127 ms */ -- return 0; /* int128 for 128-255 ms (Max.) */ -+ return 3; /* int64 for 64-127 ms */ -+ return 2; /* int128 for 128-255 ms (Max.) */ - } - - -@@ -363,12 +386,12 @@ struct uhci_hcd { - - spinlock_t lock; - -- dma_addr_t frame_dma_handle; /* Hardware frame list */ -+ dma_addr_t frame_dma_handle; /* Hardware frame list */ - __le32 *frame; -- void **frame_cpu; /* CPU's frame list */ -+ void **frame_cpu; /* CPU's frame list */ - -- int fsbr; /* Full-speed bandwidth reclamation */ -- unsigned long fsbrtimeout; /* FSBR delay */ -+ int fsbr; /* Full-speed bandwidth reclamation */ -+ unsigned long fsbrtimeout; /* FSBR delay */ - - enum uhci_rh_state rh_state; - unsigned long auto_stop_time; /* When to AUTO_STOP */ -@@ -392,24 +415,19 @@ struct uhci_hcd { - /* Main list of URBs currently controlled by this HC */ - struct list_head urb_list; - -- /* List of QHs that are done, but waiting to be unlinked (race) */ -- struct list_head qh_remove_list; -- unsigned int qh_remove_age; /* Age in frames */ -- - /* List of TDs that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; - unsigned int td_remove_age; /* Age in frames */ - -- /* List of asynchronously unlinked URBs */ -- struct list_head urb_remove_list; -- unsigned int urb_remove_age; /* Age in frames */ -- - /* List of URBs awaiting completion callback */ - struct list_head complete_list; - -+ struct list_head idle_qh_list; /* Where the idle QHs live */ -+ - int rh_numports; /* Number of root-hub ports */ - - wait_queue_head_t waitqh; /* endpoint_disable waiters */ -+ int num_waiting; /* Number of waiters */ - }; - - /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ -@@ -430,22 +448,19 @@ static inline struct usb_hcd *uhci_to_hc - */ - struct urb_priv { - struct list_head urb_list; -+ struct list_head node; /* Node in the QH's urbp list */ - - struct urb *urb; - - struct uhci_qh *qh; /* QH for this URB */ - struct list_head td_list; - -- unsigned fsbr : 1; /* URB turned on FSBR */ -- unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ -- unsigned queued : 1; /* QH was queued (not linked in) */ -- unsigned short_control_packet : 1; /* If we get a short packet during */ -- /* a control transfer, retrigger */ -- /* the status phase */ -- - unsigned long fsbrtime; /* In jiffies */ - -- struct list_head queue_list; -+ unsigned fsbr : 1; /* URB turned on FSBR */ -+ unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ -+ unsigned short_transfer : 1; /* URB got a short transfer, no -+ * need to rescan */ - }; - - ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -13,13 +13,9 @@ - * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface - * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). - * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) -- * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu -+ * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu - */ - --static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); --static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); --static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); --static void uhci_free_pending_qhs(struct uhci_hcd *uhci); - static void uhci_free_pending_tds(struct uhci_hcd *uhci); - - /* -@@ -30,7 +26,7 @@ static void uhci_free_pending_tds(struct - * games with the FSBR code to make sure we get the correct order in all - * the cases. I don't think it's worth the effort - */ --static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) -+static void uhci_set_next_interrupt(struct uhci_hcd *uhci) - { - if (uhci->is_stopped) - mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); -@@ -42,12 +38,6 @@ static inline void uhci_clear_next_inter - uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); - } - --static inline void uhci_moveto_complete(struct uhci_hcd *uhci, -- struct urb_priv *urbp) --{ -- list_move_tail(&urbp->urb_list, &uhci->complete_list); --} -- - static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) - { - dma_addr_t dma_handle; -@@ -71,6 +61,18 @@ static struct uhci_td *uhci_alloc_td(str - return td; - } - -+static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) -+{ -+ if (!list_empty(&td->list)) -+ dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); -+ if (!list_empty(&td->remove_list)) -+ dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); -+ if (!list_empty(&td->fl_list)) -+ dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); -+ -+ dma_pool_free(uhci->td_pool, td, td->dma_handle); -+} -+ - static inline void uhci_fill_td(struct uhci_td *td, u32 status, - u32 token, u32 buffer) - { -@@ -82,7 +84,8 @@ static inline void uhci_fill_td(struct u - /* - * We insert Isochronous URBs directly into the frame list at the beginning - */ --static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) -+static inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci, -+ struct uhci_td *td, unsigned framenum) - { - framenum &= (UHCI_NUMFRAMES - 1); - -@@ -108,7 +111,7 @@ static void uhci_insert_td_frame_list(st - } - } - --static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci, -+static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, - struct uhci_td *td) - { - /* If it's not inserted, don't remove it */ -@@ -139,48 +142,68 @@ static inline void uhci_remove_td_frame_ - td->frame = -1; - } - --static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) -+/* -+ * Remove all the TDs for an Isochronous URB from the frame list -+ */ -+static void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) - { - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - struct uhci_td *td; - - list_for_each_entry(td, &urbp->td_list, list) -- uhci_remove_td_frame_list(uhci, td); -+ uhci_remove_td_from_frame_list(uhci, td); - wmb(); - } - - /* -- * Inserts a td list into qh. -+ * Remove an URB's TDs from the hardware schedule - */ --static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth) -+static void uhci_remove_tds_from_schedule(struct uhci_hcd *uhci, -+ struct urb *urb, int status) - { -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; -- struct uhci_td *td; -- __le32 *plink; -+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - -- /* Ordering isn't important here yet since the QH hasn't been */ -- /* inserted into the schedule yet */ -- plink = &qh->element; -- list_for_each_entry(td, &urbp->td_list, list) { -- *plink = cpu_to_le32(td->dma_handle) | breadth; -- plink = &td->link; -+ /* Isochronous TDs get unlinked directly from the frame list */ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ uhci_unlink_isochronous_tds(uhci, urb); -+ return; - } -- *plink = UHCI_PTR_TERM; --} - --static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) --{ -- if (!list_empty(&td->list)) -- dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); -- if (!list_empty(&td->remove_list)) -- dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); -- if (!list_empty(&td->fl_list)) -- dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); -- -- dma_pool_free(uhci->td_pool, td, td->dma_handle); -+ /* If the URB isn't first on its queue, adjust the link pointer -+ * of the last TD in the previous URB. */ -+ if (urbp->node.prev != &urbp->qh->queue) { -+ struct urb_priv *purbp; -+ struct uhci_td *ptd, *ltd; -+ -+ if (status == -EINPROGRESS) -+ status = 0; -+ purbp = list_entry(urbp->node.prev, struct urb_priv, node); -+ ptd = list_entry(purbp->td_list.prev, struct uhci_td, -+ list); -+ ltd = list_entry(urbp->td_list.prev, struct uhci_td, -+ list); -+ ptd->link = ltd->link; -+ } -+ -+ /* If the URB completed with an error, then the QH element certainly -+ * points to one of the URB's TDs. If it completed normally then -+ * the QH element has certainly moved on to the next URB. And if -+ * the URB is still in progress then it must have been dequeued. -+ * The QH element either hasn't reached it yet or is somewhere in -+ * the middle. If the URB wasn't first we can assume that it -+ * hasn't started yet (see above): Otherwise all the preceding URBs -+ * would have completed and been removed from the queue, so this one -+ * _would_ be first. -+ * -+ * If the QH element is inside this URB, clear it. It will be -+ * set properly when the QH is activated. -+ */ -+ if (status < 0) -+ urbp->qh->element = UHCI_PTR_TERM; - } - --static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci) -+static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, -+ struct usb_device *udev, struct usb_host_endpoint *hep) - { - dma_addr_t dma_handle; - struct uhci_qh *qh; -@@ -194,256 +217,120 @@ static struct uhci_qh *uhci_alloc_qh(str - qh->element = UHCI_PTR_TERM; - qh->link = UHCI_PTR_TERM; - -- qh->urbp = NULL; -- -- INIT_LIST_HEAD(&qh->list); -- INIT_LIST_HEAD(&qh->remove_list); -+ INIT_LIST_HEAD(&qh->queue); -+ INIT_LIST_HEAD(&qh->node); - -+ if (udev) { /* Normal QH */ -+ qh->state = QH_STATE_IDLE; -+ qh->hep = hep; -+ qh->udev = udev; -+ hep->hcpriv = qh; -+ usb_get_dev(udev); -+ -+ } else { /* Skeleton QH */ -+ qh->state = QH_STATE_ACTIVE; -+ qh->udev = NULL; -+ } - return qh; - } - - static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) - { -- if (!list_empty(&qh->list)) -+ WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); -+ if (!list_empty(&qh->queue)) - dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh); -- if (!list_empty(&qh->remove_list)) -- dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); - -+ list_del(&qh->node); -+ if (qh->udev) { -+ qh->hep->hcpriv = NULL; -+ usb_put_dev(qh->udev); -+ } - dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); - } - - /* -- * Append this urb's qh after the last qh in skelqh->list -- * -- * Note that urb_priv.queue_list doesn't have a separate queue head; -- * it's a ring with every element "live". -+ * Put a QH on the schedule in both hardware and software - */ --static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) -+static void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) - { -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; -- struct urb_priv *turbp; -- struct uhci_qh *lqh; -+ struct uhci_qh *pqh; - -- /* Grab the last QH */ -- lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); -+ WARN_ON(list_empty(&qh->queue)); - -- /* Point to the next skelqh */ -- urbp->qh->link = lqh->link; -- wmb(); /* Ordering is important */ -+ /* Set the element pointer if it isn't set already. -+ * This isn't needed for Isochronous queues, but it doesn't hurt. */ -+ if (qh_element(qh) == UHCI_PTR_TERM) { -+ struct urb_priv *urbp = list_entry(qh->queue.next, -+ struct urb_priv, node); -+ struct uhci_td *td = list_entry(urbp->td_list.next, -+ struct uhci_td, list); - -- /* -- * Patch QHs for previous endpoint's queued URBs? HC goes -- * here next, not to the next skelqh it now points to. -- * -- * lqh --> td ... --> qh ... --> td --> qh ... --> td -- * | | | -- * v v v -- * +<----------------+-----------------+ -- * v -- * newqh --> td ... --> td -- * | -- * v -- * ... -- * -- * The HC could see (and use!) any of these as we write them. -- */ -- lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; -- if (lqh->urbp) { -- list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list) -- turbp->qh->link = lqh->link; -+ qh->element = cpu_to_le32(td->dma_handle); - } - -- list_add_tail(&urbp->qh->list, &skelqh->list); -+ if (qh->state == QH_STATE_ACTIVE) -+ return; -+ qh->state = QH_STATE_ACTIVE; -+ -+ /* Move the QH from its old list to the end of the appropriate -+ * skeleton's list */ -+ list_move_tail(&qh->node, &qh->skel->node); -+ -+ /* Link it into the schedule */ -+ pqh = list_entry(qh->node.prev, struct uhci_qh, node); -+ qh->link = pqh->link; -+ wmb(); -+ pqh->link = UHCI_PTR_QH | cpu_to_le32(qh->dma_handle); - } - - /* -- * Start removal of QH from schedule; it finishes next frame. -- * TDs should be unlinked before this is called. -+ * Take a QH off the hardware schedule - */ --static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -+static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) - { - struct uhci_qh *pqh; -- __le32 newlink; - -- if (!qh) -+ if (qh->state == QH_STATE_UNLINKING) - return; -+ WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev); -+ qh->state = QH_STATE_UNLINKING; - -- /* -- * Only go through the hoops if it's actually linked in -- */ -- if (!list_empty(&qh->list)) { -- -- /* If our queue is nonempty, make the next URB the head */ -- if (!list_empty(&qh->urbp->queue_list)) { -- struct urb_priv *nurbp; -- -- nurbp = list_entry(qh->urbp->queue_list.next, -- struct urb_priv, queue_list); -- nurbp->queued = 0; -- list_add(&nurbp->qh->list, &qh->list); -- newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; -- } else -- newlink = qh->link; -- -- /* Fix up the previous QH's queue to link to either -- * the new head of this queue or the start of the -- * next endpoint's queue. */ -- pqh = list_entry(qh->list.prev, struct uhci_qh, list); -- pqh->link = newlink; -- if (pqh->urbp) { -- struct urb_priv *turbp; -- -- list_for_each_entry(turbp, &pqh->urbp->queue_list, -- queue_list) -- turbp->qh->link = newlink; -- } -- wmb(); -- -- /* Leave qh->link in case the HC is on the QH now, it will */ -- /* continue the rest of the schedule */ -- qh->element = UHCI_PTR_TERM; -- -- list_del_init(&qh->list); -- } -- -- list_del_init(&qh->urbp->queue_list); -- qh->urbp = NULL; -+ /* Unlink the QH from the schedule and record when we did it */ -+ pqh = list_entry(qh->node.prev, struct uhci_qh, node); -+ pqh->link = qh->link; -+ mb(); - - uhci_get_current_frame_number(uhci); -- if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) { -- uhci_free_pending_qhs(uhci); -- uhci->qh_remove_age = uhci->frame_number; -- } -+ qh->unlink_frame = uhci->frame_number; - -- /* Check to see if the remove list is empty. Set the IOC bit */ -- /* to force an interrupt so we can remove the QH */ -- if (list_empty(&uhci->qh_remove_list)) -+ /* Force an interrupt so we know when the QH is fully unlinked */ -+ if (list_empty(&uhci->skel_unlink_qh->node)) - uhci_set_next_interrupt(uhci); - -- list_add(&qh->remove_list, &uhci->qh_remove_list); --} -- --static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) --{ -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; -- struct uhci_td *td; -- -- list_for_each_entry(td, &urbp->td_list, list) { -- if (toggle) -- td->token |= cpu_to_le32(TD_TOKEN_TOGGLE); -- else -- td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE); -- -- toggle ^= 1; -- } -- -- return toggle; --} -- --/* This function will append one URB's QH to another URB's QH. This is for */ --/* queuing interrupt, control or bulk transfers */ --static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb) --{ -- struct urb_priv *eurbp, *urbp, *furbp, *lurbp; -- struct uhci_td *lltd; -- -- eurbp = eurb->hcpriv; -- urbp = urb->hcpriv; -- -- /* Find the first URB in the queue */ -- furbp = eurbp; -- if (eurbp->queued) { -- list_for_each_entry(furbp, &eurbp->queue_list, queue_list) -- if (!furbp->queued) -- break; -- } -- -- lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); -- -- lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); -- -- /* Control transfers always start with toggle 0 */ -- if (!usb_pipecontrol(urb->pipe)) -- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe), -- uhci_fixup_toggle(urb, -- uhci_toggle(td_token(lltd)) ^ 1)); -- -- /* All qhs in the queue need to link to the next queue */ -- urbp->qh->link = eurbp->qh->link; -- -- wmb(); /* Make sure we flush everything */ -- -- lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; -- -- list_add_tail(&urbp->queue_list, &furbp->queue_list); -- -- urbp->queued = 1; -+ /* Move the QH from its old list to the end of the unlinking list */ -+ list_move_tail(&qh->node, &uhci->skel_unlink_qh->node); - } - --static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) -+/* -+ * When we and the controller are through with a QH, it becomes IDLE. -+ * This happens when a QH has been off the schedule (on the unlinking -+ * list) for more than one frame, or when an error occurs while adding -+ * the first URB onto a new QH. -+ */ -+static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) - { -- struct urb_priv *urbp, *nurbp, *purbp, *turbp; -- struct uhci_td *pltd; -- unsigned int toggle; -- -- urbp = urb->hcpriv; -- -- if (list_empty(&urbp->queue_list)) -- return; -- -- nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); -- -- /* -- * Fix up the toggle for the following URBs in the queue. -- * Only needed for bulk and interrupt: control and isochronous -- * endpoints don't propagate toggles between messages. -- */ -- if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) { -- if (!urbp->queued) -- /* We just set the toggle in uhci_unlink_generic */ -- toggle = usb_gettoggle(urb->dev, -- usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe)); -- else { -- /* If we're in the middle of the queue, grab the */ -- /* toggle from the TD previous to us */ -- purbp = list_entry(urbp->queue_list.prev, -- struct urb_priv, queue_list); -- pltd = list_entry(purbp->td_list.prev, -- struct uhci_td, list); -- toggle = uhci_toggle(td_token(pltd)) ^ 1; -- } -- -- list_for_each_entry(turbp, &urbp->queue_list, queue_list) { -- if (!turbp->queued) -- break; -- toggle = uhci_fixup_toggle(turbp->urb, toggle); -- } -- -- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -- usb_pipeout(urb->pipe), toggle); -- } -+ WARN_ON(qh->state == QH_STATE_ACTIVE); - -- if (urbp->queued) { -- /* We're somewhere in the middle (or end). The case where -- * we're at the head is handled in uhci_remove_qh(). */ -- purbp = list_entry(urbp->queue_list.prev, struct urb_priv, -- queue_list); -- -- pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); -- if (nurbp->queued) -- pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; -- else -- /* The next URB happens to be the beginning, so */ -- /* we're the last, end the chain */ -- pltd->link = UHCI_PTR_TERM; -- } -+ list_move(&qh->node, &uhci->idle_qh_list); -+ qh->state = QH_STATE_IDLE; - -- /* urbp->queue_list is handled in uhci_remove_qh() */ -+ /* If anyone is waiting for a QH to become idle, wake them up */ -+ if (uhci->num_waiting) -+ wake_up_all(&uhci->waitqh); - } - --static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb) -+static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, -+ struct urb *urb) - { - struct urb_priv *urbp; - -@@ -453,17 +340,14 @@ static struct urb_priv *uhci_alloc_urb_p - - memset((void *)urbp, 0, sizeof(*urbp)); - -- urbp->fsbrtime = jiffies; - urbp->urb = urb; -+ urb->hcpriv = urbp; -+ urbp->fsbrtime = jiffies; - -+ INIT_LIST_HEAD(&urbp->node); - INIT_LIST_HEAD(&urbp->td_list); -- INIT_LIST_HEAD(&urbp->queue_list); - INIT_LIST_HEAD(&urbp->urb_list); - -- list_add_tail(&urbp->urb_list, &uhci->urb_list); -- -- urb->hcpriv = urbp; -- - return urbp; - } - -@@ -482,18 +366,17 @@ static void uhci_remove_td_from_urb(stru - list_del_init(&td->list); - } - --static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) -+static void uhci_free_urb_priv(struct uhci_hcd *uhci, -+ struct urb_priv *urbp) - { - struct uhci_td *td, *tmp; -- struct urb_priv *urbp; -- -- urbp = (struct urb_priv *)urb->hcpriv; -- if (!urbp) -- return; - - if (!list_empty(&urbp->urb_list)) -- dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " -- "or uhci->remove_list!\n", urb); -+ dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list!\n", -+ urbp->urb); -+ if (!list_empty(&urbp->node)) -+ dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n", -+ urbp->urb); - - uhci_get_current_frame_number(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { -@@ -502,7 +385,7 @@ static void uhci_destroy_urb_priv(struct - } - - /* Check to see if the remove list is empty. Set the IOC bit */ -- /* to force an interrupt so we can remove the TDs*/ -+ /* to force an interrupt so we can remove the TDs. */ - if (list_empty(&uhci->td_remove_list)) - uhci_set_next_interrupt(uhci); - -@@ -511,7 +394,7 @@ static void uhci_destroy_urb_priv(struct - list_add(&td->remove_list, &uhci->td_remove_list); - } - -- urb->hcpriv = NULL; -+ urbp->urb->hcpriv = NULL; - kmem_cache_free(uhci_up_cachep, urbp); - } - -@@ -568,17 +451,82 @@ static int uhci_map_status(int status, i - } - - /* -+ * Fix up the data toggles for URBs in a queue, when one of them -+ * terminates early (short transfer, error, or dequeued). -+ */ -+static void uhci_fixup_toggles(struct urb *urb) -+{ -+ struct list_head *head; -+ struct uhci_td *td; -+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; -+ int prevactive = 0; -+ unsigned int toggle = 0; -+ struct urb_priv *turbp, *list_end; -+ -+ /* -+ * We need to find out what the last successful toggle was so -+ * we can update the data toggles for the following transfers. -+ * -+ * There are 2 ways the last successful completed TD is found: -+ * -+ * 1) The TD is NOT active and the actual length < expected length -+ * 2) The TD is NOT active and it's the last TD in the chain -+ * -+ * and a third way the first uncompleted TD is found: -+ * -+ * 3) The TD is active and the previous TD is NOT active -+ */ -+ head = &urbp->td_list; -+ list_for_each_entry(td, head, list) { -+ unsigned int ctrlstat = td_status(td); -+ -+ if (!(ctrlstat & TD_CTRL_ACTIVE) && -+ (uhci_actual_length(ctrlstat) < -+ uhci_expected_length(td_token(td)) || -+ td->list.next == head)) -+ toggle = uhci_toggle(td_token(td)) ^ 1; -+ else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) -+ toggle = uhci_toggle(td_token(td)); -+ -+ prevactive = ctrlstat & TD_CTRL_ACTIVE; -+ } -+ -+ /* -+ * Fix up the toggle for the following URBs in the queue. -+ * -+ * We can stop as soon as we find an URB with toggles set correctly, -+ * because then all the following URBs will be correct also. -+ */ -+ list_end = list_entry(&urbp->qh->queue, struct urb_priv, node); -+ turbp = urbp; -+ while ((turbp = list_entry(turbp->node.next, struct urb_priv, node)) -+ != list_end) { -+ td = list_entry(turbp->td_list.next, struct uhci_td, list); -+ if (uhci_toggle(td_token(td)) == toggle) -+ return; -+ -+ list_for_each_entry(td, &turbp->td_list, list) { -+ td->token ^= __constant_cpu_to_le32(TD_TOKEN_TOGGLE); -+ toggle ^= 1; -+ } -+ } -+ -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe), toggle); -+} -+ -+/* - * Control transfers - */ --static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -+static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; -- struct uhci_qh *qh, *skelqh; - unsigned long destination, status; -- int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); - int len = urb->transfer_buffer_length; - dma_addr_t data = urb->transfer_dma; -+ __le32 *plink; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; -@@ -597,7 +545,8 @@ static int uhci_submit_control(struct uh - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(8), -- urb->setup_dma); -+ urb->setup_dma); -+ plink = &td->link; - - /* - * If direction is "send", change the packet ID from SETUP (0x2D) -@@ -615,21 +564,20 @@ static int uhci_submit_control(struct uh - * Build the DATA TDs - */ - while (len > 0) { -- int pktsze = len; -- -- if (pktsze > maxsze) -- pktsze = maxsze; -+ int pktsze = min(len, maxsze); - - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; -+ *plink = cpu_to_le32(td->dma_handle); - - /* Alternate Data0/1 (start with Data1) */ - destination ^= TD_TOKEN_TOGGLE; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze), -- data); -+ data); -+ plink = &td->link; - - data += pktsze; - len -= pktsze; -@@ -641,6 +589,7 @@ static int uhci_submit_control(struct uh - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; -+ *plink = cpu_to_le32(td->dma_handle); - - /* - * It's IN if the pipe is an output pipe or we're not expecting -@@ -658,16 +607,7 @@ static int uhci_submit_control(struct uh - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status | TD_CTRL_IOC, -- destination | uhci_explen(0), 0); -- -- qh = uhci_alloc_qh(uhci); -- if (!qh) -- return -ENOMEM; -- -- urbp->qh = qh; -- qh->urbp = urbp; -- -- uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); -+ destination | uhci_explen(0), 0); - - /* Low-speed transfers get a different queue, and won't hog the bus. - * Also, some devices enumerate better without FSBR; the easiest way -@@ -675,18 +615,13 @@ static int uhci_submit_control(struct uh - * isn't in the CONFIGURED state. */ - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->state != USB_STATE_CONFIGURED) -- skelqh = uhci->skel_ls_control_qh; -+ qh->skel = uhci->skel_ls_control_qh; - else { -- skelqh = uhci->skel_fs_control_qh; -+ qh->skel = uhci->skel_fs_control_qh; - uhci_inc_fsbr(uhci, urb); - } - -- if (eurb) -- uhci_append_queued_urb(uhci, eurb, urb); -- else -- uhci_insert_qh(uhci, skelqh, urb); -- -- return -EINPROGRESS; -+ return 0; - } - - /* -@@ -703,7 +638,7 @@ static int usb_control_retrigger_status( - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - -- urbp->short_control_packet = 1; -+ urbp->short_transfer = 1; - - td = list_entry(urbp->td_list.prev, struct uhci_td, list); - urbp->qh->element = cpu_to_le32(td->dma_handle); -@@ -720,16 +655,14 @@ static int uhci_result_control(struct uh - unsigned int status; - int ret = 0; - -- if (list_empty(&urbp->td_list)) -- return -EINVAL; -- - head = &urbp->td_list; -- -- if (urbp->short_control_packet) { -+ if (urbp->short_transfer) { - tmp = head->prev; - goto status_stage; - } - -+ urb->actual_length = 0; -+ - tmp = head->next; - td = list_entry(tmp, struct uhci_td, list); - -@@ -742,8 +675,6 @@ static int uhci_result_control(struct uh - if (status) - goto td_error; - -- urb->actual_length = 0; -- - /* The rest of the TDs (but the last) are data */ - tmp = tmp->next; - while (tmp != head && tmp->next != head) { -@@ -770,10 +701,7 @@ static int uhci_result_control(struct uh - goto err; - } - -- if (uhci_packetid(td_token(td)) == USB_PID_IN) -- return usb_control_retrigger_status(uhci, urb); -- else -- return 0; -+ return usb_control_retrigger_status(uhci, urb); - } - } - -@@ -825,15 +753,15 @@ err: - /* - * Common submit for bulk and interrupt - */ --static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh) -+static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { - struct uhci_td *td; -- struct uhci_qh *qh; - unsigned long destination, status; -- int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); - int len = urb->transfer_buffer_length; -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - dma_addr_t data = urb->transfer_dma; -+ __le32 *plink, fake_link; - - if (len < 0) - return -EINVAL; -@@ -841,7 +769,8 @@ static int uhci_submit_common(struct uhc - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - -- status = uhci_maxerr(3) | TD_CTRL_ACTIVE; -+ /* 3 errors */ -+ status = TD_CTRL_ACTIVE | uhci_maxerr(3); - if (urb->dev->speed == USB_SPEED_LOW) - status |= TD_CTRL_LS; - if (usb_pipein(urb->pipe)) -@@ -850,10 +779,11 @@ static int uhci_submit_common(struct uhc - /* - * Build the DATA TDs - */ -+ plink = &fake_link; - do { /* Allow zero length packets */ - int pktsze = maxsze; - -- if (pktsze >= len) { -+ if (len <= pktsze) { /* The last packet */ - pktsze = len; - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) - status &= ~TD_CTRL_SPD; -@@ -862,12 +792,15 @@ static int uhci_submit_common(struct uhc - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; -+ *plink = cpu_to_le32(td->dma_handle); - - uhci_add_td_to_urb(urb, td); -- uhci_fill_td(td, status, destination | uhci_explen(pktsze) | -+ uhci_fill_td(td, status, -+ destination | uhci_explen(pktsze) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); -+ plink = &td->link; - - data += pktsze; - len -= maxsze; -@@ -883,11 +816,13 @@ static int uhci_submit_common(struct uhc - * however, if transfer_length == 0, the zero packet was already - * prepared above. - */ -- if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && -- !len && urb->transfer_buffer_length) { -+ if ((urb->transfer_flags & URB_ZERO_PACKET) && -+ usb_pipeout(urb->pipe) && len == 0 && -+ urb->transfer_buffer_length > 0) { - td = uhci_alloc_td(uhci); - if (!td) - return -ENOMEM; -+ *plink = cpu_to_le32(td->dma_handle); - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(0) | -@@ -905,24 +840,9 @@ static int uhci_submit_common(struct uhc - * fast side but not enough to justify delaying an interrupt - * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT - * flag setting. */ -- td->status |= cpu_to_le32(TD_CTRL_IOC); -- -- qh = uhci_alloc_qh(uhci); -- if (!qh) -- return -ENOMEM; -- -- urbp->qh = qh; -- qh->urbp = urbp; -+ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); - -- /* Always breadth first */ -- uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); -- -- if (eurb) -- uhci_append_queued_urb(uhci, eurb, urb); -- else -- uhci_insert_qh(uhci, skelqh, urb); -- -- return -EINPROGRESS; -+ return 0; - } - - /* -@@ -954,8 +874,24 @@ static int uhci_result_common(struct uhc - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; -- } else -- return 0; -+ } -+ -+ /* -+ * This URB stopped short of its end. We have to -+ * fix up the toggles of the following URBs on the -+ * queue and restart the queue. -+ * -+ * Do this only the first time we encounter the -+ * short URB. -+ */ -+ if (!urbp->short_transfer) { -+ urbp->short_transfer = 1; -+ uhci_fixup_toggles(urb); -+ td = list_entry(urbp->td_list.prev, -+ struct uhci_td, list); -+ urbp->qh->element = td->link; -+ } -+ break; - } - } - -@@ -988,7 +924,8 @@ err: - return ret; - } - --static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -+static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { - int ret; - -@@ -996,21 +933,22 @@ static inline int uhci_submit_bulk(struc - if (urb->dev->speed == USB_SPEED_LOW) - return -EINVAL; - -- ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh); -- if (ret == -EINPROGRESS) -+ qh->skel = uhci->skel_bulk_qh; -+ ret = uhci_submit_common(uhci, urb, qh); -+ if (ret == 0) - uhci_inc_fsbr(uhci, urb); -- - return ret; - } - --static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -+static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { -- /* USB 1.1 interrupt transfers only involve one packet per interval; -- * that's the uhci_submit_common() "breadth first" policy. Drivers -- * can submit urbs of any length, but longer ones might need many -- * intervals to complete. -+ /* USB 1.1 interrupt transfers only involve one packet per interval. -+ * Drivers can submit URBs of any length, but longer ones will need -+ * multiple intervals to complete. - */ -- return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]); -+ qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)]; -+ return uhci_submit_common(uhci, urb, qh); - } - - /* -@@ -1072,11 +1010,12 @@ static int isochronous_find_start(struct - /* - * Isochronous transfers - */ --static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) -+static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, -+ struct uhci_qh *qh) - { -- struct uhci_td *td; -+ struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ - int i, ret, frame; -- int status, destination; -+ unsigned long destination, status; - struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; -@@ -1092,20 +1031,25 @@ static int uhci_submit_isochronous(struc - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); -- uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length), -- urb->transfer_dma + urb->iso_frame_desc[i].offset); -- -- if (i + 1 >= urb->number_of_packets) -- td->status |= cpu_to_le32(TD_CTRL_IOC); -+ uhci_fill_td(td, status, destination | -+ uhci_explen(urb->iso_frame_desc[i].length), -+ urb->transfer_dma + -+ urb->iso_frame_desc[i].offset); - } - -+ /* Set the interrupt-on-completion flag on the last packet. */ -+ td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); -+ -+ qh->skel = uhci->skel_iso_qh; -+ -+ /* Add the TDs to the frame list */ - frame = urb->start_frame; - list_for_each_entry(td, &urbp->td_list, list) { -- uhci_insert_td_frame_list(uhci, td, frame); -+ uhci_insert_td_in_frame_list(uhci, td, frame); - frame += urb->interval; - } - -- return -EINPROGRESS; -+ return 0; - } - - static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) -@@ -1139,80 +1083,67 @@ static int uhci_result_isochronous(struc - - i++; - } -- unlink_isochronous_tds(uhci, urb); - - return ret; - } - --static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) --{ -- struct urb_priv *up; -- -- /* We don't match Isoc transfers since they are special */ -- if (usb_pipeisoc(urb->pipe)) -- return NULL; -- -- list_for_each_entry(up, &uhci->urb_list, urb_list) { -- struct urb *u = up->urb; -- -- if (u->dev == urb->dev && u->status == -EINPROGRESS) { -- /* For control, ignore the direction */ -- if (usb_pipecontrol(urb->pipe) && -- (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN)) -- return u; -- else if (u->pipe == urb->pipe) -- return u; -- } -- } -- -- return NULL; --} -- - static int uhci_urb_enqueue(struct usb_hcd *hcd, -- struct usb_host_endpoint *ep, -+ struct usb_host_endpoint *hep, - struct urb *urb, gfp_t mem_flags) - { - int ret; - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; -- struct urb *eurb; -+ struct urb_priv *urbp; -+ struct uhci_qh *qh; - int bustime; - - spin_lock_irqsave(&uhci->lock, flags); - - ret = urb->status; - if (ret != -EINPROGRESS) /* URB already unlinked! */ -- goto out; -+ goto done; - -- eurb = uhci_find_urb_ep(uhci, urb); -+ ret = -ENOMEM; -+ urbp = uhci_alloc_urb_priv(uhci, urb); -+ if (!urbp) -+ goto done; - -- if (!uhci_alloc_urb_priv(uhci, urb)) { -- ret = -ENOMEM; -- goto out; -+ if (hep->hcpriv) -+ qh = (struct uhci_qh *) hep->hcpriv; -+ else { -+ qh = uhci_alloc_qh(uhci, urb->dev, hep); -+ if (!qh) -+ goto err_no_qh; - } -+ urbp->qh = qh; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: -- ret = uhci_submit_control(uhci, urb, eurb); -+ ret = uhci_submit_control(uhci, urb, qh); -+ break; -+ case PIPE_BULK: -+ ret = uhci_submit_bulk(uhci, urb, qh); - break; - case PIPE_INTERRUPT: -- if (!eurb) { -+ if (list_empty(&qh->queue)) { - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) - ret = bustime; - else { -- ret = uhci_submit_interrupt(uhci, urb, eurb); -- if (ret == -EINPROGRESS) -+ ret = uhci_submit_interrupt(uhci, urb, qh); -+ if (ret == 0) - usb_claim_bandwidth(urb->dev, urb, bustime, 0); - } - } else { /* inherit from parent */ -- urb->bandwidth = eurb->bandwidth; -- ret = uhci_submit_interrupt(uhci, urb, eurb); -+ struct urb_priv *eurbp; -+ -+ eurbp = list_entry(qh->queue.prev, struct urb_priv, -+ node); -+ urb->bandwidth = eurbp->urb->bandwidth; -+ ret = uhci_submit_interrupt(uhci, urb, qh); - } - break; -- case PIPE_BULK: -- ret = uhci_submit_bulk(uhci, urb, eurb); -- break; - case PIPE_ISOCHRONOUS: - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) { -@@ -1220,22 +1151,59 @@ static int uhci_urb_enqueue(struct usb_h - break; - } - -- ret = uhci_submit_isochronous(uhci, urb); -- if (ret == -EINPROGRESS) -+ ret = uhci_submit_isochronous(uhci, urb, qh); -+ if (ret == 0) - usb_claim_bandwidth(urb->dev, urb, bustime, 1); - break; - } -+ if (ret != 0) -+ goto err_submit_failed; - -- if (ret != -EINPROGRESS) { -- /* Submit failed, so delete it from the urb_list */ -- struct urb_priv *urbp = urb->hcpriv; -+ /* Add this URB to the QH */ -+ urbp->qh = qh; -+ list_add_tail(&urbp->node, &qh->queue); -+ list_add_tail(&urbp->urb_list, &uhci->urb_list); - -- list_del_init(&urbp->urb_list); -- uhci_destroy_urb_priv(uhci, urb); -- } else -- ret = 0; -+ /* If the new URB is the first and only one on this QH then either -+ * the QH is new and idle or else it's unlinked and waiting to -+ * become idle, so we can activate it right away. */ -+ if (qh->queue.next == &urbp->node) -+ uhci_activate_qh(uhci, qh); -+ -+ /* If the QH is already active, we have a race with the hardware. -+ * This won't get fixed until dummy TDs are added. */ -+ else if (qh->state == QH_STATE_ACTIVE) { -+ -+ /* If the URB isn't first on its queue, adjust the link pointer -+ * of the last TD in the previous URB. */ -+ if (urbp->node.prev != &urbp->qh->queue) { -+ struct urb_priv *purbp = list_entry(urbp->node.prev, -+ struct urb_priv, node); -+ struct uhci_td *ptd = list_entry(purbp->td_list.prev, -+ struct uhci_td, list); -+ struct uhci_td *td = list_entry(urbp->td_list.next, -+ struct uhci_td, list); -+ -+ ptd->link = cpu_to_le32(td->dma_handle); -+ -+ } -+ if (qh_element(qh) == UHCI_PTR_TERM) { -+ struct uhci_td *td = list_entry(urbp->td_list.next, -+ struct uhci_td, list); -+ -+ qh->element = cpu_to_le32(td->dma_handle); -+ } -+ } -+ goto done; -+ -+err_submit_failed: -+ if (qh->state == QH_STATE_IDLE) -+ uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ - --out: -+err_no_qh: -+ uhci_free_urb_priv(uhci, urbp); -+ -+done: - spin_unlock_irqrestore(&uhci->lock, flags); - return ret; - } -@@ -1245,119 +1213,115 @@ out: - */ - static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) - { -- int ret = -EINPROGRESS; -- struct urb_priv *urbp; -- -- spin_lock(&urb->lock); -- -- urbp = (struct urb_priv *)urb->hcpriv; -- -- if (urb->status != -EINPROGRESS) /* URB already dequeued */ -- goto out; -+ int status; -+ int okay_to_giveback = 0; -+ struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: -- ret = uhci_result_control(uhci, urb); -- break; -- case PIPE_BULK: -- case PIPE_INTERRUPT: -- ret = uhci_result_common(uhci, urb); -+ status = uhci_result_control(uhci, urb); - break; - case PIPE_ISOCHRONOUS: -- ret = uhci_result_isochronous(uhci, urb); -+ status = uhci_result_isochronous(uhci, urb); -+ break; -+ default: /* PIPE_BULK or PIPE_INTERRUPT */ -+ status = uhci_result_common(uhci, urb); - break; - } - -- if (ret == -EINPROGRESS) -- goto out; -- urb->status = ret; -+ spin_lock(&urb->lock); -+ if (urb->status == -EINPROGRESS) { /* Not yet dequeued */ -+ if (status != -EINPROGRESS) { /* URB has completed */ -+ urb->status = status; -+ -+ /* If the URB got a real error (as opposed to -+ * simply being dequeued), we don't have to -+ * unlink the QH. Fix this later... */ -+ if (status < 0) -+ uhci_unlink_qh(uhci, urbp->qh); -+ else -+ okay_to_giveback = 1; -+ } -+ } else { /* Already dequeued */ -+ if (urbp->qh->state == QH_STATE_UNLINKING && -+ uhci->frame_number + uhci->is_stopped != -+ urbp->qh->unlink_frame) -+ okay_to_giveback = 1; -+ } -+ spin_unlock(&urb->lock); -+ if (!okay_to_giveback) -+ return; - - switch (usb_pipetype(urb->pipe)) { -- case PIPE_CONTROL: -- case PIPE_BULK: - case PIPE_ISOCHRONOUS: - /* Release bandwidth for Interrupt or Isoc. transfers */ - if (urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 1); -- uhci_unlink_generic(uhci, urb); - break; - case PIPE_INTERRUPT: - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Make sure we don't release if we have a queued URB */ -- if (list_empty(&urbp->queue_list) && urb->bandwidth) -+ if (list_empty(&urbp->qh->queue) && urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 0); - else - /* bandwidth was passed on to queued URB, */ - /* so don't let usb_unlink_urb() release it */ - urb->bandwidth = 0; -- uhci_unlink_generic(uhci, urb); -+ /* Falls through */ -+ case PIPE_BULK: -+ if (status < 0) -+ uhci_fixup_toggles(urb); -+ break; -+ default: /* PIPE_CONTROL */ - break; -- default: -- dev_info(uhci_dev(uhci), "%s: unknown pipe type %d " -- "for urb %p\n", -- __FUNCTION__, usb_pipetype(urb->pipe), urb); - } - -- /* Move it from uhci->urb_list to uhci->complete_list */ -- uhci_moveto_complete(uhci, urbp); -+ /* Take the URB's TDs off the hardware schedule */ -+ uhci_remove_tds_from_schedule(uhci, urb, status); - --out: -- spin_unlock(&urb->lock); -+ /* Take the URB off the QH's queue and see if the QH is now unused */ -+ list_del_init(&urbp->node); -+ if (list_empty(&urbp->qh->queue)) -+ uhci_unlink_qh(uhci, urbp->qh); -+ -+ uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ -+ -+ /* Queue it for giving back */ -+ list_move_tail(&urbp->urb_list, &uhci->complete_list); - } - --static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) -+/* -+ * Check out the QHs waiting to be fully unlinked -+ */ -+static void uhci_scan_unlinking_qhs(struct uhci_hcd *uhci) - { -- struct list_head *head; -- struct uhci_td *td; -- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; -- int prevactive = 0; -+ struct uhci_qh *qh, *tmp; - -- uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ -+ list_for_each_entry_safe(qh, tmp, &uhci->skel_unlink_qh->node, node) { - -- /* -- * Now we need to find out what the last successful toggle was -- * so we can update the local data toggle for the next transfer -- * -- * There are 2 ways the last successful completed TD is found: -- * -- * 1) The TD is NOT active and the actual length < expected length -- * 2) The TD is NOT active and it's the last TD in the chain -- * -- * and a third way the first uncompleted TD is found: -- * -- * 3) The TD is active and the previous TD is NOT active -- * -- * Control and Isochronous ignore the toggle, so this is safe -- * for all types -- * -- * FIXME: The toggle fixups won't be 100% reliable until we -- * change over to using a single queue for each endpoint and -- * stop the queue before unlinking. -- */ -- head = &urbp->td_list; -- list_for_each_entry(td, head, list) { -- unsigned int ctrlstat = td_status(td); -+ /* If the queue is empty and the QH is fully unlinked then -+ * it can become IDLE. */ -+ if (list_empty(&qh->queue)) { -+ if (uhci->frame_number + uhci->is_stopped != -+ qh->unlink_frame) -+ uhci_make_qh_idle(uhci, qh); - -- if (!(ctrlstat & TD_CTRL_ACTIVE) && -- (uhci_actual_length(ctrlstat) < -- uhci_expected_length(td_token(td)) || -- td->list.next == head)) -- usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), -- uhci_packetout(td_token(td)), -- uhci_toggle(td_token(td)) ^ 1); -- else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) -- usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), -- uhci_packetout(td_token(td)), -- uhci_toggle(td_token(td))); -+ /* If none of the QH's URBs have been dequeued then the QH -+ * should be re-activated. */ -+ } else { -+ struct urb_priv *urbp; -+ int any_dequeued = 0; - -- prevactive = ctrlstat & TD_CTRL_ACTIVE; -+ list_for_each_entry(urbp, &qh->queue, node) { -+ if (urbp->urb->status != -EINPROGRESS) { -+ any_dequeued = 1; -+ break; -+ } -+ } -+ if (!any_dequeued) -+ uhci_activate_qh(uhci, qh); -+ } - } -- -- uhci_delete_queued_urb(uhci, urb); -- -- /* The interrupt loop will reclaim the QHs */ -- uhci_remove_qh(uhci, urbp->qh); -- urbp->qh = NULL; - } - - static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -@@ -1370,22 +1334,11 @@ static int uhci_urb_dequeue(struct usb_h - urbp = urb->hcpriv; - if (!urbp) /* URB was never linked! */ - goto done; -- list_del_init(&urbp->urb_list); - -+ /* Remove Isochronous TDs from the frame list ASAP */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) -- unlink_isochronous_tds(uhci, urb); -- uhci_unlink_generic(uhci, urb); -- -- uhci_get_current_frame_number(uhci); -- if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) { -- uhci_remove_pending_urbps(uhci); -- uhci->urb_remove_age = uhci->frame_number; -- } -- -- /* If we're the first, set the next interrupt bit */ -- if (list_empty(&uhci->urb_remove_list)) -- uhci_set_next_interrupt(uhci); -- list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); -+ uhci_unlink_isochronous_tds(uhci, urb); -+ uhci_unlink_qh(uhci, urbp->qh); - - done: - spin_unlock_irqrestore(&uhci->lock, flags); -@@ -1426,17 +1379,6 @@ static int uhci_fsbr_timeout(struct uhci - return 0; - } - --static void uhci_free_pending_qhs(struct uhci_hcd *uhci) --{ -- struct uhci_qh *qh, *tmp; -- -- list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) { -- list_del_init(&qh->remove_list); -- -- uhci_free_qh(uhci, qh); -- } --} -- - static void uhci_free_pending_tds(struct uhci_hcd *uhci) - { - struct uhci_td *td, *tmp; -@@ -1455,7 +1397,7 @@ __acquires(uhci->lock) - { - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - -- uhci_destroy_urb_priv(uhci, urb); -+ uhci_free_urb_priv(uhci, (struct urb_priv *) (urb->hcpriv)); - - spin_unlock(&uhci->lock); - usb_hcd_giveback_urb(hcd, urb, regs); -@@ -1474,13 +1416,6 @@ static void uhci_finish_completion(struc - } - } - --static void uhci_remove_pending_urbps(struct uhci_hcd *uhci) --{ -- -- /* Splice the urb_remove_list onto the end of the complete_list */ -- list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev); --} -- - /* Process events in the schedule, but only in one thread at a time */ - static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) - { -@@ -1498,12 +1433,8 @@ static void uhci_scan_schedule(struct uh - uhci_clear_next_interrupt(uhci); - uhci_get_current_frame_number(uhci); - -- if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) -- uhci_free_pending_qhs(uhci); - if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) - uhci_free_pending_tds(uhci); -- if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) -- uhci_remove_pending_urbps(uhci); - - /* Walk the list of pending URBs to see which ones completed - * (must be _safe because uhci_transfer_result() dequeues URBs) */ -@@ -1516,25 +1447,21 @@ static void uhci_scan_schedule(struct uh - uhci_finish_completion(uhci, regs); - - /* If the controller is stopped, we can finish these off right now */ -- if (uhci->is_stopped) { -- uhci_free_pending_qhs(uhci); -+ if (uhci->is_stopped) - uhci_free_pending_tds(uhci); -- uhci_remove_pending_urbps(uhci); -- } - - if (uhci->need_rescan) - goto rescan; - uhci->scan_in_progress = 0; - -- if (list_empty(&uhci->urb_remove_list) && -- list_empty(&uhci->td_remove_list) && -- list_empty(&uhci->qh_remove_list)) -+ /* Check out the QHs waiting for unlinking */ -+ uhci_scan_unlinking_qhs(uhci); -+ -+ if (list_empty(&uhci->td_remove_list) && -+ list_empty(&uhci->skel_unlink_qh->node)) - uhci_clear_next_interrupt(uhci); - else - uhci_set_next_interrupt(uhci); -- -- /* Wake up anyone waiting for an URB to complete */ -- wake_up_all(&uhci->waitqh); - } - - static void check_fsbr(struct uhci_hcd *uhci) diff --git a/usb/usb-add-support-for-at91-gadget.patch b/usb/usb-add-support-for-at91-gadget.patch deleted file mode 100644 index 4ae77f61f6d4a..0000000000000 --- a/usb/usb-add-support-for-at91-gadget.patch +++ /dev/null @@ -1,2022 +0,0 @@ -From david-b@pacbell.net Sun Jan 22 11:29:00 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: add support for AT91 gadget -Date: Sun, 22 Jan 2006 10:32:37 -0800 -Cc: Andrew Victor <andrew@sanpeople.com> -Message-Id: <200601221032.37299.david-b@pacbell.net> - - -This adds support for the USB peripheral controller on AT91 -(rm9200, eventually also sam9261 or uClinux) platforms. - -More SOC support for Linux-USB ... an uncomplicated pure PIO driver. -It'd be worth using this as a model, if you're starting a driver -for some other peripheral controller. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/Kconfig | 17 - drivers/usb/gadget/Makefile | 1 - drivers/usb/gadget/at91_udc.c | 1773 ++++++++++++++++++++++++++++++++++++++++++ - drivers/usb/gadget/at91_udc.h | 181 ++++ - 4 files changed, 1972 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/gadget/Kconfig -+++ gregkh-2.6/drivers/usb/gadget/Kconfig -@@ -187,6 +187,23 @@ config USB_OTG - - Select this only if your OMAP board has a Mini-AB connector. - -+config USB_GADGET_AT91 -+ boolean "AT91 USB Device Port" -+ depends on ARCH_AT91RM9200 -+ select USB_GADGET_SELECTED -+ help -+ Many Atmel AT91 processors (such as the AT91RM2000) have a -+ full speed USB Device Port with support for five configurable -+ endpoints (plus endpoint zero). -+ -+ Say "y" to link the driver statically, or "m" to build a -+ dynamically linked module called "at91_udc" and force all -+ gadget drivers to also be dynamically linked. -+ -+config USB_AT91 -+ tristate -+ depends on USB_GADGET_AT91 -+ default USB_GADGET - - config USB_GADGET_DUMMY_HCD - boolean "Dummy HCD (DEVELOPMENT)" ---- gregkh-2.6.orig/drivers/usb/gadget/Makefile -+++ gregkh-2.6/drivers/usb/gadget/Makefile -@@ -7,6 +7,7 @@ obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o - obj-$(CONFIG_USB_GOKU) += goku_udc.o - obj-$(CONFIG_USB_OMAP) += omap_udc.o - obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o -+obj-$(CONFIG_USB_AT91) += at91_udc.o - - # - # USB gadget drivers ---- /dev/null -+++ gregkh-2.6/drivers/usb/gadget/at91_udc.c -@@ -0,0 +1,1773 @@ -+/* -+ * at91_udc -- driver for at91-series USB peripheral controller -+ * -+ * Copyright (C) 2004 by Thomas Rathbone -+ * Copyright (C) 2005 by HP Labs -+ * Copyright (C) 2005 by David Brownell -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 02111-1307, USA. -+ */ -+ -+#undef DEBUG -+#undef VERBOSE -+#undef PACKET_TRACE -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/ioport.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/smp_lock.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/interrupt.h> -+#include <linux/proc_fs.h> -+#include <linux/clk.h> -+#include <linux/usb_ch9.h> -+#include <linux/usb_gadget.h> -+ -+#include <asm/byteorder.h> -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+#include <asm/mach-types.h> -+ -+#include <asm/arch/hardware.h> -+#include <asm/arch/gpio.h> -+#include <asm/arch/board.h> -+ -+#include "at91_udc.h" -+ -+ -+/* -+ * This controller is simple and PIO-only. It's used in many AT91-series -+ * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU), -+ * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions. -+ * -+ * This driver expects the board has been wired with two GPIOs suppporting -+ * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the -+ * testing hasn't covered such cases.) The pullup is most important; it -+ * provides software control over whether the host enumerates the device. -+ * The VBUS sensing helps during enumeration, and allows both USB clocks -+ * (and the transceiver) to stay gated off until they're necessary, saving -+ * power. During USB suspend, the 48 MHz clock is gated off. -+ */ -+ -+#define DRIVER_VERSION "8 March 2005" -+ -+static const char driver_name [] = "at91_udc"; -+static const char ep0name[] = "ep0"; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * Read from a UDP register. -+ */ -+static inline unsigned long at91_udp_read(unsigned int reg) -+{ -+ void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; -+ -+ return __raw_readl(udp_base + reg); -+} -+ -+/* -+ * Write to a UDP register. -+ */ -+static inline void at91_udp_write(unsigned int reg, unsigned long value) -+{ -+ void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP; -+ -+ __raw_writel(value, udp_base + reg); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+#ifdef CONFIG_USB_GADGET_DEBUG_FILES -+ -+#include <linux/seq_file.h> -+ -+static const char debug_filename[] = "driver/udc"; -+ -+#define FOURBITS "%s%s%s%s" -+#define EIGHTBITS FOURBITS FOURBITS -+ -+static void proc_ep_show(struct seq_file *s, struct at91_ep *ep) -+{ -+ static char *types[] = { -+ "control", "out-iso", "out-bulk", "out-int", -+ "BOGUS", "in-iso", "in-bulk", "in-int"}; -+ -+ u32 csr; -+ struct at91_request *req; -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ -+ csr = __raw_readl(ep->creg); -+ -+ /* NOTE: not collecting per-endpoint irq statistics... */ -+ -+ seq_printf(s, "\n"); -+ seq_printf(s, "%s, maxpacket %d %s%s %s%s\n", -+ ep->ep.name, ep->ep.maxpacket, -+ ep->is_in ? "in" : "out", -+ ep->is_iso ? " iso" : "", -+ ep->is_pingpong -+ ? (ep->fifo_bank ? "pong" : "ping") -+ : "", -+ ep->stopped ? " stopped" : ""); -+ seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n", -+ csr, -+ (csr & 0x07ff0000) >> 16, -+ (csr & (1 << 15)) ? "enabled" : "disabled", -+ (csr & (1 << 11)) ? "DATA1" : "DATA0", -+ types[(csr & 0x700) >> 8], -+ -+ /* iff type is control then print current direction */ -+ (!(csr & 0x700)) -+ ? ((csr & (1 << 7)) ? " IN" : " OUT") -+ : "", -+ (csr & (1 << 6)) ? " rxdatabk1" : "", -+ (csr & (1 << 5)) ? " forcestall" : "", -+ (csr & (1 << 4)) ? " txpktrdy" : "", -+ -+ (csr & (1 << 3)) ? " stallsent" : "", -+ (csr & (1 << 2)) ? " rxsetup" : "", -+ (csr & (1 << 1)) ? " rxdatabk0" : "", -+ (csr & (1 << 0)) ? " txcomp" : ""); -+ if (list_empty (&ep->queue)) -+ seq_printf(s, "\t(queue empty)\n"); -+ -+ else list_for_each_entry (req, &ep->queue, queue) { -+ unsigned length = req->req.actual; -+ -+ seq_printf(s, "\treq %p len %d/%d buf %p\n", -+ &req->req, length, -+ req->req.length, req->req.buf); -+ } -+ local_irq_restore(flags); -+} -+ -+static void proc_irq_show(struct seq_file *s, const char *label, u32 mask) -+{ -+ int i; -+ -+ seq_printf(s, "%s %04x:%s%s" FOURBITS, label, mask, -+ (mask & (1 << 13)) ? " wakeup" : "", -+ (mask & (1 << 12)) ? " endbusres" : "", -+ -+ (mask & (1 << 11)) ? " sofint" : "", -+ (mask & (1 << 10)) ? " extrsm" : "", -+ (mask & (1 << 9)) ? " rxrsm" : "", -+ (mask & (1 << 8)) ? " rxsusp" : ""); -+ for (i = 0; i < 8; i++) { -+ if (mask & (1 << i)) -+ seq_printf(s, " ep%d", i); -+ } -+ seq_printf(s, "\n"); -+} -+ -+static int proc_udc_show(struct seq_file *s, void *unused) -+{ -+ struct at91_udc *udc = s->private; -+ struct at91_ep *ep; -+ u32 tmp; -+ -+ seq_printf(s, "%s: version %s\n", driver_name, DRIVER_VERSION); -+ -+ seq_printf(s, "vbus %s, pullup %s, %s powered%s, gadget %s\n\n", -+ udc->vbus ? "present" : "off", -+ udc->enabled -+ ? (udc->vbus ? "active" : "enabled") -+ : "disabled", -+ udc->selfpowered ? "self" : "VBUS", -+ udc->suspended ? ", suspended" : "", -+ udc->driver ? udc->driver->driver.name : "(none)"); -+ -+ /* don't access registers when interface isn't clocked */ -+ if (!udc->clocked) { -+ seq_printf(s, "(not clocked)\n"); -+ return 0; -+ } -+ -+ tmp = at91_udp_read(AT91_UDP_FRM_NUM); -+ seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp, -+ (tmp & AT91_UDP_FRM_OK) ? " ok" : "", -+ (tmp & AT91_UDP_FRM_ERR) ? " err" : "", -+ (tmp & AT91_UDP_NUM)); -+ -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT); -+ seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp, -+ (tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "", -+ (tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "", -+ (tmp & AT91_UDP_ESR) ? " esr" : "", -+ (tmp & AT91_UDP_CONFG) ? " confg" : "", -+ (tmp & AT91_UDP_FADDEN) ? " fadden" : ""); -+ -+ tmp = at91_udp_read(AT91_UDP_FADDR); -+ seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp, -+ (tmp & AT91_UDP_FEN) ? " fen" : "", -+ (tmp & AT91_UDP_FADD)); -+ -+ proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR)); -+ proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR)); -+ -+ if (udc->enabled && udc->vbus) { -+ proc_ep_show(s, &udc->ep[0]); -+ list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) { -+ if (ep->desc) -+ proc_ep_show(s, ep); -+ } -+ } -+ return 0; -+} -+ -+static int proc_udc_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, proc_udc_show, PDE(inode)->data); -+} -+ -+static struct file_operations proc_ops = { -+ .open = proc_udc_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static void create_debug_file(struct at91_udc *udc) -+{ -+ struct proc_dir_entry *pde; -+ -+ pde = create_proc_entry (debug_filename, 0, NULL); -+ udc->pde = pde; -+ if (pde == NULL) -+ return; -+ -+ pde->proc_fops = &proc_ops; -+ pde->data = udc; -+} -+ -+static void remove_debug_file(struct at91_udc *udc) -+{ -+ if (udc->pde) -+ remove_proc_entry(debug_filename, NULL); -+} -+ -+#else -+ -+static inline void create_debug_file(struct at91_udc *udc) {} -+static inline void remove_debug_file(struct at91_udc *udc) {} -+ -+#endif -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void done(struct at91_ep *ep, struct at91_request *req, int status) -+{ -+ unsigned stopped = ep->stopped; -+ -+ list_del_init(&req->queue); -+ if (req->req.status == -EINPROGRESS) -+ req->req.status = status; -+ else -+ status = req->req.status; -+ if (status && status != -ESHUTDOWN) -+ VDBG("%s done %p, status %d\n", ep->ep.name, req, status); -+ -+ ep->stopped = 1; -+ req->req.complete(&ep->ep, &req->req); -+ ep->stopped = stopped; -+ -+ /* ep0 is always ready; other endpoints need a non-empty queue */ -+ if (list_empty(&ep->queue) && ep->int_mask != (1 << 0)) -+ at91_udp_write(AT91_UDP_IDR, ep->int_mask); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* bits indicating OUT fifo has data ready */ -+#define RX_DATA_READY (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1) -+ -+/* -+ * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write -+ * back most of the value you just read (because of side effects, including -+ * bits that may change after reading and before writing). -+ * -+ * Except when changing a specific bit, always write values which: -+ * - clear SET_FX bits (setting them could change something) -+ * - set CLR_FX bits (clearing them could change something) -+ * -+ * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE -+ * that shouldn't normally be changed. -+ */ -+#define SET_FX (AT91_UDP_TXPKTRDY) -+#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) -+ -+/* pull OUT packet data from the endpoint's fifo */ -+static int read_fifo (struct at91_ep *ep, struct at91_request *req) -+{ -+ u32 __iomem *creg = ep->creg; -+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); -+ u32 csr; -+ u8 *buf; -+ unsigned int count, bufferspace, is_done; -+ -+ buf = req->req.buf + req->req.actual; -+ bufferspace = req->req.length - req->req.actual; -+ -+ /* -+ * there might be nothing to read if ep_queue() calls us, -+ * or if we already emptied both pingpong buffers -+ */ -+rescan: -+ csr = __raw_readl(creg); -+ if ((csr & RX_DATA_READY) == 0) -+ return 0; -+ -+ count = (csr & AT91_UDP_RXBYTECNT) >> 16; -+ if (count > ep->ep.maxpacket) -+ count = ep->ep.maxpacket; -+ if (count > bufferspace) { -+ DBG("%s buffer overflow\n", ep->ep.name); -+ req->req.status = -EOVERFLOW; -+ count = bufferspace; -+ } -+ __raw_readsb(dreg, buf, count); -+ -+ /* release and swap pingpong mem bank */ -+ csr |= CLR_FX; -+ if (ep->is_pingpong) { -+ if (ep->fifo_bank == 0) { -+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); -+ ep->fifo_bank = 1; -+ } else { -+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1); -+ ep->fifo_bank = 0; -+ } -+ } else -+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); -+ __raw_writel(csr, creg); -+ -+ req->req.actual += count; -+ is_done = (count < ep->ep.maxpacket); -+ if (count == bufferspace) -+ is_done = 1; -+ -+ PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count, -+ is_done ? " (done)" : ""); -+ -+ /* -+ * avoid extra trips through IRQ logic for packets already in -+ * the fifo ... maybe preventing an extra (expensive) OUT-NAK -+ */ -+ if (is_done) -+ done(ep, req, 0); -+ else if (ep->is_pingpong) { -+ bufferspace -= count; -+ buf += count; -+ goto rescan; -+ } -+ -+ return is_done; -+} -+ -+/* load fifo for an IN packet */ -+static int write_fifo(struct at91_ep *ep, struct at91_request *req) -+{ -+ u32 __iomem *creg = ep->creg; -+ u32 csr = __raw_readl(creg); -+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); -+ unsigned total, count, is_last; -+ -+ /* -+ * TODO: allow for writing two packets to the fifo ... that'll -+ * reduce the amount of IN-NAKing, but probably won't affect -+ * throughput much. (Unlike preventing OUT-NAKing!) -+ */ -+ -+ /* -+ * If ep_queue() calls us, the queue is empty and possibly in -+ * odd states like TXCOMP not yet cleared (we do it, saving at -+ * least one IRQ) or the fifo not yet being free. Those aren't -+ * issues normally (IRQ handler fast path). -+ */ -+ if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) { -+ if (csr & AT91_UDP_TXCOMP) { -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_TXCOMP); -+ __raw_writel(csr, creg); -+ csr = __raw_readl(creg); -+ } -+ if (csr & AT91_UDP_TXPKTRDY) -+ return 0; -+ } -+ -+ total = req->req.length - req->req.actual; -+ if (ep->ep.maxpacket < total) { -+ count = ep->ep.maxpacket; -+ is_last = 0; -+ } else { -+ count = total; -+ is_last = (count < ep->ep.maxpacket) || !req->req.zero; -+ } -+ -+ /* -+ * Write the packet, maybe it's a ZLP. -+ * -+ * NOTE: incrementing req->actual before we receive the ACK means -+ * gadget driver IN bytecounts can be wrong in fault cases. That's -+ * fixable with PIO drivers like this one (save "count" here, and -+ * do the increment later on TX irq), but not for most DMA hardware. -+ * -+ * So all gadget drivers must accept that potential error. Some -+ * hardware supports precise fifo status reporting, letting them -+ * recover when the actual bytecount matters (e.g. for USB Test -+ * and Measurement Class devices). -+ */ -+ __raw_writesb(dreg, req->req.buf + req->req.actual, count); -+ csr &= ~SET_FX; -+ csr |= CLR_FX | AT91_UDP_TXPKTRDY; -+ __raw_writel(csr, creg); -+ req->req.actual += count; -+ -+ PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count, -+ is_last ? " (done)" : ""); -+ if (is_last) -+ done(ep, req, 0); -+ return is_last; -+} -+ -+static void nuke(struct at91_ep *ep, int status) -+{ -+ struct at91_request *req; -+ -+ // terminer chaque requete dans la queue -+ ep->stopped = 1; -+ if (list_empty(&ep->queue)) -+ return; -+ -+ VDBG("%s %s\n", __FUNCTION__, ep->ep.name); -+ while (!list_empty(&ep->queue)) { -+ req = list_entry(ep->queue.next, struct at91_request, queue); -+ done(ep, req, status); -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) -+{ -+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); -+ struct at91_udc *dev = ep->udc; -+ u16 maxpacket; -+ u32 tmp; -+ unsigned long flags; -+ -+ if (!_ep || !ep -+ || !desc || ep->desc -+ || _ep->name == ep0name -+ || desc->bDescriptorType != USB_DT_ENDPOINT -+ || (maxpacket = le16_to_cpu(desc->wMaxPacketSize)) == 0 -+ || maxpacket > ep->maxpacket) { -+ DBG("bad ep or descriptor\n"); -+ return -EINVAL; -+ } -+ -+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { -+ DBG("bogus device state\n"); -+ return -ESHUTDOWN; -+ } -+ -+ tmp = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -+ switch (tmp) { -+ case USB_ENDPOINT_XFER_CONTROL: -+ DBG("only one control endpoint\n"); -+ return -EINVAL; -+ case USB_ENDPOINT_XFER_INT: -+ if (maxpacket > 64) -+ goto bogus_max; -+ break; -+ case USB_ENDPOINT_XFER_BULK: -+ switch (maxpacket) { -+ case 8: -+ case 16: -+ case 32: -+ case 64: -+ goto ok; -+ } -+bogus_max: -+ DBG("bogus maxpacket %d\n", maxpacket); -+ return -EINVAL; -+ case USB_ENDPOINT_XFER_ISOC: -+ if (!ep->is_pingpong) { -+ DBG("iso requires double buffering\n"); -+ return -EINVAL; -+ } -+ break; -+ } -+ -+ok: -+ local_irq_save(flags); -+ -+ /* initialize endpoint to match this descriptor */ -+ ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0; -+ ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC); -+ ep->stopped = 0; -+ if (ep->is_in) -+ tmp |= 0x04; -+ tmp <<= 8; -+ tmp |= AT91_UDP_EPEDS; -+ __raw_writel(tmp, ep->creg); -+ -+ ep->desc = desc; -+ ep->ep.maxpacket = maxpacket; -+ -+ /* -+ * reset/init endpoint fifo. NOTE: leaves fifo_bank alone, -+ * since endpoint resets don't reset hw pingpong state. -+ */ -+ at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(AT91_UDP_RST_EP, 0); -+ -+ local_irq_restore(flags); -+ return 0; -+} -+ -+static int at91_ep_disable (struct usb_ep * _ep) -+{ -+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); -+ unsigned long flags; -+ -+ if (ep == &ep->udc->ep[0]) -+ return -EINVAL; -+ -+ local_irq_save(flags); -+ -+ nuke(ep, -ESHUTDOWN); -+ -+ /* restore the endpoint's pristine config */ -+ ep->desc = NULL; -+ ep->ep.maxpacket = ep->maxpacket; -+ -+ /* reset fifos and endpoint */ -+ if (ep->udc->clocked) { -+ at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(AT91_UDP_RST_EP, 0); -+ __raw_writel(0, ep->creg); -+ } -+ -+ local_irq_restore(flags); -+ return 0; -+} -+ -+/* -+ * this is a PIO-only driver, so there's nothing -+ * interesting for request or buffer allocation. -+ */ -+ -+static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) -+{ -+ struct at91_request *req; -+ -+ req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); -+ if (!req) -+ return NULL; -+ -+ INIT_LIST_HEAD(&req->queue); -+ return &req->req; -+} -+ -+static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct at91_request *req; -+ -+ req = container_of(_req, struct at91_request, req); -+ BUG_ON(!list_empty(&req->queue)); -+ kfree(req); -+} -+ -+static void *at91_ep_alloc_buffer( -+ struct usb_ep *_ep, -+ unsigned bytes, -+ dma_addr_t *dma, -+ gfp_t gfp_flags) -+{ -+ *dma = ~0; -+ return kmalloc(bytes, gfp_flags); -+} -+ -+static void at91_ep_free_buffer( -+ struct usb_ep *ep, -+ void *buf, -+ dma_addr_t dma, -+ unsigned bytes) -+{ -+ kfree(buf); -+} -+ -+static int at91_ep_queue(struct usb_ep *_ep, -+ struct usb_request *_req, gfp_t gfp_flags) -+{ -+ struct at91_request *req; -+ struct at91_ep *ep; -+ struct at91_udc *dev; -+ int status; -+ unsigned long flags; -+ -+ req = container_of(_req, struct at91_request, req); -+ ep = container_of(_ep, struct at91_ep, ep); -+ -+ if (!_req || !_req->complete -+ || !_req->buf || !list_empty(&req->queue)) { -+ DBG("invalid request\n"); -+ return -EINVAL; -+ } -+ -+ if (!_ep || (!ep->desc && ep->ep.name != ep0name)) { -+ DBG("invalid ep\n"); -+ return -EINVAL; -+ } -+ -+ dev = ep->udc; -+ -+ if (!dev || !dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { -+ DBG("invalid device\n"); -+ return -EINVAL; -+ } -+ -+ _req->status = -EINPROGRESS; -+ _req->actual = 0; -+ -+ local_irq_save(flags); -+ -+ /* try to kickstart any empty and idle queue */ -+ if (list_empty(&ep->queue) && !ep->stopped) { -+ int is_ep0; -+ -+ /* -+ * If this control request has a non-empty DATA stage, this -+ * will start that stage. It works just like a non-control -+ * request (until the status stage starts, maybe early). -+ * -+ * If the data stage is empty, then this starts a successful -+ * IN/STATUS stage. (Unsuccessful ones use set_halt.) -+ */ -+ is_ep0 = (ep->ep.name == ep0name); -+ if (is_ep0) { -+ u32 tmp; -+ -+ if (!dev->req_pending) { -+ status = -EINVAL; -+ goto done; -+ } -+ -+ /* -+ * defer changing CONFG until after the gadget driver -+ * reconfigures the endpoints. -+ */ -+ if (dev->wait_for_config_ack) { -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT); -+ tmp ^= AT91_UDP_CONFG; -+ VDBG("toggle config\n"); -+ at91_udp_write(AT91_UDP_GLB_STAT, tmp); -+ } -+ if (req->req.length == 0) { -+ep0_in_status: -+ PACKET("ep0 in/status\n"); -+ status = 0; -+ tmp = __raw_readl(ep->creg); -+ tmp &= ~SET_FX; -+ tmp |= CLR_FX | AT91_UDP_TXPKTRDY; -+ __raw_writel(tmp, ep->creg); -+ dev->req_pending = 0; -+ goto done; -+ } -+ } -+ -+ if (ep->is_in) -+ status = write_fifo(ep, req); -+ else { -+ status = read_fifo(ep, req); -+ -+ /* IN/STATUS stage is otherwise triggered by irq */ -+ if (status && is_ep0) -+ goto ep0_in_status; -+ } -+ } else -+ status = 0; -+ -+ if (req && !status) { -+ list_add_tail (&req->queue, &ep->queue); -+ at91_udp_write(AT91_UDP_IER, ep->int_mask); -+ } -+done: -+ local_irq_restore(flags); -+ return (status < 0) ? status : 0; -+} -+ -+static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) -+{ -+ struct at91_ep *ep; -+ struct at91_request *req; -+ -+ ep = container_of(_ep, struct at91_ep, ep); -+ if (!_ep || ep->ep.name == ep0name) -+ return -EINVAL; -+ -+ /* make sure it's actually queued on this endpoint */ -+ list_for_each_entry (req, &ep->queue, queue) { -+ if (&req->req == _req) -+ break; -+ } -+ if (&req->req != _req) -+ return -EINVAL; -+ -+ done(ep, req, -ECONNRESET); -+ return 0; -+} -+ -+static int at91_ep_set_halt(struct usb_ep *_ep, int value) -+{ -+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); -+ u32 __iomem *creg; -+ u32 csr; -+ unsigned long flags; -+ int status = 0; -+ -+ if (!_ep || ep->is_iso || !ep->udc->clocked) -+ return -EINVAL; -+ -+ creg = ep->creg; -+ local_irq_save(flags); -+ -+ csr = __raw_readl(creg); -+ -+ /* -+ * fail with still-busy IN endpoints, ensuring correct sequencing -+ * of data tx then stall. note that the fifo rx bytecount isn't -+ * completely accurate as a tx bytecount. -+ */ -+ if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0)) -+ status = -EAGAIN; -+ else { -+ csr |= CLR_FX; -+ csr &= ~SET_FX; -+ if (value) { -+ csr |= AT91_UDP_FORCESTALL; -+ VDBG("halt %s\n", ep->ep.name); -+ } else { -+ at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(AT91_UDP_RST_EP, 0); -+ csr &= ~AT91_UDP_FORCESTALL; -+ } -+ __raw_writel(csr, creg); -+ } -+ -+ local_irq_restore(flags); -+ return status; -+} -+ -+static struct usb_ep_ops at91_ep_ops = { -+ .enable = at91_ep_enable, -+ .disable = at91_ep_disable, -+ .alloc_request = at91_ep_alloc_request, -+ .free_request = at91_ep_free_request, -+ .alloc_buffer = at91_ep_alloc_buffer, -+ .free_buffer = at91_ep_free_buffer, -+ .queue = at91_ep_queue, -+ .dequeue = at91_ep_dequeue, -+ .set_halt = at91_ep_set_halt, -+ // there's only imprecise fifo status reporting -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int at91_get_frame(struct usb_gadget *gadget) -+{ -+ if (!to_udc(gadget)->clocked) -+ return -EINVAL; -+ return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM; -+} -+ -+static int at91_wakeup(struct usb_gadget *gadget) -+{ -+ struct at91_udc *udc = to_udc(gadget); -+ u32 glbstate; -+ int status = -EINVAL; -+ unsigned long flags; -+ -+ DBG("%s\n", __FUNCTION__ ); -+ local_irq_save(flags); -+ -+ if (!udc->clocked || !udc->suspended) -+ goto done; -+ -+ /* NOTE: some "early versions" handle ESR differently ... */ -+ -+ glbstate = at91_udp_read(AT91_UDP_GLB_STAT); -+ if (!(glbstate & AT91_UDP_ESR)) -+ goto done; -+ glbstate |= AT91_UDP_ESR; -+ at91_udp_write(AT91_UDP_GLB_STAT, glbstate); -+ -+done: -+ local_irq_restore(flags); -+ return status; -+} -+ -+/* reinit == restore inital software state */ -+static void udc_reinit(struct at91_udc *udc) -+{ -+ u32 i; -+ -+ INIT_LIST_HEAD(&udc->gadget.ep_list); -+ INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); -+ -+ for (i = 0; i < NUM_ENDPOINTS; i++) { -+ struct at91_ep *ep = &udc->ep[i]; -+ -+ if (i != 0) -+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); -+ ep->desc = NULL; -+ ep->stopped = 0; -+ ep->fifo_bank = 0; -+ ep->ep.maxpacket = ep->maxpacket; -+ // initialiser une queue par endpoint -+ INIT_LIST_HEAD(&ep->queue); -+ } -+} -+ -+static void stop_activity(struct at91_udc *udc) -+{ -+ struct usb_gadget_driver *driver = udc->driver; -+ int i; -+ -+ if (udc->gadget.speed == USB_SPEED_UNKNOWN) -+ driver = NULL; -+ udc->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ for (i = 0; i < NUM_ENDPOINTS; i++) { -+ struct at91_ep *ep = &udc->ep[i]; -+ ep->stopped = 1; -+ nuke(ep, -ESHUTDOWN); -+ } -+ if (driver) -+ driver->disconnect(&udc->gadget); -+ -+ udc_reinit(udc); -+} -+ -+static void clk_on(struct at91_udc *udc) -+{ -+ if (udc->clocked) -+ return; -+ udc->clocked = 1; -+ clk_enable(udc->iclk); -+ clk_enable(udc->fclk); -+} -+ -+static void clk_off(struct at91_udc *udc) -+{ -+ if (!udc->clocked) -+ return; -+ udc->clocked = 0; -+ udc->gadget.speed = USB_SPEED_UNKNOWN; -+ clk_disable(udc->iclk); -+ clk_disable(udc->fclk); -+} -+ -+/* -+ * activate/deactivate link with host; minimize power usage for -+ * inactive links by cutting clocks and transceiver power. -+ */ -+static void pullup(struct at91_udc *udc, int is_on) -+{ -+ if (!udc->enabled || !udc->vbus) -+ is_on = 0; -+ DBG("%sactive\n", is_on ? "" : "in"); -+ if (is_on) { -+ clk_on(udc); -+ at91_udp_write(AT91_UDP_TXVC, 0); -+ at91_set_gpio_value(udc->board.pullup_pin, 1); -+ } else { -+ stop_activity(udc); -+ at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); -+ at91_set_gpio_value(udc->board.pullup_pin, 0); -+ clk_off(udc); -+ -+ // REVISIT: with transceiver disabled, will D- float -+ // so that a host would falsely detect a device? -+ } -+} -+ -+/* vbus is here! turn everything on that's ready */ -+static int at91_vbus_session(struct usb_gadget *gadget, int is_active) -+{ -+ struct at91_udc *udc = to_udc(gadget); -+ unsigned long flags; -+ -+ // VDBG("vbus %s\n", is_active ? "on" : "off"); -+ local_irq_save(flags); -+ udc->vbus = (is_active != 0); -+ pullup(udc, is_active); -+ local_irq_restore(flags); -+ return 0; -+} -+ -+static int at91_pullup(struct usb_gadget *gadget, int is_on) -+{ -+ struct at91_udc *udc = to_udc(gadget); -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ udc->enabled = is_on = !!is_on; -+ pullup(udc, is_on); -+ local_irq_restore(flags); -+ return 0; -+} -+ -+static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on) -+{ -+ struct at91_udc *udc = to_udc(gadget); -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ udc->selfpowered = (is_on != 0); -+ local_irq_restore(flags); -+ return 0; -+} -+ -+static const struct usb_gadget_ops at91_udc_ops = { -+ .get_frame = at91_get_frame, -+ .wakeup = at91_wakeup, -+ .set_selfpowered = at91_set_selfpowered, -+ .vbus_session = at91_vbus_session, -+ .pullup = at91_pullup, -+ -+ /* -+ * VBUS-powered devices may also also want to support bigger -+ * power budgets after an appropriate SET_CONFIGURATION. -+ */ -+ // .vbus_power = at91_vbus_power, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int handle_ep(struct at91_ep *ep) -+{ -+ struct at91_request *req; -+ u32 __iomem *creg = ep->creg; -+ u32 csr = __raw_readl(creg); -+ -+ if (!list_empty(&ep->queue)) -+ req = list_entry(ep->queue.next, -+ struct at91_request, queue); -+ else -+ req = NULL; -+ -+ if (ep->is_in) { -+ if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) { -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP); -+ __raw_writel(csr, creg); -+ } -+ if (req) -+ return write_fifo(ep, req); -+ -+ } else { -+ if (csr & AT91_UDP_STALLSENT) { -+ /* STALLSENT bit == ISOERR */ -+ if (ep->is_iso && req) -+ req->req.status = -EILSEQ; -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_STALLSENT); -+ __raw_writel(csr, creg); -+ csr = __raw_readl(creg); -+ } -+ if (req && (csr & RX_DATA_READY)) -+ return read_fifo(ep, req); -+ } -+ return 0; -+} -+ -+union setup { -+ u8 raw[8]; -+ struct usb_ctrlrequest r; -+}; -+ -+static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr) -+{ -+ u32 __iomem *creg = ep->creg; -+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0)); -+ unsigned rxcount, i = 0; -+ u32 tmp; -+ union setup pkt; -+ int status = 0; -+ -+ /* read and ack SETUP; hard-fail for bogus packets */ -+ rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16; -+ if (likely(rxcount == 8)) { -+ while (rxcount--) -+ pkt.raw[i++] = __raw_readb(dreg); -+ if (pkt.r.bRequestType & USB_DIR_IN) { -+ csr |= AT91_UDP_DIR; -+ ep->is_in = 1; -+ } else { -+ csr &= ~AT91_UDP_DIR; -+ ep->is_in = 0; -+ } -+ } else { -+ // REVISIT this happens sometimes under load; why?? -+ ERR("SETUP len %d, csr %08x\n", rxcount, csr); -+ status = -EINVAL; -+ } -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_RXSETUP); -+ __raw_writel(csr, creg); -+ udc->wait_for_addr_ack = 0; -+ udc->wait_for_config_ack = 0; -+ ep->stopped = 0; -+ if (unlikely(status != 0)) -+ goto stall; -+ -+#define w_index le16_to_cpu(pkt.r.wIndex) -+#define w_value le16_to_cpu(pkt.r.wValue) -+#define w_length le16_to_cpu(pkt.r.wLength) -+ -+ VDBG("SETUP %02x.%02x v%04x i%04x l%04x\n", -+ pkt.r.bRequestType, pkt.r.bRequest, -+ w_value, w_index, w_length); -+ -+ /* -+ * A few standard requests get handled here, ones that touch -+ * hardware ... notably for device and endpoint features. -+ */ -+ udc->req_pending = 1; -+ csr = __raw_readl(creg); -+ csr |= CLR_FX; -+ csr &= ~SET_FX; -+ switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) { -+ -+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) -+ | USB_REQ_SET_ADDRESS: -+ __raw_writel(csr | AT91_UDP_TXPKTRDY, creg); -+ udc->addr = w_value; -+ udc->wait_for_addr_ack = 1; -+ udc->req_pending = 0; -+ /* FADDR is set later, when we ack host STATUS */ -+ return; -+ -+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) -+ | USB_REQ_SET_CONFIGURATION: -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG; -+ if (pkt.r.wValue) -+ udc->wait_for_config_ack = (tmp == 0); -+ else -+ udc->wait_for_config_ack = (tmp != 0); -+ if (udc->wait_for_config_ack) -+ VDBG("wait for config\n"); -+ /* CONFG is toggled later, if gadget driver succeeds */ -+ break; -+ -+ /* -+ * Hosts may set or clear remote wakeup status, and -+ * devices may report they're VBUS powered. -+ */ -+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) -+ | USB_REQ_GET_STATUS: -+ tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED); -+ if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR) -+ tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP); -+ PACKET("get device status\n"); -+ __raw_writeb(tmp, dreg); -+ __raw_writeb(0, dreg); -+ goto write_in; -+ /* then STATUS starts later, automatically */ -+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) -+ | USB_REQ_SET_FEATURE: -+ if (w_value != USB_DEVICE_REMOTE_WAKEUP) -+ goto stall; -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT); -+ tmp |= AT91_UDP_ESR; -+ at91_udp_write(AT91_UDP_GLB_STAT, tmp); -+ goto succeed; -+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8) -+ | USB_REQ_CLEAR_FEATURE: -+ if (w_value != USB_DEVICE_REMOTE_WAKEUP) -+ goto stall; -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT); -+ tmp &= ~AT91_UDP_ESR; -+ at91_udp_write(AT91_UDP_GLB_STAT, tmp); -+ goto succeed; -+ -+ /* -+ * Interfaces have no feature settings; this is pretty useless. -+ * we won't even insist the interface exists... -+ */ -+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) -+ | USB_REQ_GET_STATUS: -+ PACKET("get interface status\n"); -+ __raw_writeb(0, dreg); -+ __raw_writeb(0, dreg); -+ goto write_in; -+ /* then STATUS starts later, automatically */ -+ case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) -+ | USB_REQ_SET_FEATURE: -+ case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8) -+ | USB_REQ_CLEAR_FEATURE: -+ goto stall; -+ -+ /* -+ * Hosts may clear bulk/intr endpoint halt after the gadget -+ * driver sets it (not widely used); or set it (for testing) -+ */ -+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) -+ | USB_REQ_GET_STATUS: -+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK; -+ ep = &udc->ep[tmp]; -+ if (tmp > NUM_ENDPOINTS || (tmp && !ep->desc)) -+ goto stall; -+ -+ if (tmp) { -+ if ((w_index & USB_DIR_IN)) { -+ if (!ep->is_in) -+ goto stall; -+ } else if (ep->is_in) -+ goto stall; -+ } -+ PACKET("get %s status\n", ep->ep.name); -+ if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL) -+ tmp = (1 << USB_ENDPOINT_HALT); -+ else -+ tmp = 0; -+ __raw_writeb(tmp, dreg); -+ __raw_writeb(0, dreg); -+ goto write_in; -+ /* then STATUS starts later, automatically */ -+ case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) -+ | USB_REQ_SET_FEATURE: -+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK; -+ ep = &udc->ep[tmp]; -+ if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS) -+ goto stall; -+ if (!ep->desc || ep->is_iso) -+ goto stall; -+ if ((w_index & USB_DIR_IN)) { -+ if (!ep->is_in) -+ goto stall; -+ } else if (ep->is_in) -+ goto stall; -+ -+ tmp = __raw_readl(ep->creg); -+ tmp &= ~SET_FX; -+ tmp |= CLR_FX | AT91_UDP_FORCESTALL; -+ __raw_writel(tmp, ep->creg); -+ goto succeed; -+ case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8) -+ | USB_REQ_CLEAR_FEATURE: -+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK; -+ ep = &udc->ep[tmp]; -+ if (w_value != USB_ENDPOINT_HALT || tmp > NUM_ENDPOINTS) -+ goto stall; -+ if (tmp == 0) -+ goto succeed; -+ if (!ep->desc || ep->is_iso) -+ goto stall; -+ if ((w_index & USB_DIR_IN)) { -+ if (!ep->is_in) -+ goto stall; -+ } else if (ep->is_in) -+ goto stall; -+ -+ at91_udp_write(AT91_UDP_RST_EP, ep->int_mask); -+ at91_udp_write(AT91_UDP_RST_EP, 0); -+ tmp = __raw_readl(ep->creg); -+ tmp |= CLR_FX; -+ tmp &= ~(SET_FX | AT91_UDP_FORCESTALL); -+ __raw_writel(tmp, ep->creg); -+ if (!list_empty(&ep->queue)) -+ handle_ep(ep); -+ goto succeed; -+ } -+ -+#undef w_value -+#undef w_index -+#undef w_length -+ -+ /* pass request up to the gadget driver */ -+ status = udc->driver->setup(&udc->gadget, &pkt.r); -+ if (status < 0) { -+stall: -+ VDBG("req %02x.%02x protocol STALL; stat %d\n", -+ pkt.r.bRequestType, pkt.r.bRequest, status); -+ csr |= AT91_UDP_FORCESTALL; -+ __raw_writel(csr, creg); -+ udc->req_pending = 0; -+ } -+ return; -+ -+succeed: -+ /* immediate successful (IN) STATUS after zero length DATA */ -+ PACKET("ep0 in/status\n"); -+write_in: -+ csr |= AT91_UDP_TXPKTRDY; -+ __raw_writel(csr, creg); -+ udc->req_pending = 0; -+ return; -+} -+ -+static void handle_ep0(struct at91_udc *udc) -+{ -+ struct at91_ep *ep0 = &udc->ep[0]; -+ u32 __iomem *creg = ep0->creg; -+ u32 csr = __raw_readl(creg); -+ struct at91_request *req; -+ -+ if (unlikely(csr & AT91_UDP_STALLSENT)) { -+ nuke(ep0, -EPROTO); -+ udc->req_pending = 0; -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL); -+ __raw_writel(csr, creg); -+ VDBG("ep0 stalled\n"); -+ csr = __raw_readl(creg); -+ } -+ if (csr & AT91_UDP_RXSETUP) { -+ nuke(ep0, 0); -+ udc->req_pending = 0; -+ handle_setup(udc, ep0, csr); -+ return; -+ } -+ -+ if (list_empty(&ep0->queue)) -+ req = NULL; -+ else -+ req = list_entry(ep0->queue.next, struct at91_request, queue); -+ -+ /* host ACKed an IN packet that we sent */ -+ if (csr & AT91_UDP_TXCOMP) { -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_TXCOMP); -+ -+ /* write more IN DATA? */ -+ if (req && ep0->is_in) { -+ if (handle_ep(ep0)) -+ udc->req_pending = 0; -+ -+ /* -+ * Ack after: -+ * - last IN DATA packet (including GET_STATUS) -+ * - IN/STATUS for OUT DATA -+ * - IN/STATUS for any zero-length DATA stage -+ * except for the IN DATA case, the host should send -+ * an OUT status later, which we'll ack. -+ */ -+ } else { -+ udc->req_pending = 0; -+ __raw_writel(csr, creg); -+ -+ /* -+ * SET_ADDRESS takes effect only after the STATUS -+ * (to the original address) gets acked. -+ */ -+ if (udc->wait_for_addr_ack) { -+ u32 tmp; -+ -+ at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); -+ tmp = at91_udp_read(AT91_UDP_GLB_STAT); -+ tmp &= ~AT91_UDP_FADDEN; -+ if (udc->addr) -+ tmp |= AT91_UDP_FADDEN; -+ at91_udp_write(AT91_UDP_GLB_STAT, tmp); -+ -+ udc->wait_for_addr_ack = 0; -+ VDBG("address %d\n", udc->addr); -+ } -+ } -+ } -+ -+ /* OUT packet arrived ... */ -+ else if (csr & AT91_UDP_RX_DATA_BK0) { -+ csr |= CLR_FX; -+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0); -+ -+ /* OUT DATA stage */ -+ if (!ep0->is_in) { -+ if (req) { -+ if (handle_ep(ep0)) { -+ /* send IN/STATUS */ -+ PACKET("ep0 in/status\n"); -+ csr = __raw_readl(creg); -+ csr &= ~SET_FX; -+ csr |= CLR_FX | AT91_UDP_TXPKTRDY; -+ __raw_writel(csr, creg); -+ udc->req_pending = 0; -+ } -+ } else if (udc->req_pending) { -+ /* -+ * AT91 hardware has a hard time with this -+ * "deferred response" mode for control-OUT -+ * transfers. (For control-IN it's fine.) -+ * -+ * The normal solution leaves OUT data in the -+ * fifo until the gadget driver is ready. -+ * We couldn't do that here without disabling -+ * the IRQ that tells about SETUP packets, -+ * e.g. when the host gets impatient... -+ * -+ * Working around it by copying into a buffer -+ * would almost be a non-deferred response, -+ * except that it wouldn't permit reliable -+ * stalling of the request. Instead, demand -+ * that gadget drivers not use this mode. -+ */ -+ DBG("no control-OUT deferred responses!\n"); -+ __raw_writel(csr | AT91_UDP_FORCESTALL, creg); -+ udc->req_pending = 0; -+ } -+ -+ /* STATUS stage for control-IN; ack. */ -+ } else { -+ PACKET("ep0 out/status ACK\n"); -+ __raw_writel(csr, creg); -+ -+ /* "early" status stage */ -+ if (req) -+ done(ep0, req, 0); -+ } -+ } -+} -+ -+static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) -+{ -+ struct at91_udc *udc = _udc; -+ u32 rescans = 5; -+ -+ while (rescans--) { -+ u32 status = at91_udp_read(AT91_UDP_ISR); -+ -+ status &= at91_udp_read(AT91_UDP_IMR); -+ if (!status) -+ break; -+ -+ /* USB reset irq: not maskable */ -+ if (status & AT91_UDP_ENDBUSRES) { -+ at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS); -+ at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS); -+ /* Atmel code clears this irq twice */ -+ at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); -+ at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES); -+ VDBG("end bus reset\n"); -+ udc->addr = 0; -+ stop_activity(udc); -+ -+ /* enable ep0 */ -+ at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); -+ udc->gadget.speed = USB_SPEED_FULL; -+ udc->suspended = 0; -+ at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); -+ -+ /* -+ * NOTE: this driver keeps clocks off unless the -+ * USB host is present. That saves power, and also -+ * eliminates IRQs (reset, resume, suspend) that can -+ * otherwise flood from the controller. If your -+ * board doesn't support VBUS detection, suspend and -+ * resume irq logic may need more attention... -+ */ -+ -+ /* host initiated suspend (3+ms bus idle) */ -+ } else if (status & AT91_UDP_RXSUSP) { -+ at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP); -+ at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM); -+ at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP); -+ // VDBG("bus suspend\n"); -+ if (udc->suspended) -+ continue; -+ udc->suspended = 1; -+ -+ /* -+ * NOTE: when suspending a VBUS-powered device, the -+ * gadget driver should switch into slow clock mode -+ * and then into standby to avoid drawing more than -+ * 500uA power (2500uA for some high-power configs). -+ */ -+ if (udc->driver && udc->driver->suspend) -+ udc->driver->suspend(&udc->gadget); -+ -+ /* host initiated resume */ -+ } else if (status & AT91_UDP_RXRSM) { -+ at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM); -+ at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP); -+ at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM); -+ // VDBG("bus resume\n"); -+ if (!udc->suspended) -+ continue; -+ udc->suspended = 0; -+ -+ /* -+ * NOTE: for a VBUS-powered device, the gadget driver -+ * would normally want to switch out of slow clock -+ * mode into normal mode. -+ */ -+ if (udc->driver && udc->driver->resume) -+ udc->driver->resume(&udc->gadget); -+ -+ /* endpoint IRQs are cleared by handling them */ -+ } else { -+ int i; -+ unsigned mask = 1; -+ struct at91_ep *ep = &udc->ep[1]; -+ -+ if (status & mask) -+ handle_ep0(udc); -+ for (i = 1; i < NUM_ENDPOINTS; i++) { -+ mask <<= 1; -+ if (status & mask) -+ handle_ep(ep); -+ ep++; -+ } -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct at91_udc controller = { -+ .gadget = { -+ .ops = &at91_udc_ops, -+ .ep0 = &controller.ep[0].ep, -+ .name = driver_name, -+ .dev = { -+ .bus_id = "gadget" -+ } -+ }, -+ .ep[0] = { -+ .ep = { -+ .name = ep0name, -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .maxpacket = 8, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), -+ .int_mask = 1 << 0, -+ }, -+ .ep[1] = { -+ .ep = { -+ .name = "ep1", -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .is_pingpong = 1, -+ .maxpacket = 64, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), -+ .int_mask = 1 << 1, -+ }, -+ .ep[2] = { -+ .ep = { -+ .name = "ep2", -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .is_pingpong = 1, -+ .maxpacket = 64, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), -+ .int_mask = 1 << 2, -+ }, -+ .ep[3] = { -+ .ep = { -+ /* could actually do bulk too */ -+ .name = "ep3-int", -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .maxpacket = 8, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), -+ .int_mask = 1 << 3, -+ }, -+ .ep[4] = { -+ .ep = { -+ .name = "ep4", -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .is_pingpong = 1, -+ .maxpacket = 256, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), -+ .int_mask = 1 << 4, -+ }, -+ .ep[5] = { -+ .ep = { -+ .name = "ep5", -+ .ops = &at91_ep_ops, -+ }, -+ .udc = &controller, -+ .is_pingpong = 1, -+ .maxpacket = 256, -+ .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), -+ .int_mask = 1 << 5, -+ }, -+ /* ep6 and ep7 are also reserved */ -+}; -+ -+static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) -+{ -+ struct at91_udc *udc = _udc; -+ unsigned value; -+ -+ /* vbus needs at least brief debouncing */ -+ udelay(10); -+ value = at91_get_gpio_value(udc->board.vbus_pin); -+ if (value != udc->vbus) -+ at91_vbus_session(&udc->gadget, value); -+ -+ return IRQ_HANDLED; -+} -+ -+int usb_gadget_register_driver (struct usb_gadget_driver *driver) -+{ -+ struct at91_udc *udc = &controller; -+ int retval; -+ -+ if (!driver -+ || driver->speed != USB_SPEED_FULL -+ || !driver->bind -+ || !driver->unbind -+ || !driver->setup) { -+ DBG("bad parameter.\n"); -+ return -EINVAL; -+ } -+ -+ if (udc->driver) { -+ DBG("UDC already has a gadget driver\n"); -+ return -EBUSY; -+ } -+ -+ udc->driver = driver; -+ udc->gadget.dev.driver = &driver->driver; -+ udc->gadget.dev.driver_data = &driver->driver; -+ udc->enabled = 1; -+ udc->selfpowered = 1; -+ -+ retval = driver->bind(&udc->gadget); -+ if (retval) { -+ DBG("driver->bind() returned %d\n", retval); -+ udc->driver = NULL; -+ return retval; -+ } -+ -+ local_irq_disable(); -+ pullup(udc, 1); -+ local_irq_enable(); -+ -+ DBG("bound to %s\n", driver->driver.name); -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_register_driver); -+ -+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) -+{ -+ struct at91_udc *udc = &controller; -+ -+ if (!driver || driver != udc->driver) -+ return -EINVAL; -+ -+ local_irq_disable(); -+ udc->enabled = 0; -+ pullup(udc, 0); -+ local_irq_enable(); -+ -+ driver->unbind(&udc->gadget); -+ udc->driver = NULL; -+ -+ DBG("unbound from %s\n", driver->driver.name); -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_unregister_driver); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void at91udc_shutdown(struct platform_device *dev) -+{ -+ /* force disconnect on reboot */ -+ pullup(platform_get_drvdata(dev), 0); -+} -+ -+static int __devinit at91udc_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct at91_udc *udc; -+ int retval; -+ -+ if (!dev->platform_data) { -+ /* small (so we copy it) but critical! */ -+ DBG("missing platform_data\n"); -+ return -ENODEV; -+ } -+ -+ if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { -+ DBG("someone's using UDC memory\n"); -+ return -EBUSY; -+ } -+ -+ /* init software state */ -+ udc = &controller; -+ udc->gadget.dev.parent = dev; -+ udc->board = *(struct at91_udc_data *) dev->platform_data; -+ udc->pdev = pdev; -+ udc_reinit(udc); -+ udc->enabled = 0; -+ -+ /* get interface and function clocks */ -+ udc->iclk = clk_get(dev, "udc_clk"); -+ udc->fclk = clk_get(dev, "udpck"); -+ if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { -+ DBG("clocks missing\n"); -+ return -ENODEV; -+ } -+ -+ retval = device_register(&udc->gadget.dev); -+ if (retval < 0) -+ goto fail0; -+ -+ /* disable everything until there's a gadget driver and vbus */ -+ pullup(udc, 0); -+ -+ /* request UDC and maybe VBUS irqs */ -+ if (request_irq(AT91_ID_UDP, at91_udc_irq, SA_INTERRUPT, driver_name, udc)) { -+ DBG("request irq %d failed\n", AT91_ID_UDP); -+ retval = -EBUSY; -+ goto fail1; -+ } -+ if (udc->board.vbus_pin > 0) { -+ if (request_irq(udc->board.vbus_pin, at91_vbus_irq, SA_INTERRUPT, driver_name, udc)) { -+ DBG("request vbus irq %d failed\n", udc->board.vbus_pin); -+ free_irq(AT91_ID_UDP, udc); -+ retval = -EBUSY; -+ goto fail1; -+ } -+ } else { -+ DBG("no VBUS detection, assuming always-on\n"); -+ udc->vbus = 1; -+ } -+ dev_set_drvdata(dev, udc); -+ create_debug_file(udc); -+ -+ INFO("%s version %s\n", driver_name, DRIVER_VERSION); -+ return 0; -+ -+fail1: -+ device_unregister(&udc->gadget.dev); -+fail0: -+ release_mem_region(AT91_VA_BASE_UDP, SZ_16K); -+ DBG("%s probe failed, %d\n", driver_name, retval); -+ return retval; -+} -+ -+static int __devexit at91udc_remove(struct platform_device *dev) -+{ -+ struct at91_udc *udc = platform_get_drvdata(dev); -+ -+ DBG("remove\n"); -+ -+ pullup(udc, 0); -+ -+ if (udc->driver != 0) -+ usb_gadget_unregister_driver(udc->driver); -+ -+ remove_debug_file(udc); -+ if (udc->board.vbus_pin > 0) -+ free_irq(udc->board.vbus_pin, udc); -+ free_irq(AT91_ID_UDP, udc); -+ device_unregister(&udc->gadget.dev); -+ release_mem_region(AT91_BASE_UDP, SZ_16K); -+ -+ clk_put(udc->iclk); -+ clk_put(udc->fclk); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int at91udc_suspend(struct platform_device *dev, u32 state, u32 level) -+{ -+ struct at91_udc *udc = platform_get_drvdata(dev); -+ -+ /* -+ * The "safe" suspend transitions are opportunistic ... e.g. when -+ * the USB link is suspended (48MHz clock autogated off), or when -+ * it's disconnected (programmatically gated off, elsewhere). -+ * Then we can suspend, and the chip can enter slow clock mode. -+ * -+ * The problem case is some component (user mode?) suspending this -+ * device while it's active, with the 48 MHz clock in use. There -+ * are two basic approaches: (a) veto suspend levels involving slow -+ * clock mode, (b) disconnect, so 48 MHz will no longer be in use -+ * and we can enter slow clock mode. This uses (b) for now, since -+ * it's simplest until AT91 PM exists and supports the other option. -+ */ -+ if (udc->vbus && !udc->suspended) -+ pullup(udc, 0); -+ return 0; -+} -+ -+static int at91udc_resume(struct platform_device *dev, u32 level) -+{ -+ struct at91_udc *udc = platform_get_drvdata(dev); -+ -+ /* maybe reconnect to host; if so, clocks on */ -+ pullup(udc, 1); -+ return 0; -+} -+#else -+#define at91udc_suspend NULL -+#define at91udc_resume NULL -+#endif -+ -+static struct platform_driver at91_udc = { -+ .probe = at91udc_probe, -+ .remove = __devexit_p(at91udc_remove), -+ .shutdown = at91udc_shutdown, -+ .suspend = at91udc_suspend, -+ .resume = at91udc_resume, -+ .driver = { -+ .name = (char *) driver_name, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __devinit udc_init_module(void) -+{ -+ return platform_driver_register(&at91_udc); -+} -+module_init(udc_init_module); -+ -+static void __devexit udc_exit_module(void) -+{ -+ platform_driver_unregister(&at91_udc); -+} -+module_exit(udc_exit_module); -+ -+MODULE_DESCRIPTION("AT91RM9200 udc driver"); -+MODULE_AUTHOR("Thomas Rathbone, David Brownell"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ gregkh-2.6/drivers/usb/gadget/at91_udc.h -@@ -0,0 +1,181 @@ -+/* -+ * Copyright (C) 2004 by Thomas Rathbone, HP Labs -+ * Copyright (C) 2005 by Ivan Kokshaysky -+ * Copyright (C) 2006 by SAN People -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the -+ * Free Software Foundation, Inc., -+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ */ -+ -+#ifndef AT91_UDC_H -+#define AT91_UDC_H -+ -+/* -+ * USB Device Port (UDP) registers. -+ * Based on AT91RM9200 datasheet revision E. -+ */ -+ -+#define AT91_UDP_FRM_NUM 0x00 /* Frame Number Register */ -+#define AT91_UDP_NUM (0x7ff << 0) /* Frame Number */ -+#define AT91_UDP_FRM_ERR (1 << 16) /* Frame Error */ -+#define AT91_UDP_FRM_OK (1 << 17) /* Frame OK */ -+ -+#define AT91_UDP_GLB_STAT 0x04 /* Global State Register */ -+#define AT91_UDP_FADDEN (1 << 0) /* Function Address Enable */ -+#define AT91_UDP_CONFG (1 << 1) /* Configured */ -+#define AT91_UDP_ESR (1 << 2) /* Enable Send Resume */ -+#define AT91_UDP_RSMINPR (1 << 3) /* Resume has been sent */ -+#define AT91_UDP_RMWUPE (1 << 4) /* Remote Wake Up Enable */ -+ -+#define AT91_UDP_FADDR 0x08 /* Function Address Register */ -+#define AT91_UDP_FADD (0x7f << 0) /* Function Address Value */ -+#define AT91_UDP_FEN (1 << 8) /* Function Enable */ -+ -+#define AT91_UDP_IER 0x10 /* Interrupt Enable Register */ -+#define AT91_UDP_IDR 0x14 /* Interrupt Disable Register */ -+#define AT91_UDP_IMR 0x18 /* Interrupt Mask Register */ -+ -+#define AT91_UDP_ISR 0x1c /* Interrupt Status Register */ -+#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */ -+#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */ -+#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */ -+#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */ -+#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */ -+#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */ -+#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */ -+ -+#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */ -+#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */ -+ -+#define AT91_UDP_CSR(n) (0x30+((n)*4)) /* Endpoint Control/Status Registers 0-7 */ -+#define AT91_UDP_TXCOMP (1 << 0) /* Generates IN packet with data previously written in DPR */ -+#define AT91_UDP_RX_DATA_BK0 (1 << 1) /* Receive Data Bank 0 */ -+#define AT91_UDP_RXSETUP (1 << 2) /* Send STALL to the host */ -+#define AT91_UDP_STALLSENT (1 << 3) /* Stall Sent / Isochronous error (Isochronous endpoints) */ -+#define AT91_UDP_TXPKTRDY (1 << 4) /* Transmit Packet Ready */ -+#define AT91_UDP_FORCESTALL (1 << 5) /* Force Stall */ -+#define AT91_UDP_RX_DATA_BK1 (1 << 6) /* Receive Data Bank 1 */ -+#define AT91_UDP_DIR (1 << 7) /* Transfer Direction */ -+#define AT91_UDP_EPTYPE (7 << 8) /* Endpoint Type */ -+#define AT91_UDP_EPTYPE_CTRL (0 << 8) -+#define AT91_UDP_EPTYPE_ISO_OUT (1 << 8) -+#define AT91_UDP_EPTYPE_BULK_OUT (2 << 8) -+#define AT91_UDP_EPTYPE_INT_OUT (3 << 8) -+#define AT91_UDP_EPTYPE_ISO_IN (5 << 8) -+#define AT91_UDP_EPTYPE_BULK_IN (6 << 8) -+#define AT91_UDP_EPTYPE_INT_IN (7 << 8) -+#define AT91_UDP_DTGLE (1 << 11) /* Data Toggle */ -+#define AT91_UDP_EPEDS (1 << 15) /* Endpoint Enable/Disable */ -+#define AT91_UDP_RXBYTECNT (0x7ff << 16) /* Number of bytes in FIFO */ -+ -+#define AT91_UDP_FDR(n) (0x50+((n)*4)) /* Endpoint FIFO Data Registers 0-7 */ -+ -+#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */ -+#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * controller driver data structures -+ */ -+ -+#define NUM_ENDPOINTS 6 -+ -+/* -+ * hardware won't disable bus reset, or resume while the controller -+ * is suspended ... watching suspend helps keep the logic symmetric. -+ */ -+#define MINIMUS_INTERRUPTUS \ -+ (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP) -+ -+struct at91_ep { -+ struct usb_ep ep; -+ struct list_head queue; -+ struct at91_udc *udc; -+ void __iomem *creg; -+ -+ unsigned maxpacket:16; -+ u8 int_mask; -+ unsigned is_pingpong:1; -+ -+ unsigned stopped:1; -+ unsigned is_in:1; -+ unsigned is_iso:1; -+ unsigned fifo_bank:1; -+ -+ const struct usb_endpoint_descriptor -+ *desc; -+}; -+ -+/* -+ * driver is non-SMP, and just blocks IRQs whenever it needs -+ * access protection for chip registers or driver state -+ */ -+struct at91_udc { -+ struct usb_gadget gadget; -+ struct at91_ep ep[NUM_ENDPOINTS]; -+ struct usb_gadget_driver *driver; -+ unsigned vbus:1; -+ unsigned enabled:1; -+ unsigned clocked:1; -+ unsigned suspended:1; -+ unsigned req_pending:1; -+ unsigned wait_for_addr_ack:1; -+ unsigned wait_for_config_ack:1; -+ unsigned selfpowered:1; -+ u8 addr; -+ struct at91_udc_data board; -+ struct clk *iclk, *fclk; -+ struct platform_device *pdev; -+ struct proc_dir_entry *pde; -+}; -+ -+static inline struct at91_udc *to_udc(struct usb_gadget *g) -+{ -+ return container_of(g, struct at91_udc, gadget); -+} -+ -+struct at91_request { -+ struct usb_request req; -+ struct list_head queue; -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+#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 -+ -+#ifdef PACKET_TRACE -+# define PACKET VDBG -+#else -+# 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) -+ -+#endif -+ diff --git a/usb/usb-add-support-for-creativelabs-silvercrest-usb-keyboard.patch b/usb/usb-add-support-for-creativelabs-silvercrest-usb-keyboard.patch deleted file mode 100644 index e1559fd6a8e64..0000000000000 --- a/usb/usb-add-support-for-creativelabs-silvercrest-usb-keyboard.patch +++ /dev/null @@ -1,34 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Wed Mar 8 08:00:38 2006 -From: Wolfgang Rohdewald <wolfgang@rohdewald.de> -Subject: USB: add support for Creativelabs Silvercrest USB keyboard -Content-Disposition: inline -Message-Id: <200603081659.51267.wolfgang@rohdewald.de> -Date: Wed, 8 Mar 2006 16:59:44 +0100 - -Signed-off-by: Wolfgang Rohdewald <wolfgang@rohdewald.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/input/hid-core.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/input/hid-core.c -+++ gregkh-2.6/drivers/usb/input/hid-core.c -@@ -1552,6 +1552,9 @@ void hid_init_reports(struct hid_device - #define USB_VENDOR_ID_HP 0x03f0 - #define USB_DEVICE_ID_HP_USBHUB_KB 0x020c - -+#define USB_VENDOR_ID_CREATIVELABS 0x062a -+#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST 0x0201 -+ - /* - * Alphabetically sorted blacklist by quirk type. - */ -@@ -1668,6 +1671,7 @@ static const struct hid_blacklist { - { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET}, - { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET}, -+ { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, - { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, diff --git a/usb/usb-add-support-for-ochi-on-at91rm9200.patch b/usb/usb-add-support-for-ochi-on-at91rm9200.patch deleted file mode 100644 index 14fc474e19004..0000000000000 --- a/usb/usb-add-support-for-ochi-on-at91rm9200.patch +++ /dev/null @@ -1,378 +0,0 @@ -From david-b@pacbell.net Sun Jan 22 11:29:00 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: add support for OCHI on AT91rm9200 -Date: Sun, 22 Jan 2006 10:32:13 -0800 -Cc: Andrew Victor <andrew@sanpeople.com> -Message-Id: <200601221032.13463.david-b@pacbell.net> - -From: Andrew Victor <andrew@sanpeople.com> - -This adds support for OHCI on AT91rm9200 based boards. - -Possibly of interest here is the way this uses <linux/clk.h> to -gate clocks on/off during system pm state transitions. That's -typical for non-PCI systems. Some can go further; Mini-A host -side connectors enable ID-pin sensing. - -From: Andrew Victor <andrew@sanpeople.com> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/Kconfig | 1 - drivers/usb/Makefile | 1 - drivers/usb/host/ohci-at91.c | 306 +++++++++++++++++++++++++++++++++++++++++++ - drivers/usb/host/ohci-hcd.c | 5 - 4 files changed, 313 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/Kconfig -+++ gregkh-2.6/drivers/usb/Kconfig -@@ -23,6 +23,7 @@ config USB_ARCH_HAS_OHCI - default y if ARCH_LH7A404 - default y if ARCH_S3C2410 - default y if PXA27x -+ default y if ARCH_AT91RM9200 - # PPC: - default y if STB03xxx - default y if PPC_MPC52xx ---- gregkh-2.6.orig/drivers/usb/Makefile -+++ gregkh-2.6/drivers/usb/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/ - obj-$(CONFIG_USB_UHCI_HCD) += host/ - obj-$(CONFIG_USB_SL811_HCD) += host/ - obj-$(CONFIG_ETRAX_USB_HOST) += host/ -+obj-$(CONFIG_USB_OHCI_AT91) += host/ - - obj-$(CONFIG_USB_ACM) += class/ - obj-$(CONFIG_USB_PRINTER) += class/ ---- /dev/null -+++ gregkh-2.6/drivers/usb/host/ohci-at91.c -@@ -0,0 +1,306 @@ -+/* -+ * OHCI HCD (Host Controller Driver) for USB. -+ * -+ * Copyright (C) 2004 SAN People (Pty) Ltd. -+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> -+ * -+ * AT91RM9200 Bus Glue -+ * -+ * Based on fragments of 2.4 driver by Rick Bronson. -+ * Based on ohci-omap.c -+ * -+ * This file is licenced under the GPL. -+ */ -+ -+#include <linux/clk.h> -+#include <linux/platform_device.h> -+ -+#include <asm/mach-types.h> -+#include <asm/hardware.h> -+#include <asm/arch/board.h> -+ -+#ifndef CONFIG_ARCH_AT91RM9200 -+#error "This file is AT91RM9200 bus glue. CONFIG_ARCH_AT91RM9200 must be defined." -+#endif -+ -+/* interface and function clocks */ -+static struct clk *iclk, *fclk; -+ -+extern int usb_disabled(void); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void at91_start_hc(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ struct ohci_regs __iomem *regs = hcd->regs; -+ -+ dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); -+ -+ /* -+ * Start the USB clocks. -+ */ -+ clk_enable(iclk); -+ clk_enable(fclk); -+ -+ /* -+ * The USB host controller must remain in reset. -+ */ -+ writel(0, ®s->control); -+} -+ -+static void at91_stop_hc(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ struct ohci_regs __iomem *regs = hcd->regs; -+ -+ dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); -+ -+ /* -+ * Put the USB host controller into reset. -+ */ -+ writel(0, ®s->control); -+ -+ /* -+ * Stop the USB clocks. -+ */ -+ clk_disable(fclk); -+ clk_disable(iclk); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); -+ -+/* configure so an HC device and id are always provided */ -+/* always called with process context; sleeping is OK */ -+ -+ -+/** -+ * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs -+ * Context: !in_interrupt() -+ * -+ * Allocates basic resources for this USB host controller, and -+ * then invokes the start() method for the HCD associated with it -+ * through the hotplug entry's driver_data. -+ * -+ * Store this function in the HCD's struct pci_driver as probe(). -+ */ -+int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) -+{ -+ int retval; -+ struct usb_hcd *hcd = NULL; -+ -+ if (pdev->num_resources != 2) { -+ pr_debug("hcd probe: invalid num_resources"); -+ return -ENODEV; -+ } -+ -+ if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { -+ pr_debug("hcd probe: invalid resource type\n"); -+ return -ENODEV; -+ } -+ -+ hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); -+ if (!hcd) -+ return -ENOMEM; -+ hcd->rsrc_start = pdev->resource[0].start; -+ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; -+ -+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -+ pr_debug("request_mem_region failed\n"); -+ retval = -EBUSY; -+ goto err1; -+ } -+ -+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -+ if (!hcd->regs) { -+ pr_debug("ioremap failed\n"); -+ retval = -EIO; -+ goto err2; -+ } -+ -+ iclk = clk_get(&pdev->dev, "ohci_clk"); -+ fclk = clk_get(&pdev->dev, "uhpck"); -+ -+ at91_start_hc(pdev); -+ ohci_hcd_init(hcd_to_ohci(hcd)); -+ -+ retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); -+ if (retval == 0) -+ return retval; -+ -+ /* Error handling */ -+ at91_stop_hc(pdev); -+ -+ clk_put(fclk); -+ clk_put(iclk); -+ -+ iounmap(hcd->regs); -+ -+ err2: -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ -+ err1: -+ usb_put_hcd(hcd); -+ return retval; -+} -+ -+ -+/* may be called without controller electrically present */ -+/* may be called with controller, bus, and devices active */ -+ -+/** -+ * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs -+ * @dev: USB Host Controller being removed -+ * Context: !in_interrupt() -+ * -+ * Reverses the effect of usb_hcd_at91_probe(), first invoking -+ * the HCD's stop() method. It is always called from a thread -+ * context, normally "rmmod", "apmd", or something similar. -+ * -+ */ -+static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) -+{ -+ usb_remove_hcd(hcd); -+ at91_stop_hc(pdev); -+ iounmap(hcd->regs); -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ -+ clk_put(fclk); -+ clk_put(iclk); -+ fclk = iclk = NULL; -+ -+ dev_set_drvdata(&pdev->dev, NULL); -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int __devinit -+ohci_at91_start (struct usb_hcd *hcd) -+{ -+// struct at91_ohci_data *board = hcd->self.controller->platform_data; -+ struct ohci_hcd *ohci = hcd_to_ohci (hcd); -+ int ret; -+ -+ if ((ret = ohci_init(ohci)) < 0) -+ return ret; -+ -+ if ((ret = ohci_run(ohci)) < 0) { -+ err("can't start %s", hcd->self.bus_name); -+ ohci_stop(hcd); -+ return ret; -+ } -+// hcd->self.root_hub->maxchild = board->ports; -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static const struct hc_driver ohci_at91_hc_driver = { -+ .description = hcd_name, -+ .product_desc = "AT91RM9200 OHCI", -+ .hcd_priv_size = sizeof(struct ohci_hcd), -+ -+ /* -+ * generic hardware linkage -+ */ -+ .irq = ohci_irq, -+ .flags = HCD_USB11 | HCD_MEMORY, -+ -+ /* -+ * basic lifecycle operations -+ */ -+ .start = ohci_at91_start, -+ .stop = ohci_stop, -+ -+ /* -+ * 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, -+ -+#ifdef CONFIG_PM -+ .hub_suspend = ohci_hub_suspend, -+ .hub_resume = ohci_hub_resume, -+#endif -+ .start_port_reset = ohci_start_port_reset, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int ohci_hcd_at91_drv_probe(struct platform_device *dev) -+{ -+ return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); -+} -+ -+static int ohci_hcd_at91_drv_remove(struct platform_device *dev) -+{ -+ return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); -+} -+ -+#ifdef CONFIG_PM -+static int ohci_hcd_at91_drv_suspend(struct platform_device *dev, u32 state, u32 level) -+{ -+ printk("%s(%s:%d): not implemented yet\n", -+ __func__, __FILE__, __LINE__); -+ -+ clk_disable(fclk); -+ -+ return 0; -+} -+ -+static int ohci_hcd_at91_drv_resume(struct platform_device *dev, u32 state) -+{ -+ printk("%s(%s:%d): not implemented yet\n", -+ __func__, __FILE__, __LINE__); -+ -+ clk_enable(fclk); -+ -+ return 0; -+} -+#else -+#define ohci_hcd_at91_drv_suspend NULL -+#define ohci_hcd_at91_drv_resume NULL -+#endif -+ -+static struct platform_driver ohci_hcd_at91_driver = { -+ .probe = ohci_hcd_at91_drv_probe, -+ .remove = ohci_hcd_at91_drv_remove, -+ .suspend = ohci_hcd_at91_drv_suspend, -+ .resume = ohci_hcd_at91_drv_resume, -+ .driver = { -+ .name = "at91rm9200-ohci", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init ohci_hcd_at91_init (void) -+{ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ return platform_driver_register(&ohci_hcd_at91_driver); -+} -+ -+static void __exit ohci_hcd_at91_cleanup (void) -+{ -+ platform_driver_unregister(&ohci_hcd_at91_driver); -+} -+ -+module_init (ohci_hcd_at91_init); -+module_exit (ohci_hcd_at91_cleanup); ---- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c -+++ gregkh-2.6/drivers/usb/host/ohci-hcd.c -@@ -905,6 +905,10 @@ MODULE_LICENSE ("GPL"); - #include "ohci-ppc-soc.c" - #endif - -+#ifdef CONFIG_ARCH_AT91RM9200 -+#include "ohci-at91.c" -+#endif -+ - #if !(defined(CONFIG_PCI) \ - || defined(CONFIG_SA1111) \ - || defined(CONFIG_ARCH_S3C2410) \ -@@ -913,6 +917,7 @@ MODULE_LICENSE ("GPL"); - || defined (CONFIG_PXA27x) \ - || defined (CONFIG_SOC_AU1X00) \ - || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ -+ || defined (CONFIG_ARCH_AT91RM9200) \ - ) - #error "missing bus glue for ohci-hcd" - #endif diff --git a/usb/usb-add-zc0301-video4linux2-driver.patch b/usb/usb-add-zc0301-video4linux2-driver.patch deleted file mode 100644 index 3e395f248ee79..0000000000000 --- a/usb/usb-add-zc0301-video4linux2-driver.patch +++ /dev/null @@ -1,3023 +0,0 @@ -From luca.risolia@studio.unibo.it Mon Feb 6 07:28:12 2006 -Date: Mon, 6 Feb 2006 16:29:35 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Cc: Mauro Carvalho <mchehab@brturbo.com.br> -Subject: USB: Add ZC0301 Video4Linux2 driver -Message-ID: <20060206162935.GA10356@studio.unibo.it> -Content-Disposition: inline - -This patch adds a Video4Linux2 driver for ZC0301 -Image Processor and Control Chip. - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/zc0301.txt | 250 ++++ - MAINTAINERS | 8 - drivers/usb/Makefile | 1 - drivers/usb/media/Kconfig | 15 - drivers/usb/media/Makefile | 2 - drivers/usb/media/zc0301.h | 185 +++ - drivers/usb/media/zc0301_core.c | 2028 +++++++++++++++++++++++++++++++++++ - drivers/usb/media/zc0301_pas202bcb.c | 353 ++++++ - drivers/usb/media/zc0301_sensor.h | 98 + - 9 files changed, 2940 insertions(+) - ---- /dev/null -+++ gregkh-2.6/Documentation/usb/zc0301.txt -@@ -0,0 +1,250 @@ -+ -+ ZC0301 Image Processor and Control Chip -+ Driver for Linux -+ ======================================= -+ -+ - Documentation - -+ -+ -+Index -+===== -+1. Copyright -+2. Disclaimer -+3. License -+4. Overview and features -+5. Module dependencies -+6. Module loading -+7. Module parameters -+8. Supported devices -+9. Notes for V4L2 application developers -+10. Contact information -+11. Credits -+ -+ -+1. Copyright -+============ -+Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> -+ -+ -+2. Disclaimer -+============= -+This software is not developed or sponsored by Z-Star Microelectronics Corp. -+Trademarks are property of their respective owner. -+ -+ -+3. License -+========== -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2 of the License, or -+(at your option) any later version. -+ -+This program is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with this program; if not, write to the Free Software -+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+ -+4. Overview and features -+======================== -+This driver supports the video interface of the devices mounting the ZC0301 -+Image Processor and Control Chip. -+ -+The driver relies on the Video4Linux2 and USB core modules. It has been -+designed to run properly on SMP systems as well. -+ -+The latest version of the ZC0301 driver can be found at the following URL: -+http://www.linux-projects.org/ -+ -+Some of the features of the driver are: -+ -+- full compliance with the Video4Linux2 API (see also "Notes for V4L2 -+ application developers" paragraph); -+- available mmap or read/poll methods for video streaming through isochronous -+ data transfers; -+- automatic detection of image sensor; -+- video formats is standard JPEG in various compression qualities -+ (see also "Notes for V4L2 application developers" paragraph); -+- full support for the capabilities of every possible image sensors that can -+ be connected to the ZC0301 bridges, including, for istance, red, green, -+ blue and global gain adjustments and exposure control (see "Supported -+ devices" paragraph for details); -+- use of default color settings for sunlight conditions; -+- dynamic driver control thanks to various module parameters (see "Module -+ parameters" paragraph); -+- up to 64 cameras can be handled at the same time; they can be connected and -+ disconnected from the host many times without turning off the computer, if -+ the system supports hotplugging; -+ -+ -+5. Module dependencies -+====================== -+For it to work properly, the driver needs kernel support for Video4Linux and -+USB. -+ -+The following options of the kernel configuration file must be enabled and -+corresponding modules must be compiled: -+ -+ # Multimedia devices -+ # -+ CONFIG_VIDEO_DEV=m -+ -+ # USB support -+ # -+ CONFIG_USB=m -+ -+In addition, depending on the hardware being used, the modules below are -+necessary: -+ -+ # USB Host Controller Drivers -+ # -+ CONFIG_USB_EHCI_HCD=m -+ CONFIG_USB_UHCI_HCD=m -+ CONFIG_USB_OHCI_HCD=m -+ -+The ZC0301 controller also provides a built-in microphone interface. It is -+supported by the USB Audio driver thanks to the ALSA API: -+ -+ # Sound -+ # -+ CONFIG_SOUND=y -+ -+ # Advanced Linux Sound Architecture -+ # -+ CONFIG_SND=m -+ -+ # USB devices -+ # -+ CONFIG_SND_USB_AUDIO=m -+ -+And finally: -+ -+ # USB Multimedia devices -+ # -+ CONFIG_USB_ZC0301=m -+ -+ -+6. Module loading -+================= -+To use the driver, it is necessary to load the "zc0301" module into memory -+after every other module required: "videodev", "usbcore" and, depending on -+the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd". -+ -+Loading can be done as shown below: -+ -+ [root@localhost home]# modprobe zc0301 -+ -+At this point the devices should be recognized. You can invoke "dmesg" to -+analyze kernel messages and verify that the loading process has gone well: -+ -+ [user@localhost home]$ dmesg -+ -+ -+7. Module parameters -+==================== -+Module parameters are listed below: -+------------------------------------------------------------------------------- -+Name: video_nr -+Type: short array (min = 0, max = 64) -+Syntax: <-1|n[,...]> -+Description: Specify V4L2 minor mode number: -+ -1 = use next available -+ n = use minor number n -+ You can specify up to 64 cameras this way. -+ For example: -+ video_nr=-1,2,-1 would assign minor number 2 to the second -+ registered camera and use auto for the first one and for every -+ other camera. -+Default: -1 -+------------------------------------------------------------------------------- -+Name: force_munmap -+Type: bool array (min = 0, max = 64) -+Syntax: <0|1[,...]> -+Description: Force the application to unmap previously mapped buffer memory -+ before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not -+ all the applications support this feature. This parameter is -+ specific for each detected camera. -+ 0 = do not force memory unmapping -+ 1 = force memory unmapping (save memory) -+Default: 0 -+------------------------------------------------------------------------------- -+Name: debug -+Type: ushort -+Syntax: <n> -+Description: Debugging information level, from 0 to 3: -+ 0 = none (use carefully) -+ 1 = critical errors -+ 2 = significant informations -+ 3 = more verbose messages -+ Level 3 is useful for testing only, when only one device -+ is used at the same time. It also shows some more informations -+ about the hardware being detected. This module parameter can be -+ changed at runtime thanks to the /sys filesystem interface. -+Default: 2 -+------------------------------------------------------------------------------- -+ -+ -+8. Supported devices -+==================== -+None of the names of the companies as well as their products will be mentioned -+here. They have never collaborated with the author, so no advertising. -+ -+From the point of view of a driver, what unambiguously identify a device are -+its vendor and product USB identifiers. Below is a list of known identifiers of -+devices mounting the ZC0301 Image Processor and Control Chips: -+ -+Vendor ID Product ID -+--------- ---------- -+0x046d 0x08ae -+ -+The following image sensors are supported: -+ -+Model Manufacturer -+----- ------------ -+PAS202BCB PixArt Imaging, Inc. -+ -+All the available control settings of each image sensor are supported through -+the V4L2 interface. -+ -+ -+9. Notes for V4L2 application developers -+======================================== -+This driver follows the V4L2 API specifications. In particular, it enforces two -+rules: -+ -+- exactly one I/O method, either "mmap" or "read", is associated with each -+file descriptor. Once it is selected, the application must close and reopen the -+device to switch to the other I/O method; -+ -+- although it is not mandatory, previously mapped buffer memory should always -+be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's. -+The same number of buffers as before will be allocated again to match the size -+of the new video frames, so you have to map the buffers again before any I/O -+attempts on them. -+ -+This driver supports the standard JPEG video format. The current compression -+quality may vary from 0 to 3 and can be selected or queried thanks to the -+VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. -+ -+ -+10. Contact information -+======================= -+The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>. -+ -+GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is -+'FCE635A4'; the public 1024-bit key should be available at any keyserver; -+the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'. -+ -+ -+11. Credits -+=========== -+- Informations about the chip internals to enable the I2C protocol have been -+ taken from the documentation of the ZC030x Video4Linux1 driver written by -+ Andrew Birkett <andy@nobugs.org>; -+- Initialization values of the ZC0301 connected to the PAS202BCB image sensor -+ have been taken from the SPCA5XX driver maintained by -+ Michel Xhaard <mxhaard@magic.fr> ---- gregkh-2.6.orig/MAINTAINERS -+++ gregkh-2.6/MAINTAINERS -@@ -2901,6 +2901,14 @@ L: video4linux-list@redhat.com - W: http://www.linux-projects.org - S: Maintained - -+USB ZC0301 DRIVER -+P: Luca Risolia -+M: luca.risolia@studio.unibo.it -+L: linux-usb-devel@lists.sourceforge.net -+L: video4linux-list@redhat.com -+W: http://www.linux-projects.org -+S: Maintained -+ - USB ZD1201 DRIVER - P: Jeroen Vreeken - M: pe1rxq@amsat.org ---- gregkh-2.6.orig/drivers/usb/Makefile -+++ gregkh-2.6/drivers/usb/Makefile -@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SN9C102) += media/ - obj-$(CONFIG_USB_STV680) += media/ - obj-$(CONFIG_USB_VICAM) += media/ - obj-$(CONFIG_USB_W9968CF) += media/ -+obj-$(CONFIG_USB_ZC0301) += media/ - - obj-$(CONFIG_USB_CATC) += net/ - obj-$(CONFIG_USB_KAWETH) += net/ ---- gregkh-2.6.orig/drivers/usb/media/Kconfig -+++ gregkh-2.6/drivers/usb/media/Kconfig -@@ -191,6 +191,21 @@ config USB_W9968CF - To compile this driver as a module, choose M here: the - module will be called w9968cf. - -+config USB_ZC0301 -+ tristate "USB ZC0301 Image Processor and Control Chip support" -+ depends on USB && VIDEO_DEV -+ ---help--- -+ Say Y here if you want support for cameras based on the ZC0301 -+ Image Processor and Control Chip. -+ -+ See <file:Documentation/usb/zc0301.txt> for more informations. -+ -+ This driver uses the Video For Linux API. You must say Y or M to -+ "Video For Linux" to use this driver. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called zc0301. -+ - config USB_PWC - tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV ---- gregkh-2.6.orig/drivers/usb/media/Makefile -+++ gregkh-2.6/drivers/usb/media/Makefile -@@ -4,6 +4,7 @@ - - sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o - et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o -+zc0301-objs := zc0301_core.o zc0301_pas202bcb.o - - obj-$(CONFIG_USB_DABUSB) += dabusb.o - obj-$(CONFIG_USB_DSBR) += dsbr100.o -@@ -16,4 +17,5 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102.o - obj-$(CONFIG_USB_STV680) += stv680.o - obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o - obj-$(CONFIG_USB_W9968CF) += w9968cf.o -+obj-$(CONFIG_USB_ZC0301) += zc0301.o - obj-$(CONFIG_USB_PWC) += pwc/ ---- /dev/null -+++ gregkh-2.6/drivers/usb/media/zc0301.h -@@ -0,0 +1,185 @@ -+/*************************************************************************** -+ * V4L2 driver for ZC0301 Image Processor and Control Chip * -+ * * -+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU General Public License as published by * -+ * the Free Software Foundation; either version 2 of the License, or * -+ * (at your option) any later version. * -+ * * -+ * This program is distributed in the hope that it will be useful, * -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -+ * GNU General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU General Public License * -+ * along with this program; if not, write to the Free Software * -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -+ ***************************************************************************/ -+ -+#ifndef _ZC0301_H_ -+#define _ZC0301_H_ -+ -+#include <linux/version.h> -+#include <linux/usb.h> -+#include <linux/videodev2.h> -+#include <media/v4l2-common.h> -+#include <linux/device.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/time.h> -+#include <linux/wait.h> -+#include <linux/types.h> -+#include <linux/param.h> -+#include <linux/mutex.h> -+#include <linux/rwsem.h> -+#include <asm/semaphore.h> -+ -+#include "zc0301_sensor.h" -+ -+/*****************************************************************************/ -+ -+#define ZC0301_DEBUG -+#define ZC0301_DEBUG_LEVEL 2 -+#define ZC0301_MAX_DEVICES 64 -+#define ZC0301_FORCE_MUNMAP 0 -+#define ZC0301_MAX_FRAMES 32 -+#define ZC0301_COMPRESSION_QUALITY 2 -+#define ZC0301_URBS 2 -+#define ZC0301_ISO_PACKETS 7 -+#define ZC0301_ALTERNATE_SETTING 7 -+#define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) -+#define ZC0301_CTRL_TIMEOUT 100 -+#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1) -+ -+/*****************************************************************************/ -+ -+ZC0301_ID_TABLE -+ZC0301_SENSOR_TABLE -+ -+enum zc0301_frame_state { -+ F_UNUSED, -+ F_QUEUED, -+ F_GRABBING, -+ F_DONE, -+ F_ERROR, -+}; -+ -+struct zc0301_frame_t { -+ void* bufmem; -+ struct v4l2_buffer buf; -+ enum zc0301_frame_state state; -+ struct list_head frame; -+ unsigned long vma_use_count; -+}; -+ -+enum zc0301_dev_state { -+ DEV_INITIALIZED = 0x01, -+ DEV_DISCONNECTED = 0x02, -+ DEV_MISCONFIGURED = 0x04, -+}; -+ -+enum zc0301_io_method { -+ IO_NONE, -+ IO_READ, -+ IO_MMAP, -+}; -+ -+enum zc0301_stream_state { -+ STREAM_OFF, -+ STREAM_INTERRUPT, -+ STREAM_ON, -+}; -+ -+struct zc0301_module_param { -+ u8 force_munmap; -+}; -+ -+static DECLARE_RWSEM(zc0301_disconnect); -+ -+struct zc0301_device { -+ struct video_device* v4ldev; -+ -+ struct zc0301_sensor* sensor; -+ -+ struct usb_device* usbdev; -+ struct urb* urb[ZC0301_URBS]; -+ void* transfer_buffer[ZC0301_URBS]; -+ u8* control_buffer; -+ -+ struct zc0301_frame_t *frame_current, frame[ZC0301_MAX_FRAMES]; -+ struct list_head inqueue, outqueue; -+ u32 frame_count, nbuffers, nreadbuffers; -+ -+ enum zc0301_io_method io; -+ enum zc0301_stream_state stream; -+ -+ struct v4l2_jpegcompression compression; -+ -+ struct zc0301_module_param module_param; -+ -+ enum zc0301_dev_state state; -+ u8 users; -+ -+ struct mutex dev_mutex, fileop_mutex; -+ spinlock_t queue_lock; -+ wait_queue_head_t open, wait_frame, wait_stream; -+}; -+ -+/*****************************************************************************/ -+ -+void -+zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) -+{ -+ cam->sensor = sensor; -+ cam->sensor->usbdev = cam->usbdev; -+} -+ -+/*****************************************************************************/ -+ -+#undef DBG -+#undef KDBG -+#ifdef ZC0301_DEBUG -+# define DBG(level, fmt, args...) \ -+do { \ -+ if (debug >= (level)) { \ -+ if ((level) == 1) \ -+ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \ -+ else if ((level) == 2) \ -+ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \ -+ else if ((level) >= 3) \ -+ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ -+ __FUNCTION__, __LINE__ , ## args); \ -+ } \ -+} while (0) -+# define KDBG(level, fmt, args...) \ -+do { \ -+ if (debug >= (level)) { \ -+ if ((level) == 1 || (level) == 2) \ -+ pr_info("zc0301: " fmt "\n", ## args); \ -+ else if ((level) == 3) \ -+ pr_debug("zc0301: [%s:%d] " fmt "\n", __FUNCTION__, \ -+ __LINE__ , ## args); \ -+ } \ -+} while (0) -+# define V4LDBG(level, name, cmd) \ -+do { \ -+ if (debug >= (level)) \ -+ v4l_print_ioctl(name, cmd); \ -+} while (0) -+#else -+# define DBG(level, fmt, args...) do {;} while(0) -+# define KDBG(level, fmt, args...) do {;} while(0) -+# define V4LDBG(level, name, cmd) do {;} while(0) -+#endif -+ -+#undef PDBG -+#define PDBG(fmt, args...) \ -+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ -+ __FUNCTION__, __LINE__ , ## args) -+ -+#undef PDBGG -+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ -+ -+#endif /* _ZC0301_H_ */ ---- /dev/null -+++ gregkh-2.6/drivers/usb/media/zc0301_core.c -@@ -0,0 +1,2028 @@ -+/*************************************************************************** -+ * Video4Linux2 driver for ZC0301 Image Processor and Control Chip * -+ * * -+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * -+ * * -+ * Informations about the chip internals to enable the I2C protocol have * -+ * been taken from the documentation of the ZC030x Video4Linux1 driver * -+ * written by Andrew Birkett <andy@nobugs.org> * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU General Public License as published by * -+ * the Free Software Foundation; either version 2 of the License, or * -+ * (at your option) any later version. * -+ * * -+ * This program is distributed in the hope that it will be useful, * -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -+ * GNU General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU General Public License * -+ * along with this program; if not, write to the Free Software * -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -+ ***************************************************************************/ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/param.h> -+#include <linux/moduleparam.h> -+#include <linux/errno.h> -+#include <linux/slab.h> -+#include <linux/string.h> -+#include <linux/device.h> -+#include <linux/fs.h> -+#include <linux/delay.h> -+#include <linux/stddef.h> -+#include <linux/compiler.h> -+#include <linux/ioctl.h> -+#include <linux/poll.h> -+#include <linux/stat.h> -+#include <linux/mm.h> -+#include <linux/vmalloc.h> -+#include <linux/page-flags.h> -+#include <linux/byteorder/generic.h> -+#include <asm/page.h> -+#include <asm/uaccess.h> -+ -+#include "zc0301.h" -+ -+/*****************************************************************************/ -+ -+#define ZC0301_MODULE_NAME "V4L2 driver for ZC0301 " \ -+ "Image Processor and Control Chip" -+#define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" -+#define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" -+#define ZC0301_MODULE_LICENSE "GPL" -+#define ZC0301_MODULE_VERSION "1:1.00" -+#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 0) -+ -+/*****************************************************************************/ -+ -+MODULE_DEVICE_TABLE(usb, zc0301_id_table); -+ -+MODULE_AUTHOR(ZC0301_MODULE_AUTHOR " " ZC0301_AUTHOR_EMAIL); -+MODULE_DESCRIPTION(ZC0301_MODULE_NAME); -+MODULE_VERSION(ZC0301_MODULE_VERSION); -+MODULE_LICENSE(ZC0301_MODULE_LICENSE); -+ -+static short video_nr[] = {[0 ... ZC0301_MAX_DEVICES-1] = -1}; -+module_param_array(video_nr, short, NULL, 0444); -+MODULE_PARM_DESC(video_nr, -+ "\n<-1|n[,...]> Specify V4L2 minor mode number." -+ "\n -1 = use next available (default)" -+ "\n n = use minor number n (integer >= 0)" -+ "\nYou can specify up to " -+ __MODULE_STRING(ZC0301_MAX_DEVICES) " cameras this way." -+ "\nFor example:" -+ "\nvideo_nr=-1,2,-1 would assign minor number 2 to" -+ "\nthe second registered camera and use auto for the first" -+ "\none and for every other camera." -+ "\n"); -+ -+static short force_munmap[] = {[0 ... ZC0301_MAX_DEVICES-1] = -+ ZC0301_FORCE_MUNMAP}; -+module_param_array(force_munmap, bool, NULL, 0444); -+MODULE_PARM_DESC(force_munmap, -+ "\n<0|1[,...]> Force the application to unmap previously" -+ "\nmapped buffer memory before calling any VIDIOC_S_CROP or" -+ "\nVIDIOC_S_FMT ioctl's. Not all the applications support" -+ "\nthis feature. This parameter is specific for each" -+ "\ndetected camera." -+ "\n 0 = do not force memory unmapping" -+ "\n 1 = force memory unmapping (save memory)" -+ "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." -+ "\n"); -+ -+#ifdef ZC0301_DEBUG -+static unsigned short debug = ZC0301_DEBUG_LEVEL; -+module_param(debug, ushort, 0644); -+MODULE_PARM_DESC(debug, -+ "\n<n> Debugging information level, from 0 to 3:" -+ "\n0 = none (use carefully)" -+ "\n1 = critical errors" -+ "\n2 = significant informations" -+ "\n3 = more verbose messages" -+ "\nLevel 3 is useful for testing only, when only " -+ "one device is used." -+ "\nDefault value is "__MODULE_STRING(ZC0301_DEBUG_LEVEL)"." -+ "\n"); -+#endif -+ -+/*****************************************************************************/ -+ -+static u32 -+zc0301_request_buffers(struct zc0301_device* cam, u32 count, -+ enum zc0301_io_method io) -+{ -+ struct v4l2_pix_format* p = &(cam->sensor->pix_format); -+ struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); -+ const size_t imagesize = cam->module_param.force_munmap || -+ io == IO_READ ? -+ (p->width * p->height * p->priv) / 8 : -+ (r->width * r->height * p->priv) / 8; -+ void* buff = NULL; -+ u32 i; -+ -+ if (count > ZC0301_MAX_FRAMES) -+ count = ZC0301_MAX_FRAMES; -+ -+ cam->nbuffers = count; -+ while (cam->nbuffers > 0) { -+ if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) -+ break; -+ cam->nbuffers--; -+ } -+ -+ for (i = 0; i < cam->nbuffers; i++) { -+ cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize); -+ cam->frame[i].buf.index = i; -+ cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize); -+ cam->frame[i].buf.length = imagesize; -+ cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cam->frame[i].buf.sequence = 0; -+ cam->frame[i].buf.field = V4L2_FIELD_NONE; -+ cam->frame[i].buf.memory = V4L2_MEMORY_MMAP; -+ cam->frame[i].buf.flags = 0; -+ } -+ -+ return cam->nbuffers; -+} -+ -+ -+static void zc0301_release_buffers(struct zc0301_device* cam) -+{ -+ if (cam->nbuffers) { -+ vfree(cam->frame[0].bufmem); -+ cam->nbuffers = 0; -+ } -+ cam->frame_current = NULL; -+} -+ -+ -+static void zc0301_empty_framequeues(struct zc0301_device* cam) -+{ -+ u32 i; -+ -+ INIT_LIST_HEAD(&cam->inqueue); -+ INIT_LIST_HEAD(&cam->outqueue); -+ -+ for (i = 0; i < ZC0301_MAX_FRAMES; i++) { -+ cam->frame[i].state = F_UNUSED; -+ cam->frame[i].buf.bytesused = 0; -+ } -+} -+ -+ -+static void zc0301_requeue_outqueue(struct zc0301_device* cam) -+{ -+ struct zc0301_frame_t *i; -+ -+ list_for_each_entry(i, &cam->outqueue, frame) { -+ i->state = F_QUEUED; -+ list_add(&i->frame, &cam->inqueue); -+ } -+ -+ INIT_LIST_HEAD(&cam->outqueue); -+} -+ -+ -+static void zc0301_queue_unusedframes(struct zc0301_device* cam) -+{ -+ unsigned long lock_flags; -+ u32 i; -+ -+ for (i = 0; i < cam->nbuffers; i++) -+ if (cam->frame[i].state == F_UNUSED) { -+ cam->frame[i].state = F_QUEUED; -+ spin_lock_irqsave(&cam->queue_lock, lock_flags); -+ list_add_tail(&cam->frame[i].frame, &cam->inqueue); -+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags); -+ } -+} -+ -+/*****************************************************************************/ -+ -+int zc0301_write_reg(struct zc0301_device* cam, u16 index, u16 value) -+{ -+ struct usb_device* udev = cam->usbdev; -+ int res; -+ -+ res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0xa0, 0x40, -+ value, index, NULL, 0, ZC0301_CTRL_TIMEOUT); -+ if (res < 0) { -+ DBG(3, "Failed to write a register (index 0x%04X, " -+ "value 0x%02X, error %d)",index, value, res); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+ -+int zc0301_read_reg(struct zc0301_device* cam, u16 index) -+{ -+ struct usb_device* udev = cam->usbdev; -+ u8* buff = cam->control_buffer; -+ int res; -+ -+ res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0xa1, 0xc0, -+ 0x0001, index, buff, 1, ZC0301_CTRL_TIMEOUT); -+ if (res < 0) -+ DBG(3, "Failed to read a register (index 0x%04X, error %d)", -+ index, res); -+ -+ PDBGG("Read: index 0x%04X, value: 0x%04X", index, (int)(*buff)); -+ -+ return (res >= 0) ? (int)(*buff) : -1; -+} -+ -+ -+int zc0301_i2c_read(struct zc0301_device* cam, u16 address, u8 length) -+{ -+ int err = 0, res, r0, r1; -+ -+ err += zc0301_write_reg(cam, 0x0092, address); -+ err += zc0301_write_reg(cam, 0x0090, 0x02); -+ -+ msleep(1); -+ -+ res = zc0301_read_reg(cam, 0x0091); -+ if (res < 0) -+ err += res; -+ r0 = zc0301_read_reg(cam, 0x0095); -+ if (r0 < 0) -+ err += r0; -+ r1 = zc0301_read_reg(cam, 0x0096); -+ if (r1 < 0) -+ err += r1; -+ -+ res = (length <= 1) ? r0 : r0 | (r1 << 8); -+ -+ if (err) -+ DBG(3, "I2C read failed at address 0x%04X, value: 0x%04X", -+ address, res); -+ -+ -+ PDBGG("I2C read: address 0x%04X, value: 0x%04X", address, res); -+ -+ return err ? -1 : res; -+} -+ -+ -+int zc0301_i2c_write(struct zc0301_device* cam, u16 address, u16 value) -+{ -+ int err = 0, res; -+ -+ err += zc0301_write_reg(cam, 0x0092, address); -+ err += zc0301_write_reg(cam, 0x0093, value & 0xff); -+ err += zc0301_write_reg(cam, 0x0094, value >> 8); -+ err += zc0301_write_reg(cam, 0x0090, 0x01); -+ -+ msleep(1); -+ -+ res = zc0301_read_reg(cam, 0x0091); -+ if (res < 0) -+ err += res; -+ -+ if (err) -+ DBG(3, "I2C write failed at address 0x%04X, value: 0x%04X", -+ address, value); -+ -+ PDBGG("I2C write: address 0x%04X, value: 0x%04X", address, value); -+ -+ return err ? -1 : 0; -+} -+ -+/*****************************************************************************/ -+ -+static void zc0301_urb_complete(struct urb *urb, struct pt_regs* regs) -+{ -+ struct zc0301_device* cam = urb->context; -+ struct zc0301_frame_t** f; -+ size_t imagesize; -+ u8 i; -+ int err = 0; -+ -+ if (urb->status == -ENOENT) -+ return; -+ -+ f = &cam->frame_current; -+ -+ if (cam->stream == STREAM_INTERRUPT) { -+ cam->stream = STREAM_OFF; -+ if ((*f)) -+ (*f)->state = F_QUEUED; -+ DBG(3, "Stream interrupted"); -+ wake_up_interruptible(&cam->wait_stream); -+ } -+ -+ if (cam->state & DEV_DISCONNECTED) -+ return; -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ wake_up_interruptible(&cam->wait_frame); -+ return; -+ } -+ -+ if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue)) -+ goto resubmit_urb; -+ -+ if (!(*f)) -+ (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, -+ frame); -+ -+ imagesize = (cam->sensor->pix_format.width * -+ cam->sensor->pix_format.height * -+ cam->sensor->pix_format.priv) / 8; -+ -+ for (i = 0; i < urb->number_of_packets; i++) { -+ unsigned int len, status; -+ void *pos; -+ u16* soi; -+ u8 sof; -+ -+ len = urb->iso_frame_desc[i].actual_length; -+ status = urb->iso_frame_desc[i].status; -+ pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer; -+ -+ if (status) { -+ DBG(3, "Error in isochronous frame"); -+ (*f)->state = F_ERROR; -+ continue; -+ } -+ -+ sof = (*(soi = pos) == 0xd8ff); -+ -+ PDBGG("Isochrnous frame: length %u, #%u i,", len, i); -+ -+ if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) -+start_of_frame: -+ if (sof) { -+ (*f)->state = F_GRABBING; -+ (*f)->buf.bytesused = 0; -+ do_gettimeofday(&(*f)->buf.timestamp); -+ DBG(3, "SOF detected: new video frame"); -+ } -+ -+ if ((*f)->state == F_GRABBING) { -+ if (sof && (*f)->buf.bytesused) -+ goto end_of_frame; -+ -+ if ((*f)->buf.bytesused + len > imagesize) { -+ DBG(3, "Video frame size exceeded"); -+ (*f)->state = F_ERROR; -+ continue; -+ } -+ -+ memcpy((*f)->bufmem+(*f)->buf.bytesused, pos, len); -+ (*f)->buf.bytesused += len; -+ -+ if ((*f)->buf.bytesused == imagesize) { -+ u32 b; -+end_of_frame: -+ b = (*f)->buf.bytesused; -+ (*f)->state = F_DONE; -+ (*f)->buf.sequence= ++cam->frame_count; -+ spin_lock(&cam->queue_lock); -+ list_move_tail(&(*f)->frame, &cam->outqueue); -+ if (!list_empty(&cam->inqueue)) -+ (*f) = list_entry(cam->inqueue.next, -+ struct zc0301_frame_t, -+ frame); -+ else -+ (*f) = NULL; -+ spin_unlock(&cam->queue_lock); -+ DBG(3, "Video frame captured: : %lu bytes", -+ (unsigned long)(b)); -+ -+ if (!(*f)) -+ goto resubmit_urb; -+ -+ if (sof) -+ goto start_of_frame; -+ } -+ } -+ } -+ -+resubmit_urb: -+ urb->dev = cam->usbdev; -+ err = usb_submit_urb(urb, GFP_ATOMIC); -+ if (err < 0 && err != -EPERM) { -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "usb_submit_urb() failed"); -+ } -+ -+ wake_up_interruptible(&cam->wait_frame); -+} -+ -+ -+static int zc0301_start_transfer(struct zc0301_device* cam) -+{ -+ struct usb_device *udev = cam->usbdev; -+ struct urb* urb; -+ const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384, -+ 512, 768, 1023}; -+ const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING]; -+ s8 i, j; -+ int err = 0; -+ -+ for (i = 0; i < ZC0301_URBS; i++) { -+ cam->transfer_buffer[i] = kzalloc(ZC0301_ISO_PACKETS * psz, -+ GFP_KERNEL); -+ if (!cam->transfer_buffer[i]) { -+ err = -ENOMEM; -+ DBG(1, "Not enough memory"); -+ goto free_buffers; -+ } -+ } -+ -+ for (i = 0; i < ZC0301_URBS; i++) { -+ urb = usb_alloc_urb(ZC0301_ISO_PACKETS, GFP_KERNEL); -+ cam->urb[i] = urb; -+ if (!urb) { -+ err = -ENOMEM; -+ DBG(1, "usb_alloc_urb() failed"); -+ goto free_urbs; -+ } -+ urb->dev = udev; -+ urb->context = cam; -+ urb->pipe = usb_rcvisocpipe(udev, 1); -+ urb->transfer_flags = URB_ISO_ASAP; -+ urb->number_of_packets = ZC0301_ISO_PACKETS; -+ urb->complete = zc0301_urb_complete; -+ urb->transfer_buffer = cam->transfer_buffer[i]; -+ urb->transfer_buffer_length = psz * ZC0301_ISO_PACKETS; -+ urb->interval = 1; -+ for (j = 0; j < ZC0301_ISO_PACKETS; j++) { -+ urb->iso_frame_desc[j].offset = psz * j; -+ urb->iso_frame_desc[j].length = psz; -+ } -+ } -+ -+ err = usb_set_interface(udev, 0, ZC0301_ALTERNATE_SETTING); -+ if (err) { -+ DBG(1, "usb_set_interface() failed"); -+ goto free_urbs; -+ } -+ -+ cam->frame_current = NULL; -+ -+ for (i = 0; i < ZC0301_URBS; i++) { -+ err = usb_submit_urb(cam->urb[i], GFP_KERNEL); -+ if (err) { -+ for (j = i-1; j >= 0; j--) -+ usb_kill_urb(cam->urb[j]); -+ DBG(1, "usb_submit_urb() failed, error %d", err); -+ goto free_urbs; -+ } -+ } -+ -+ return 0; -+ -+free_urbs: -+ for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) -+ usb_free_urb(cam->urb[i]); -+ -+free_buffers: -+ for (i = 0; (i < ZC0301_URBS) && cam->transfer_buffer[i]; i++) -+ kfree(cam->transfer_buffer[i]); -+ -+ return err; -+} -+ -+ -+static int zc0301_stop_transfer(struct zc0301_device* cam) -+{ -+ struct usb_device *udev = cam->usbdev; -+ s8 i; -+ int err = 0; -+ -+ if (cam->state & DEV_DISCONNECTED) -+ return 0; -+ -+ for (i = ZC0301_URBS-1; i >= 0; i--) { -+ usb_kill_urb(cam->urb[i]); -+ usb_free_urb(cam->urb[i]); -+ kfree(cam->transfer_buffer[i]); -+ } -+ -+ err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */ -+ if (err) -+ DBG(3, "usb_set_interface() failed"); -+ -+ return err; -+} -+ -+ -+static int zc0301_stream_interrupt(struct zc0301_device* cam) -+{ -+ long timeout; -+ -+ cam->stream = STREAM_INTERRUPT; -+ timeout = wait_event_timeout(cam->wait_stream, -+ (cam->stream == STREAM_OFF) || -+ (cam->state & DEV_DISCONNECTED), -+ ZC0301_URB_TIMEOUT); -+ if (cam->state & DEV_DISCONNECTED) -+ return -ENODEV; -+ else if (!timeout) { -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "URB timeout reached. The camera is misconfigured. To " -+ "use it, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+/*****************************************************************************/ -+ -+static int -+zc0301_set_compression(struct zc0301_device* cam, -+ struct v4l2_jpegcompression* compression) -+{ -+ int r, err = 0; -+ -+ if ((r = zc0301_read_reg(cam, 0x0008)) < 0) -+ err += r; -+ err += zc0301_write_reg(cam, 0x0008, -+ r | 0x11 | (compression->quality >> 1)); -+ -+ return err ? -EIO : 0; -+} -+ -+ -+static int zc0301_init(struct zc0301_device* cam) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_control ctrl; -+ struct v4l2_queryctrl *qctrl; -+ struct v4l2_rect* rect; -+ u8 i = 0; -+ int err = 0; -+ -+ if (!(cam->state & DEV_INITIALIZED)) { -+ init_waitqueue_head(&cam->open); -+ qctrl = s->qctrl; -+ rect = &(s->cropcap.defrect); -+ cam->compression.quality = ZC0301_COMPRESSION_QUALITY; -+ } else { /* use current values */ -+ qctrl = s->_qctrl; -+ rect = &(s->_rect); -+ } -+ -+ if (s->init) { -+ err = s->init(cam); -+ if (err) { -+ DBG(3, "Sensor initialization failed"); -+ return err; -+ } -+ } -+ -+ if ((err = zc0301_set_compression(cam, &cam->compression))) { -+ DBG(3, "set_compression() failed"); -+ return err; -+ } -+ -+ if (s->set_crop) -+ if ((err = s->set_crop(cam, rect))) { -+ DBG(3, "set_crop() failed"); -+ return err; -+ } -+ -+ if (s->set_ctrl) { -+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) -+ if (s->qctrl[i].id != 0 && -+ !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) { -+ ctrl.id = s->qctrl[i].id; -+ ctrl.value = qctrl[i].default_value; -+ err = s->set_ctrl(cam, &ctrl); -+ if (err) { -+ DBG(3, "Set %s control failed", -+ s->qctrl[i].name); -+ return err; -+ } -+ DBG(3, "Image sensor supports '%s' control", -+ s->qctrl[i].name); -+ } -+ } -+ -+ if (!(cam->state & DEV_INITIALIZED)) { -+ mutex_init(&cam->fileop_mutex); -+ spin_lock_init(&cam->queue_lock); -+ init_waitqueue_head(&cam->wait_frame); -+ init_waitqueue_head(&cam->wait_stream); -+ cam->nreadbuffers = 2; -+ memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl)); -+ memcpy(&(s->_rect), &(s->cropcap.defrect), -+ sizeof(struct v4l2_rect)); -+ cam->state |= DEV_INITIALIZED; -+ } -+ -+ DBG(2, "Initialization succeeded"); -+ return 0; -+} -+ -+ -+static void zc0301_release_resources(struct zc0301_device* cam) -+{ -+ DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); -+ video_set_drvdata(cam->v4ldev, NULL); -+ video_unregister_device(cam->v4ldev); -+ kfree(cam->control_buffer); -+} -+ -+/*****************************************************************************/ -+ -+static int zc0301_open(struct inode* inode, struct file* filp) -+{ -+ struct zc0301_device* cam; -+ int err = 0; -+ -+ /* -+ This is the only safe way to prevent race conditions with -+ disconnect -+ */ -+ if (!down_read_trylock(&zc0301_disconnect)) -+ return -ERESTARTSYS; -+ -+ cam = video_get_drvdata(video_devdata(filp)); -+ -+ if (mutex_lock_interruptible(&cam->dev_mutex)) { -+ up_read(&zc0301_disconnect); -+ return -ERESTARTSYS; -+ } -+ -+ if (cam->users) { -+ DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); -+ if ((filp->f_flags & O_NONBLOCK) || -+ (filp->f_flags & O_NDELAY)) { -+ err = -EWOULDBLOCK; -+ goto out; -+ } -+ mutex_unlock(&cam->dev_mutex); -+ err = wait_event_interruptible_exclusive(cam->open, -+ cam->state & DEV_DISCONNECTED -+ || !cam->users); -+ if (err) { -+ up_read(&zc0301_disconnect); -+ return err; -+ } -+ if (cam->state & DEV_DISCONNECTED) { -+ up_read(&zc0301_disconnect); -+ return -ENODEV; -+ } -+ mutex_lock(&cam->dev_mutex); -+ } -+ -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ err = zc0301_init(cam); -+ if (err) { -+ DBG(1, "Initialization failed again. " -+ "I will retry on next open()."); -+ goto out; -+ } -+ cam->state &= ~DEV_MISCONFIGURED; -+ } -+ -+ if ((err = zc0301_start_transfer(cam))) -+ goto out; -+ -+ filp->private_data = cam; -+ cam->users++; -+ cam->io = IO_NONE; -+ cam->stream = STREAM_OFF; -+ cam->nbuffers = 0; -+ cam->frame_count = 0; -+ zc0301_empty_framequeues(cam); -+ -+ DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); -+ -+out: -+ mutex_unlock(&cam->dev_mutex); -+ up_read(&zc0301_disconnect); -+ return err; -+} -+ -+ -+static int zc0301_release(struct inode* inode, struct file* filp) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ -+ mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ -+ -+ zc0301_stop_transfer(cam); -+ -+ zc0301_release_buffers(cam); -+ -+ if (cam->state & DEV_DISCONNECTED) { -+ zc0301_release_resources(cam); -+ mutex_unlock(&cam->dev_mutex); -+ kfree(cam); -+ return 0; -+ } -+ -+ cam->users--; -+ wake_up_interruptible_nr(&cam->open, 1); -+ -+ DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); -+ -+ mutex_unlock(&cam->dev_mutex); -+ -+ return 0; -+} -+ -+ -+static ssize_t -+zc0301_read(struct file* filp, char __user * buf, -+ size_t count, loff_t* f_pos) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ struct zc0301_frame_t* f, * i; -+ unsigned long lock_flags; -+ long timeout; -+ int err = 0; -+ -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) -+ return -ERESTARTSYS; -+ -+ if (cam->state & DEV_DISCONNECTED) { -+ DBG(1, "Device not present"); -+ mutex_unlock(&cam->fileop_mutex); -+ return -ENODEV; -+ } -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ DBG(1, "The camera is misconfigured. Close and open it " -+ "again."); -+ mutex_unlock(&cam->fileop_mutex); -+ return -EIO; -+ } -+ -+ if (cam->io == IO_MMAP) { -+ DBG(3, "Close and open the device again to choose the read " -+ "method"); -+ mutex_unlock(&cam->fileop_mutex); -+ return -EINVAL; -+ } -+ -+ if (cam->io == IO_NONE) { -+ if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { -+ DBG(1, "read() failed, not enough memory"); -+ mutex_unlock(&cam->fileop_mutex); -+ return -ENOMEM; -+ } -+ cam->io = IO_READ; -+ cam->stream = STREAM_ON; -+ } -+ -+ if (list_empty(&cam->inqueue)) { -+ if (!list_empty(&cam->outqueue)) -+ zc0301_empty_framequeues(cam); -+ zc0301_queue_unusedframes(cam); -+ } -+ -+ if (!count) { -+ mutex_unlock(&cam->fileop_mutex); -+ return 0; -+ } -+ -+ if (list_empty(&cam->outqueue)) { -+ if (filp->f_flags & O_NONBLOCK) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -EAGAIN; -+ } -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ ZC0301_FRAME_TIMEOUT ); -+ if (timeout < 0) { -+ mutex_unlock(&cam->fileop_mutex); -+ return timeout; -+ } -+ if (cam->state & DEV_DISCONNECTED) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -ENODEV; -+ } -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -EIO; -+ } -+ } -+ -+ f = list_entry(cam->outqueue.prev, struct zc0301_frame_t, frame); -+ -+ if (count > f->buf.bytesused) -+ count = f->buf.bytesused; -+ -+ if (copy_to_user(buf, f->bufmem, count)) { -+ err = -EFAULT; -+ goto exit; -+ } -+ *f_pos += count; -+ -+exit: -+ spin_lock_irqsave(&cam->queue_lock, lock_flags); -+ list_for_each_entry(i, &cam->outqueue, frame) -+ i->state = F_UNUSED; -+ INIT_LIST_HEAD(&cam->outqueue); -+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags); -+ -+ zc0301_queue_unusedframes(cam); -+ -+ PDBGG("Frame #%lu, bytes read: %zu", -+ (unsigned long)f->buf.index, count); -+ -+ mutex_unlock(&cam->fileop_mutex); -+ -+ return err ? err : count; -+} -+ -+ -+static unsigned int zc0301_poll(struct file *filp, poll_table *wait) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ struct zc0301_frame_t* f; -+ unsigned long lock_flags; -+ unsigned int mask = 0; -+ -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) -+ return POLLERR; -+ -+ if (cam->state & DEV_DISCONNECTED) { -+ DBG(1, "Device not present"); -+ goto error; -+ } -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ DBG(1, "The camera is misconfigured. Close and open it " -+ "again."); -+ goto error; -+ } -+ -+ if (cam->io == IO_NONE) { -+ if (!zc0301_request_buffers(cam, cam->nreadbuffers, IO_READ)) { -+ DBG(1, "poll() failed, not enough memory"); -+ goto error; -+ } -+ cam->io = IO_READ; -+ cam->stream = STREAM_ON; -+ } -+ -+ if (cam->io == IO_READ) { -+ spin_lock_irqsave(&cam->queue_lock, lock_flags); -+ list_for_each_entry(f, &cam->outqueue, frame) -+ f->state = F_UNUSED; -+ INIT_LIST_HEAD(&cam->outqueue); -+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags); -+ zc0301_queue_unusedframes(cam); -+ } -+ -+ poll_wait(filp, &cam->wait_frame, wait); -+ -+ if (!list_empty(&cam->outqueue)) -+ mask |= POLLIN | POLLRDNORM; -+ -+ mutex_unlock(&cam->fileop_mutex); -+ -+ return mask; -+ -+error: -+ mutex_unlock(&cam->fileop_mutex); -+ return POLLERR; -+} -+ -+ -+static void zc0301_vm_open(struct vm_area_struct* vma) -+{ -+ struct zc0301_frame_t* f = vma->vm_private_data; -+ f->vma_use_count++; -+} -+ -+ -+static void zc0301_vm_close(struct vm_area_struct* vma) -+{ -+ /* NOTE: buffers are not freed here */ -+ struct zc0301_frame_t* f = vma->vm_private_data; -+ f->vma_use_count--; -+} -+ -+ -+static struct vm_operations_struct zc0301_vm_ops = { -+ .open = zc0301_vm_open, -+ .close = zc0301_vm_close, -+}; -+ -+ -+static int zc0301_mmap(struct file* filp, struct vm_area_struct *vma) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ unsigned long size = vma->vm_end - vma->vm_start, -+ start = vma->vm_start; -+ void *pos; -+ u32 i; -+ -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) -+ return -ERESTARTSYS; -+ -+ if (cam->state & DEV_DISCONNECTED) { -+ DBG(1, "Device not present"); -+ mutex_unlock(&cam->fileop_mutex); -+ return -ENODEV; -+ } -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ DBG(1, "The camera is misconfigured. Close and open it " -+ "again."); -+ mutex_unlock(&cam->fileop_mutex); -+ return -EIO; -+ } -+ -+ if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || -+ size != PAGE_ALIGN(cam->frame[0].buf.length)) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < cam->nbuffers; i++) { -+ if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff) -+ break; -+ } -+ if (i == cam->nbuffers) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -EINVAL; -+ } -+ -+ vma->vm_flags |= VM_IO; -+ vma->vm_flags |= VM_RESERVED; -+ -+ pos = cam->frame[i].bufmem; -+ while (size > 0) { /* size is page-aligned */ -+ if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { -+ mutex_unlock(&cam->fileop_mutex); -+ return -EAGAIN; -+ } -+ start += PAGE_SIZE; -+ pos += PAGE_SIZE; -+ size -= PAGE_SIZE; -+ } -+ -+ vma->vm_ops = &zc0301_vm_ops; -+ vma->vm_private_data = &cam->frame[i]; -+ -+ zc0301_vm_open(vma); -+ -+ mutex_unlock(&cam->fileop_mutex); -+ -+ return 0; -+} -+ -+/*****************************************************************************/ -+ -+static int -+zc0301_vidioc_querycap(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_capability cap = { -+ .driver = "zc0301", -+ .version = ZC0301_MODULE_VERSION_CODE, -+ .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | -+ V4L2_CAP_STREAMING, -+ }; -+ -+ strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); -+ if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) -+ strlcpy(cap.bus_info, cam->usbdev->dev.bus_id, -+ sizeof(cap.bus_info)); -+ -+ if (copy_to_user(arg, &cap, sizeof(cap))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_enuminput(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_input i; -+ -+ if (copy_from_user(&i, arg, sizeof(i))) -+ return -EFAULT; -+ -+ if (i.index) -+ return -EINVAL; -+ -+ memset(&i, 0, sizeof(i)); -+ strcpy(i.name, "Camera"); -+ -+ if (copy_to_user(arg, &i, sizeof(i))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg) -+{ -+ int index; -+ -+ if (copy_from_user(&index, arg, sizeof(index))) -+ return -EFAULT; -+ -+ if (index != 0) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_queryctrl qc; -+ u8 i; -+ -+ if (copy_from_user(&qc, arg, sizeof(qc))) -+ return -EFAULT; -+ -+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) -+ if (qc.id && qc.id == s->qctrl[i].id) { -+ memcpy(&qc, &(s->qctrl[i]), sizeof(qc)); -+ if (copy_to_user(arg, &qc, sizeof(qc))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+ -+static int -+zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_control ctrl; -+ int err = 0; -+ u8 i; -+ -+ if (!s->get_ctrl && !s->set_ctrl) -+ return -EINVAL; -+ -+ if (copy_from_user(&ctrl, arg, sizeof(ctrl))) -+ return -EFAULT; -+ -+ if (!s->get_ctrl) { -+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) -+ if (ctrl.id == s->qctrl[i].id) { -+ ctrl.value = s->_qctrl[i].default_value; -+ goto exit; -+ } -+ return -EINVAL; -+ } else -+ err = s->get_ctrl(cam, &ctrl); -+ -+exit: -+ if (copy_to_user(arg, &ctrl, sizeof(ctrl))) -+ return -EFAULT; -+ -+ return err; -+} -+ -+ -+static int -+zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_control ctrl; -+ u8 i; -+ int err = 0; -+ -+ if (!s->set_ctrl) -+ return -EINVAL; -+ -+ if (copy_from_user(&ctrl, arg, sizeof(ctrl))) -+ return -EFAULT; -+ -+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) -+ if (ctrl.id == s->qctrl[i].id) { -+ if (ctrl.value < s->qctrl[i].minimum || -+ ctrl.value > s->qctrl[i].maximum) -+ return -ERANGE; -+ ctrl.value -= ctrl.value % s->qctrl[i].step; -+ break; -+ } -+ -+ if ((err = s->set_ctrl(cam, &ctrl))) -+ return err; -+ -+ s->_qctrl[i].default_value = ctrl.value; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_cropcap* cc = &(cam->sensor->cropcap); -+ -+ cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cc->pixelaspect.numerator = 1; -+ cc->pixelaspect.denominator = 1; -+ -+ if (copy_to_user(arg, cc, sizeof(*cc))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_crop crop = { -+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, -+ }; -+ -+ memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect)); -+ -+ if (copy_to_user(arg, &crop, sizeof(crop))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_crop crop; -+ struct v4l2_rect* rect; -+ struct v4l2_rect* bounds = &(s->cropcap.bounds); -+ const enum zc0301_stream_state stream = cam->stream; -+ const u32 nbuffers = cam->nbuffers; -+ u32 i; -+ int err = 0; -+ -+ if (copy_from_user(&crop, arg, sizeof(crop))) -+ return -EFAULT; -+ -+ rect = &(crop.c); -+ -+ if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ if (cam->module_param.force_munmap) -+ for (i = 0; i < cam->nbuffers; i++) -+ if (cam->frame[i].vma_use_count) { -+ DBG(3, "VIDIOC_S_CROP failed. " -+ "Unmap the buffers first."); -+ return -EINVAL; -+ } -+ -+ if (!s->set_crop) { -+ memcpy(rect, &(s->_rect), sizeof(*rect)); -+ if (copy_to_user(arg, &crop, sizeof(crop))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ rect->left &= ~7L; -+ rect->top &= ~7L; -+ if (rect->width < 8) -+ rect->width = 8; -+ if (rect->height < 8) -+ rect->height = 8; -+ if (rect->width > bounds->width) -+ rect->width = bounds->width; -+ if (rect->height > bounds->height) -+ rect->height = bounds->height; -+ if (rect->left < bounds->left) -+ rect->left = bounds->left; -+ if (rect->top < bounds->top) -+ rect->top = bounds->top; -+ if (rect->left + rect->width > bounds->left + bounds->width) -+ rect->left = bounds->left+bounds->width - rect->width; -+ if (rect->top + rect->height > bounds->top + bounds->height) -+ rect->top = bounds->top+bounds->height - rect->height; -+ rect->width &= ~7L; -+ rect->height &= ~7L; -+ -+ if (cam->stream == STREAM_ON) -+ if ((err = zc0301_stream_interrupt(cam))) -+ return err; -+ -+ if (copy_to_user(arg, &crop, sizeof(crop))) { -+ cam->stream = stream; -+ return -EFAULT; -+ } -+ -+ if (cam->module_param.force_munmap || cam->io == IO_READ) -+ zc0301_release_buffers(cam); -+ -+ if (s->set_crop) -+ err += s->set_crop(cam, rect); -+ -+ if (err) { /* atomic, no rollback in ioctl() */ -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " -+ "use the camera, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -EIO; -+ } -+ -+ s->pix_format.width = rect->width; -+ s->pix_format.height = rect->height; -+ memcpy(&(s->_rect), rect, sizeof(*rect)); -+ -+ if ((cam->module_param.force_munmap || cam->io == IO_READ) && -+ nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " -+ "use the camera, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -ENOMEM; -+ } -+ -+ if (cam->io == IO_READ) -+ zc0301_empty_framequeues(cam); -+ else if (cam->module_param.force_munmap) -+ zc0301_requeue_outqueue(cam); -+ -+ cam->stream = stream; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_enum_fmt(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_fmtdesc fmtd; -+ -+ if (copy_from_user(&fmtd, arg, sizeof(fmtd))) -+ return -EFAULT; -+ -+ if (fmtd.index == 0) { -+ strcpy(fmtd.description, "JPEG"); -+ fmtd.pixelformat = V4L2_PIX_FMT_JPEG; -+ fmtd.flags = V4L2_FMT_FLAG_COMPRESSED; -+ } else -+ return -EINVAL; -+ -+ fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ memset(&fmtd.reserved, 0, sizeof(fmtd.reserved)); -+ -+ if (copy_to_user(arg, &fmtd, sizeof(fmtd))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_format format; -+ struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); -+ -+ if (copy_from_user(&format, arg, sizeof(format))) -+ return -EFAULT; -+ -+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ pfmt->bytesperline = 0; -+ pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8); -+ pfmt->field = V4L2_FIELD_NONE; -+ memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt)); -+ -+ if (copy_to_user(arg, &format, sizeof(format))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, -+ void __user * arg) -+{ -+ struct zc0301_sensor* s = cam->sensor; -+ struct v4l2_format format; -+ struct v4l2_pix_format* pix; -+ struct v4l2_pix_format* pfmt = &(s->pix_format); -+ struct v4l2_rect* bounds = &(s->cropcap.bounds); -+ struct v4l2_rect rect; -+ const enum zc0301_stream_state stream = cam->stream; -+ const u32 nbuffers = cam->nbuffers; -+ u32 i; -+ int err = 0; -+ -+ if (copy_from_user(&format, arg, sizeof(format))) -+ return -EFAULT; -+ -+ pix = &(format.fmt.pix); -+ -+ if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ memcpy(&rect, &(s->_rect), sizeof(rect)); -+ -+ if (!s->set_crop) { -+ pix->width = rect.width; -+ pix->height = rect.height; -+ } else { -+ rect.width = pix->width; -+ rect.height = pix->height; -+ } -+ -+ if (rect.width < 8) -+ rect.width = 8; -+ if (rect.height < 8) -+ rect.height = 8; -+ if (rect.width > bounds->left + bounds->width - rect.left) -+ rect.width = bounds->left + bounds->width - rect.left; -+ if (rect.height > bounds->top + bounds->height - rect.top) -+ rect.height = bounds->top + bounds->height - rect.top; -+ rect.width &= ~7L; -+ rect.height &= ~7L; -+ -+ pix->width = rect.width; -+ pix->height = rect.height; -+ pix->pixelformat = pfmt->pixelformat; -+ pix->priv = pfmt->priv; -+ pix->colorspace = pfmt->colorspace; -+ pix->bytesperline = 0; -+ pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8); -+ pix->field = V4L2_FIELD_NONE; -+ -+ if (cmd == VIDIOC_TRY_FMT) { -+ if (copy_to_user(arg, &format, sizeof(format))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ if (cam->module_param.force_munmap) -+ for (i = 0; i < cam->nbuffers; i++) -+ if (cam->frame[i].vma_use_count) { -+ DBG(3, "VIDIOC_S_FMT failed. " -+ "Unmap the buffers first."); -+ return -EINVAL; -+ } -+ -+ if (cam->stream == STREAM_ON) -+ if ((err = zc0301_stream_interrupt(cam))) -+ return err; -+ -+ if (copy_to_user(arg, &format, sizeof(format))) { -+ cam->stream = stream; -+ return -EFAULT; -+ } -+ -+ if (cam->module_param.force_munmap || cam->io == IO_READ) -+ zc0301_release_buffers(cam); -+ -+ if (s->set_crop) -+ err += s->set_crop(cam, &rect); -+ -+ if (err) { /* atomic, no rollback in ioctl() */ -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " -+ "use the camera, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -EIO; -+ } -+ -+ memcpy(pfmt, pix, sizeof(*pix)); -+ memcpy(&(s->_rect), &rect, sizeof(rect)); -+ -+ if ((cam->module_param.force_munmap || cam->io == IO_READ) && -+ nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " -+ "use the camera, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -ENOMEM; -+ } -+ -+ if (cam->io == IO_READ) -+ zc0301_empty_framequeues(cam); -+ else if (cam->module_param.force_munmap) -+ zc0301_requeue_outqueue(cam); -+ -+ cam->stream = stream; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_g_jpegcomp(struct zc0301_device* cam, void __user * arg) -+{ -+ if (copy_to_user(arg, &cam->compression, sizeof(cam->compression))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_jpegcompression jc; -+ const enum zc0301_stream_state stream = cam->stream; -+ int err = 0; -+ -+ if (copy_from_user(&jc, arg, sizeof(jc))) -+ return -EFAULT; -+ -+ if (jc.quality < 0 || jc.quality > 3) -+ return -EINVAL; -+ -+ if (cam->stream == STREAM_ON) -+ if ((err = zc0301_stream_interrupt(cam))) -+ return err; -+ -+ err += zc0301_set_compression(cam, &jc); -+ if (err) { /* atomic, no rollback in ioctl() */ -+ cam->state |= DEV_MISCONFIGURED; -+ DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " -+ "problems. To use the camera, close and open " -+ "/dev/video%d again.", cam->v4ldev->minor); -+ return -EIO; -+ } -+ -+ cam->compression.quality = jc.quality; -+ -+ cam->stream = stream; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_reqbufs(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_requestbuffers rb; -+ u32 i; -+ int err; -+ -+ if (copy_from_user(&rb, arg, sizeof(rb))) -+ return -EFAULT; -+ -+ if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || -+ rb.memory != V4L2_MEMORY_MMAP) -+ return -EINVAL; -+ -+ if (cam->io == IO_READ) { -+ DBG(3, "Close and open the device again to choose the mmap " -+ "I/O method"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < cam->nbuffers; i++) -+ if (cam->frame[i].vma_use_count) { -+ DBG(3, "VIDIOC_REQBUFS failed. " -+ "Previous buffers are still mapped."); -+ return -EINVAL; -+ } -+ -+ if (cam->stream == STREAM_ON) -+ if ((err = zc0301_stream_interrupt(cam))) -+ return err; -+ -+ zc0301_empty_framequeues(cam); -+ -+ zc0301_release_buffers(cam); -+ if (rb.count) -+ rb.count = zc0301_request_buffers(cam, rb.count, IO_MMAP); -+ -+ if (copy_to_user(arg, &rb, sizeof(rb))) { -+ zc0301_release_buffers(cam); -+ cam->io = IO_NONE; -+ return -EFAULT; -+ } -+ -+ cam->io = rb.count ? IO_MMAP : IO_NONE; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_querybuf(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_buffer b; -+ -+ if (copy_from_user(&b, arg, sizeof(b))) -+ return -EFAULT; -+ -+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || -+ b.index >= cam->nbuffers || cam->io != IO_MMAP) -+ return -EINVAL; -+ -+ memcpy(&b, &cam->frame[b.index].buf, sizeof(b)); -+ -+ if (cam->frame[b.index].vma_use_count) -+ b.flags |= V4L2_BUF_FLAG_MAPPED; -+ -+ if (cam->frame[b.index].state == F_DONE) -+ b.flags |= V4L2_BUF_FLAG_DONE; -+ else if (cam->frame[b.index].state != F_UNUSED) -+ b.flags |= V4L2_BUF_FLAG_QUEUED; -+ -+ if (copy_to_user(arg, &b, sizeof(b))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_qbuf(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_buffer b; -+ unsigned long lock_flags; -+ -+ if (copy_from_user(&b, arg, sizeof(b))) -+ return -EFAULT; -+ -+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || -+ b.index >= cam->nbuffers || cam->io != IO_MMAP) -+ return -EINVAL; -+ -+ if (cam->frame[b.index].state != F_UNUSED) -+ return -EINVAL; -+ -+ cam->frame[b.index].state = F_QUEUED; -+ -+ spin_lock_irqsave(&cam->queue_lock, lock_flags); -+ list_add_tail(&cam->frame[b.index].frame, &cam->inqueue); -+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags); -+ -+ PDBGG("Frame #%lu queued", (unsigned long)b.index); -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_dqbuf(struct zc0301_device* cam, struct file* filp, -+ void __user * arg) -+{ -+ struct v4l2_buffer b; -+ struct zc0301_frame_t *f; -+ unsigned long lock_flags; -+ long timeout; -+ -+ if (copy_from_user(&b, arg, sizeof(b))) -+ return -EFAULT; -+ -+ if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP) -+ return -EINVAL; -+ -+ if (list_empty(&cam->outqueue)) { -+ if (cam->stream == STREAM_OFF) -+ return -EINVAL; -+ if (filp->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ ZC0301_FRAME_TIMEOUT ); -+ if (timeout < 0) -+ return timeout; -+ if (cam->state & DEV_DISCONNECTED) -+ return -ENODEV; -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) -+ return -EIO; -+ } -+ -+ spin_lock_irqsave(&cam->queue_lock, lock_flags); -+ f = list_entry(cam->outqueue.next, struct zc0301_frame_t, frame); -+ list_del(cam->outqueue.next); -+ spin_unlock_irqrestore(&cam->queue_lock, lock_flags); -+ -+ f->state = F_UNUSED; -+ -+ memcpy(&b, &f->buf, sizeof(b)); -+ if (f->vma_use_count) -+ b.flags |= V4L2_BUF_FLAG_MAPPED; -+ -+ if (copy_to_user(arg, &b, sizeof(b))) -+ return -EFAULT; -+ -+ PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index); -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_streamon(struct zc0301_device* cam, void __user * arg) -+{ -+ int type; -+ -+ if (copy_from_user(&type, arg, sizeof(type))) -+ return -EFAULT; -+ -+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) -+ return -EINVAL; -+ -+ if (list_empty(&cam->inqueue)) -+ return -EINVAL; -+ -+ cam->stream = STREAM_ON; -+ -+ DBG(3, "Stream on"); -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_streamoff(struct zc0301_device* cam, void __user * arg) -+{ -+ int type, err; -+ -+ if (copy_from_user(&type, arg, sizeof(type))) -+ return -EFAULT; -+ -+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP) -+ return -EINVAL; -+ -+ if (cam->stream == STREAM_ON) -+ if ((err = zc0301_stream_interrupt(cam))) -+ return err; -+ -+ zc0301_empty_framequeues(cam); -+ -+ DBG(3, "Stream off"); -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_g_parm(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_streamparm sp; -+ -+ if (copy_from_user(&sp, arg, sizeof(sp))) -+ return -EFAULT; -+ -+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ sp.parm.capture.extendedmode = 0; -+ sp.parm.capture.readbuffers = cam->nreadbuffers; -+ -+ if (copy_to_user(arg, &sp, sizeof(sp))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg) -+{ -+ struct v4l2_streamparm sp; -+ -+ if (copy_from_user(&sp, arg, sizeof(sp))) -+ return -EFAULT; -+ -+ if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ sp.parm.capture.extendedmode = 0; -+ -+ if (sp.parm.capture.readbuffers == 0) -+ sp.parm.capture.readbuffers = cam->nreadbuffers; -+ -+ if (sp.parm.capture.readbuffers > ZC0301_MAX_FRAMES) -+ sp.parm.capture.readbuffers = ZC0301_MAX_FRAMES; -+ -+ if (copy_to_user(arg, &sp, sizeof(sp))) -+ return -EFAULT; -+ -+ cam->nreadbuffers = sp.parm.capture.readbuffers; -+ -+ return 0; -+} -+ -+ -+static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp, -+ unsigned int cmd, void __user * arg) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ -+ switch (cmd) { -+ -+ case VIDIOC_QUERYCAP: -+ return zc0301_vidioc_querycap(cam, arg); -+ -+ case VIDIOC_ENUMINPUT: -+ return zc0301_vidioc_enuminput(cam, arg); -+ -+ case VIDIOC_G_INPUT: -+ case VIDIOC_S_INPUT: -+ return zc0301_vidioc_gs_input(cam, arg); -+ -+ case VIDIOC_QUERYCTRL: -+ return zc0301_vidioc_query_ctrl(cam, arg); -+ -+ case VIDIOC_G_CTRL: -+ return zc0301_vidioc_g_ctrl(cam, arg); -+ -+ case VIDIOC_S_CTRL_OLD: -+ case VIDIOC_S_CTRL: -+ return zc0301_vidioc_s_ctrl(cam, arg); -+ -+ case VIDIOC_CROPCAP_OLD: -+ case VIDIOC_CROPCAP: -+ return zc0301_vidioc_cropcap(cam, arg); -+ -+ case VIDIOC_G_CROP: -+ return zc0301_vidioc_g_crop(cam, arg); -+ -+ case VIDIOC_S_CROP: -+ return zc0301_vidioc_s_crop(cam, arg); -+ -+ case VIDIOC_ENUM_FMT: -+ return zc0301_vidioc_enum_fmt(cam, arg); -+ -+ case VIDIOC_G_FMT: -+ return zc0301_vidioc_g_fmt(cam, arg); -+ -+ case VIDIOC_TRY_FMT: -+ case VIDIOC_S_FMT: -+ return zc0301_vidioc_try_s_fmt(cam, cmd, arg); -+ -+ case VIDIOC_G_JPEGCOMP: -+ return zc0301_vidioc_g_jpegcomp(cam, arg); -+ -+ case VIDIOC_S_JPEGCOMP: -+ return zc0301_vidioc_s_jpegcomp(cam, arg); -+ -+ case VIDIOC_REQBUFS: -+ return zc0301_vidioc_reqbufs(cam, arg); -+ -+ case VIDIOC_QUERYBUF: -+ return zc0301_vidioc_querybuf(cam, arg); -+ -+ case VIDIOC_QBUF: -+ return zc0301_vidioc_qbuf(cam, arg); -+ -+ case VIDIOC_DQBUF: -+ return zc0301_vidioc_dqbuf(cam, filp, arg); -+ -+ case VIDIOC_STREAMON: -+ return zc0301_vidioc_streamon(cam, arg); -+ -+ case VIDIOC_STREAMOFF: -+ return zc0301_vidioc_streamoff(cam, arg); -+ -+ case VIDIOC_G_PARM: -+ return zc0301_vidioc_g_parm(cam, arg); -+ -+ case VIDIOC_S_PARM_OLD: -+ case VIDIOC_S_PARM: -+ return zc0301_vidioc_s_parm(cam, arg); -+ -+ case VIDIOC_G_STD: -+ case VIDIOC_S_STD: -+ case VIDIOC_QUERYSTD: -+ case VIDIOC_ENUMSTD: -+ case VIDIOC_QUERYMENU: -+ return -EINVAL; -+ -+ default: -+ return -EINVAL; -+ -+ } -+} -+ -+ -+static int zc0301_ioctl(struct inode* inode, struct file* filp, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); -+ int err = 0; -+ -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) -+ return -ERESTARTSYS; -+ -+ if (cam->state & DEV_DISCONNECTED) { -+ DBG(1, "Device not present"); -+ mutex_unlock(&cam->fileop_mutex); -+ return -ENODEV; -+ } -+ -+ if (cam->state & DEV_MISCONFIGURED) { -+ DBG(1, "The camera is misconfigured. Close and open it " -+ "again."); -+ mutex_unlock(&cam->fileop_mutex); -+ return -EIO; -+ } -+ -+ V4LDBG(3, "zc0301", cmd); -+ -+ err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); -+ -+ mutex_unlock(&cam->fileop_mutex); -+ -+ return err; -+} -+ -+ -+static struct file_operations zc0301_fops = { -+ .owner = THIS_MODULE, -+ .open = zc0301_open, -+ .release = zc0301_release, -+ .ioctl = zc0301_ioctl, -+ .read = zc0301_read, -+ .poll = zc0301_poll, -+ .mmap = zc0301_mmap, -+ .llseek = no_llseek, -+}; -+ -+/*****************************************************************************/ -+ -+static int -+zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) -+{ -+ struct usb_device *udev = interface_to_usbdev(intf); -+ struct zc0301_device* cam; -+ static unsigned int dev_nr = 0; -+ unsigned int i; -+ int err = 0; -+ -+ if (!(cam = kzalloc(sizeof(struct zc0301_device), GFP_KERNEL))) -+ return -ENOMEM; -+ -+ cam->usbdev = udev; -+ -+ if (!(cam->control_buffer = kzalloc(4, GFP_KERNEL))) { -+ DBG(1, "kmalloc() failed"); -+ err = -ENOMEM; -+ goto fail; -+ } -+ -+ if (!(cam->v4ldev = video_device_alloc())) { -+ DBG(1, "video_device_alloc() failed"); -+ err = -ENOMEM; -+ goto fail; -+ } -+ -+ mutex_init(&cam->dev_mutex); -+ -+ DBG(2, "ZC0301 Image Processor and Control Chip detected " -+ "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); -+ -+ for (i = 0; zc0301_sensor_table[i]; i++) { -+ err = zc0301_sensor_table[i](cam); -+ if (!err) -+ break; -+ } -+ -+ if (!err && cam->sensor) -+ DBG(2, "%s image sensor detected", cam->sensor->name); -+ else { -+ DBG(1, "No supported image sensor detected"); -+ err = -ENODEV; -+ goto fail; -+ } -+ -+ if (zc0301_init(cam)) { -+ DBG(1, "Initialization failed. I will retry on open()."); -+ cam->state |= DEV_MISCONFIGURED; -+ } -+ -+ strcpy(cam->v4ldev->name, "ZC0301 PC Camera"); -+ cam->v4ldev->owner = THIS_MODULE; -+ cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; -+ cam->v4ldev->hardware = 0; -+ cam->v4ldev->fops = &zc0301_fops; -+ cam->v4ldev->minor = video_nr[dev_nr]; -+ cam->v4ldev->release = video_device_release; -+ video_set_drvdata(cam->v4ldev, cam); -+ -+ mutex_lock(&cam->dev_mutex); -+ -+ err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, -+ video_nr[dev_nr]); -+ if (err) { -+ DBG(1, "V4L2 device registration failed"); -+ if (err == -ENFILE && video_nr[dev_nr] == -1) -+ DBG(1, "Free /dev/videoX node not found"); -+ video_nr[dev_nr] = -1; -+ dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; -+ mutex_unlock(&cam->dev_mutex); -+ goto fail; -+ } -+ -+ DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); -+ -+ cam->module_param.force_munmap = force_munmap[dev_nr]; -+ -+ dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; -+ -+ usb_set_intfdata(intf, cam); -+ -+ mutex_unlock(&cam->dev_mutex); -+ -+ return 0; -+ -+fail: -+ if (cam) { -+ kfree(cam->control_buffer); -+ if (cam->v4ldev) -+ video_device_release(cam->v4ldev); -+ kfree(cam); -+ } -+ return err; -+} -+ -+ -+static void zc0301_usb_disconnect(struct usb_interface* intf) -+{ -+ struct zc0301_device* cam = usb_get_intfdata(intf); -+ -+ if (!cam) -+ return; -+ -+ down_write(&zc0301_disconnect); -+ -+ mutex_lock(&cam->dev_mutex); -+ -+ DBG(2, "Disconnecting %s...", cam->v4ldev->name); -+ -+ wake_up_interruptible_all(&cam->open); -+ -+ if (cam->users) { -+ DBG(2, "Device /dev/video%d is open! Deregistration and " -+ "memory deallocation are deferred on close.", -+ cam->v4ldev->minor); -+ cam->state |= DEV_MISCONFIGURED; -+ zc0301_stop_transfer(cam); -+ cam->state |= DEV_DISCONNECTED; -+ wake_up_interruptible(&cam->wait_frame); -+ wake_up_interruptible(&cam->wait_stream); -+ } else { -+ cam->state |= DEV_DISCONNECTED; -+ zc0301_release_resources(cam); -+ } -+ -+ mutex_unlock(&cam->dev_mutex); -+ -+ if (!cam->users) -+ kfree(cam); -+ -+ up_write(&zc0301_disconnect); -+} -+ -+ -+static struct usb_driver zc0301_usb_driver = { -+ .name = "zc0301", -+ .id_table = zc0301_id_table, -+ .probe = zc0301_usb_probe, -+ .disconnect = zc0301_usb_disconnect, -+}; -+ -+/*****************************************************************************/ -+ -+static int __init zc0301_module_init(void) -+{ -+ int err = 0; -+ -+ KDBG(2, ZC0301_MODULE_NAME " v" ZC0301_MODULE_VERSION); -+ KDBG(3, ZC0301_MODULE_AUTHOR); -+ -+ if ((err = usb_register(&zc0301_usb_driver))) -+ KDBG(1, "usb_register() failed"); -+ -+ return err; -+} -+ -+ -+static void __exit zc0301_module_exit(void) -+{ -+ usb_deregister(&zc0301_usb_driver); -+} -+ -+ -+module_init(zc0301_module_init); -+module_exit(zc0301_module_exit); ---- /dev/null -+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c -@@ -0,0 +1,353 @@ -+/*************************************************************************** -+ * Plug-in for PAS202BCB image sensor connected to the ZC030! Image * -+ * Processor and Control Chip * -+ * * -+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * -+ * * -+ * Initialization values of the ZC0301 have been taken from the SPCA5XX * -+ * driver maintained by Michel Xhaard <mxhaard@magic.fr> * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU General Public License as published by * -+ * the Free Software Foundation; either version 2 of the License, or * -+ * (at your option) any later version. * -+ * * -+ * This program is distributed in the hope that it will be useful, * -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -+ * GNU General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU General Public License * -+ * along with this program; if not, write to the Free Software * -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -+ ***************************************************************************/ -+ -+#include <linux/delay.h> -+#include "zc0301_sensor.h" -+ -+ -+static struct zc0301_sensor pas202bcb; -+ -+ -+static int pas202bcb_init(struct zc0301_device* cam) -+{ -+ int err = 0; -+ -+ err += zc0301_write_reg(cam, 0x0002, 0x00); -+ err += zc0301_write_reg(cam, 0x0003, 0x02); -+ err += zc0301_write_reg(cam, 0x0004, 0x80); -+ err += zc0301_write_reg(cam, 0x0005, 0x01); -+ err += zc0301_write_reg(cam, 0x0006, 0xE0); -+ err += zc0301_write_reg(cam, 0x0098, 0x00); -+ err += zc0301_write_reg(cam, 0x009A, 0x03); -+ err += zc0301_write_reg(cam, 0x011A, 0x00); -+ err += zc0301_write_reg(cam, 0x011C, 0x03); -+ err += zc0301_write_reg(cam, 0x009B, 0x01); -+ err += zc0301_write_reg(cam, 0x009C, 0xE6); -+ err += zc0301_write_reg(cam, 0x009D, 0x02); -+ err += zc0301_write_reg(cam, 0x009E, 0x86); -+ -+ err += zc0301_i2c_write(cam, 0x02, 0x02); -+ err += zc0301_i2c_write(cam, 0x0A, 0x01); -+ err += zc0301_i2c_write(cam, 0x0B, 0x01); -+ err += zc0301_i2c_write(cam, 0x0D, 0x00); -+ err += zc0301_i2c_write(cam, 0x12, 0x05); -+ err += zc0301_i2c_write(cam, 0x13, 0x63); -+ err += zc0301_i2c_write(cam, 0x15, 0x70); -+ -+ err += zc0301_write_reg(cam, 0x0101, 0xB7); -+ err += zc0301_write_reg(cam, 0x0100, 0x0D); -+ err += zc0301_write_reg(cam, 0x0189, 0x06); -+ err += zc0301_write_reg(cam, 0x01AD, 0x00); -+ err += zc0301_write_reg(cam, 0x01C5, 0x03); -+ err += zc0301_write_reg(cam, 0x01CB, 0x13); -+ err += zc0301_write_reg(cam, 0x0250, 0x08); -+ err += zc0301_write_reg(cam, 0x0301, 0x08); -+ err += zc0301_write_reg(cam, 0x018D, 0x70); -+ err += zc0301_write_reg(cam, 0x0008, 0x03); -+ err += zc0301_write_reg(cam, 0x01C6, 0x04); -+ err += zc0301_write_reg(cam, 0x01CB, 0x07); -+ err += zc0301_write_reg(cam, 0x0120, 0x11); -+ err += zc0301_write_reg(cam, 0x0121, 0x37); -+ err += zc0301_write_reg(cam, 0x0122, 0x58); -+ err += zc0301_write_reg(cam, 0x0123, 0x79); -+ err += zc0301_write_reg(cam, 0x0124, 0x91); -+ err += zc0301_write_reg(cam, 0x0125, 0xA6); -+ err += zc0301_write_reg(cam, 0x0126, 0xB8); -+ err += zc0301_write_reg(cam, 0x0127, 0xC7); -+ err += zc0301_write_reg(cam, 0x0128, 0xD3); -+ err += zc0301_write_reg(cam, 0x0129, 0xDE); -+ err += zc0301_write_reg(cam, 0x012A, 0xE6); -+ err += zc0301_write_reg(cam, 0x012B, 0xED); -+ err += zc0301_write_reg(cam, 0x012C, 0xF3); -+ err += zc0301_write_reg(cam, 0x012D, 0xF8); -+ err += zc0301_write_reg(cam, 0x012E, 0xFB); -+ err += zc0301_write_reg(cam, 0x012F, 0xFF); -+ err += zc0301_write_reg(cam, 0x0130, 0x26); -+ err += zc0301_write_reg(cam, 0x0131, 0x23); -+ err += zc0301_write_reg(cam, 0x0132, 0x20); -+ err += zc0301_write_reg(cam, 0x0133, 0x1C); -+ err += zc0301_write_reg(cam, 0x0134, 0x16); -+ err += zc0301_write_reg(cam, 0x0135, 0x13); -+ err += zc0301_write_reg(cam, 0x0136, 0x10); -+ err += zc0301_write_reg(cam, 0x0137, 0x0D); -+ err += zc0301_write_reg(cam, 0x0138, 0x0B); -+ err += zc0301_write_reg(cam, 0x0139, 0x09); -+ err += zc0301_write_reg(cam, 0x013A, 0x07); -+ err += zc0301_write_reg(cam, 0x013B, 0x06); -+ err += zc0301_write_reg(cam, 0x013C, 0x05); -+ err += zc0301_write_reg(cam, 0x013D, 0x04); -+ err += zc0301_write_reg(cam, 0x013E, 0x03); -+ err += zc0301_write_reg(cam, 0x013F, 0x02); -+ err += zc0301_write_reg(cam, 0x010A, 0x4C); -+ err += zc0301_write_reg(cam, 0x010B, 0xF5); -+ err += zc0301_write_reg(cam, 0x010C, 0xFF); -+ err += zc0301_write_reg(cam, 0x010D, 0xF9); -+ err += zc0301_write_reg(cam, 0x010E, 0x51); -+ err += zc0301_write_reg(cam, 0x010F, 0xF5); -+ err += zc0301_write_reg(cam, 0x0110, 0xFB); -+ err += zc0301_write_reg(cam, 0x0111, 0xED); -+ err += zc0301_write_reg(cam, 0x0112, 0x5F); -+ err += zc0301_write_reg(cam, 0x0180, 0x00); -+ err += zc0301_write_reg(cam, 0x0019, 0x00); -+ err += zc0301_write_reg(cam, 0x0087, 0x20); -+ err += zc0301_write_reg(cam, 0x0088, 0x21); -+ -+ err += zc0301_i2c_write(cam, 0x20, 0x02); -+ err += zc0301_i2c_write(cam, 0x21, 0x1B); -+ err += zc0301_i2c_write(cam, 0x03, 0x44); -+ err += zc0301_i2c_write(cam, 0x0E, 0x01); -+ err += zc0301_i2c_write(cam, 0x0F, 0x00); -+ -+ err += zc0301_write_reg(cam, 0x01A9, 0x14); -+ err += zc0301_write_reg(cam, 0x01AA, 0x24); -+ err += zc0301_write_reg(cam, 0x0190, 0x00); -+ err += zc0301_write_reg(cam, 0x0191, 0x02); -+ err += zc0301_write_reg(cam, 0x0192, 0x1B); -+ err += zc0301_write_reg(cam, 0x0195, 0x00); -+ err += zc0301_write_reg(cam, 0x0196, 0x00); -+ err += zc0301_write_reg(cam, 0x0197, 0x4D); -+ err += zc0301_write_reg(cam, 0x018C, 0x10); -+ err += zc0301_write_reg(cam, 0x018F, 0x20); -+ err += zc0301_write_reg(cam, 0x001D, 0x44); -+ err += zc0301_write_reg(cam, 0x001E, 0x6F); -+ err += zc0301_write_reg(cam, 0x001F, 0xAD); -+ err += zc0301_write_reg(cam, 0x0020, 0xEB); -+ err += zc0301_write_reg(cam, 0x0087, 0x0F); -+ err += zc0301_write_reg(cam, 0x0088, 0x0E); -+ err += zc0301_write_reg(cam, 0x0180, 0x40); -+ err += zc0301_write_reg(cam, 0x0192, 0x1B); -+ err += zc0301_write_reg(cam, 0x0191, 0x02); -+ err += zc0301_write_reg(cam, 0x0190, 0x00); -+ err += zc0301_write_reg(cam, 0x0116, 0x1D); -+ err += zc0301_write_reg(cam, 0x0117, 0x40); -+ err += zc0301_write_reg(cam, 0x0118, 0x99); -+ err += zc0301_write_reg(cam, 0x0180, 0x42); -+ err += zc0301_write_reg(cam, 0x0116, 0x1D); -+ err += zc0301_write_reg(cam, 0x0117, 0x40); -+ err += zc0301_write_reg(cam, 0x0118, 0x99); -+ err += zc0301_write_reg(cam, 0x0007, 0x00); -+ -+ err += zc0301_i2c_write(cam, 0x11, 0x01); -+ -+ msleep(100); -+ -+ return err; -+} -+ -+ -+static int pas202bcb_get_ctrl(struct zc0301_device* cam, -+ struct v4l2_control* ctrl) -+{ -+ switch (ctrl->id) { -+ case V4L2_CID_EXPOSURE: -+ { -+ int r1 = zc0301_i2c_read(cam, 0x04, 1), -+ r2 = zc0301_i2c_read(cam, 0x05, 1); -+ if (r1 < 0 || r2 < 0) -+ return -EIO; -+ ctrl->value = (r1 << 6) | (r2 & 0x3f); -+ } -+ return 0; -+ case V4L2_CID_RED_BALANCE: -+ if ((ctrl->value = zc0301_i2c_read(cam, 0x09, 1)) < 0) -+ return -EIO; -+ ctrl->value &= 0x0f; -+ return 0; -+ case V4L2_CID_BLUE_BALANCE: -+ if ((ctrl->value = zc0301_i2c_read(cam, 0x07, 1)) < 0) -+ return -EIO; -+ ctrl->value &= 0x0f; -+ return 0; -+ case V4L2_CID_GAIN: -+ if ((ctrl->value = zc0301_i2c_read(cam, 0x10, 1)) < 0) -+ return -EIO; -+ ctrl->value &= 0x1f; -+ return 0; -+ case ZC0301_V4L2_CID_GREEN_BALANCE: -+ if ((ctrl->value = zc0301_i2c_read(cam, 0x08, 1)) < 0) -+ return -EIO; -+ ctrl->value &= 0x0f; -+ return 0; -+ case ZC0301_V4L2_CID_DAC_MAGNITUDE: -+ if ((ctrl->value = zc0301_i2c_read(cam, 0x0c, 1)) < 0) -+ return -EIO; -+ return 0; -+ default: -+ return -EINVAL; -+ } -+} -+ -+ -+static int pas202bcb_set_ctrl(struct zc0301_device* cam, -+ const struct v4l2_control* ctrl) -+{ -+ int err = 0; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_EXPOSURE: -+ err += zc0301_i2c_write(cam, 0x04, ctrl->value >> 6); -+ err += zc0301_i2c_write(cam, 0x05, ctrl->value & 0x3f); -+ break; -+ case V4L2_CID_RED_BALANCE: -+ err += zc0301_i2c_write(cam, 0x09, ctrl->value); -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ err += zc0301_i2c_write(cam, 0x07, ctrl->value); -+ break; -+ case V4L2_CID_GAIN: -+ err += zc0301_i2c_write(cam, 0x10, ctrl->value); -+ break; -+ case ZC0301_V4L2_CID_GREEN_BALANCE: -+ err += zc0301_i2c_write(cam, 0x08, ctrl->value); -+ break; -+ case ZC0301_V4L2_CID_DAC_MAGNITUDE: -+ err += zc0301_i2c_write(cam, 0x0c, ctrl->value); -+ break; -+ default: -+ return -EINVAL; -+ } -+ err += zc0301_i2c_write(cam, 0x11, 0x01); -+ -+ return err ? -EIO : 0; -+} -+ -+ -+static struct zc0301_sensor pas202bcb = { -+ .name = "PAS202BCB", -+ .init = &pas202bcb_init, -+ .qctrl = { -+ { -+ .id = V4L2_CID_EXPOSURE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "exposure", -+ .minimum = 0x01e5, -+ .maximum = 0x3fff, -+ .step = 0x0001, -+ .default_value = 0x01e5, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_GAIN, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "global gain", -+ .minimum = 0x00, -+ .maximum = 0x1f, -+ .step = 0x01, -+ .default_value = 0x0c, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_RED_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "red balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x01, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_BLUE_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "blue balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x05, -+ .flags = 0, -+ }, -+ { -+ .id = ZC0301_V4L2_CID_GREEN_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "green balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x00, -+ .flags = 0, -+ }, -+ { -+ .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "DAC magnitude", -+ .minimum = 0x00, -+ .maximum = 0xff, -+ .step = 0x01, -+ .default_value = 0x04, -+ .flags = 0, -+ }, -+ }, -+ .get_ctrl = &pas202bcb_get_ctrl, -+ .set_ctrl = &pas202bcb_set_ctrl, -+ .cropcap = { -+ .bounds = { -+ .left = 0, -+ .top = 0, -+ .width = 640, -+ .height = 480, -+ }, -+ .defrect = { -+ .left = 0, -+ .top = 0, -+ .width = 640, -+ .height = 480, -+ }, -+ }, -+ .pix_format = { -+ .width = 640, -+ .height = 480, -+ .pixelformat = V4L2_PIX_FMT_JPEG, -+ .priv = 16, -+ }, -+}; -+ -+ -+int zc0301_probe_pas202bcb(struct zc0301_device* cam) -+{ -+ int r0 = 0, r1 = 0, err = 0; -+ unsigned int pid = 0; -+ -+ err += zc0301_write_reg(cam, 0x0000, 0x01); -+ err += zc0301_write_reg(cam, 0x0010, 0x0e); -+ err += zc0301_write_reg(cam, 0x0001, 0x01); -+ err += zc0301_write_reg(cam, 0x0012, 0x03); -+ err += zc0301_write_reg(cam, 0x0012, 0x01); -+ err += zc0301_write_reg(cam, 0x008d, 0x08); -+ -+ msleep(10); -+ -+ r0 = zc0301_i2c_read(cam, 0x00, 1); -+ r1 = zc0301_i2c_read(cam, 0x01, 1); -+ -+ if (r0 < 0 || r1 < 0 || err) -+ return -EIO; -+ -+ pid = (r0 << 4) | ((r1 & 0xf0) >> 4); -+ if (pid != 0x017) -+ return -ENODEV; -+ -+ zc0301_attach_sensor(cam, &pas202bcb); -+ -+ return 0; -+} ---- /dev/null -+++ gregkh-2.6/drivers/usb/media/zc0301_sensor.h -@@ -0,0 +1,98 @@ -+/*************************************************************************** -+ * API for image sensors connected to the ZC030! Image Processor and * -+ * Control Chip * -+ * * -+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU General Public License as published by * -+ * the Free Software Foundation; either version 2 of the License, or * -+ * (at your option) any later version. * -+ * * -+ * This program is distributed in the hope that it will be useful, * -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -+ * GNU General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU General Public License * -+ * along with this program; if not, write to the Free Software * -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -+ ***************************************************************************/ -+ -+#ifndef _ZC0301_SENSOR_H_ -+#define _ZC0301_SENSOR_H_ -+ -+#include <linux/usb.h> -+#include <linux/videodev.h> -+#include <linux/device.h> -+#include <linux/stddef.h> -+#include <linux/errno.h> -+#include <asm/types.h> -+ -+struct zc0301_device; -+struct zc0301_sensor; -+ -+/*****************************************************************************/ -+ -+extern int zc0301_probe_pas202bcb(struct zc0301_device* cam); -+ -+#define ZC0301_SENSOR_TABLE \ -+/* Weak detections must go at the end of the list */ \ -+static int (*zc0301_sensor_table[])(struct zc0301_device*) = { \ -+ &zc0301_probe_pas202bcb, \ -+ NULL, \ -+}; -+ -+extern void -+zc0301_attach_sensor(struct zc0301_device* cam, -+ struct zc0301_sensor* sensor); -+ -+#define ZC0301_USB_DEVICE(vend, prod, intclass) \ -+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ -+ USB_DEVICE_ID_MATCH_INT_CLASS, \ -+ .idVendor = (vend), \ -+ .idProduct = (prod), \ -+ .bInterfaceClass = (intclass) -+ -+#define ZC0301_ID_TABLE \ -+static const struct usb_device_id zc0301_id_table[] = { \ -+ { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ -+ { } \ -+}; -+ -+/*****************************************************************************/ -+ -+extern int zc0301_write_reg(struct zc0301_device*, u16 index, u16 value); -+extern int zc0301_read_reg(struct zc0301_device*, u16 index); -+extern int zc0301_i2c_write(struct zc0301_device*, u16 address, u16 value); -+extern int zc0301_i2c_read(struct zc0301_device*, u16 address, u8 length); -+ -+/*****************************************************************************/ -+ -+#define ZC0301_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 -+#define ZC0301_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE -+#define ZC0301_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1 -+ -+struct zc0301_sensor { -+ char name[32]; -+ -+ struct v4l2_queryctrl qctrl[ZC0301_MAX_CTRLS]; -+ struct v4l2_cropcap cropcap; -+ struct v4l2_pix_format pix_format; -+ -+ int (*init)(struct zc0301_device* cam); -+ int (*get_ctrl)(struct zc0301_device* cam, -+ struct v4l2_control* ctrl); -+ int (*set_ctrl)(struct zc0301_device* cam, -+ const struct v4l2_control* ctrl); -+ int (*set_crop)(struct zc0301_device* cam, -+ const struct v4l2_rect* rect); -+ -+ const struct usb_device* usbdev; -+ -+ /* Private */ -+ struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; -+ struct v4l2_rect _rect; -+}; -+ -+#endif /* _ZC0301_SENSOR_H_ */ diff --git a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch b/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch deleted file mode 100644 index 2df571a82b2fa..0000000000000 --- a/usb/usb-convert-a-bunch-of-usb-semaphores-to-mutexes.patch +++ /dev/null @@ -1,3199 +0,0 @@ -From SRS0+792853cd028d39ab690f+871+infradead.org+arjan@pentafluge.srs.infradead.org Wed Jan 11 13:33:30 2006 -From: Arjan van de Ven <arjan@infradead.org> -Subject: USB: convert a bunch of USB semaphores to mutexes -To: <greg@kroah.com> -Cc: <mingo@elte.hu> -Date: Wed, 11 Jan 2006 15:55:29 +0100 -Message-Id: <1136991329.2929.57.camel@laptopd505.fenrus.org> - -the patch below converts a bunch of semaphores-used-as-mutex in the USB -code to mutexes - - -Signed-off-by: Arjan van de Ven <arjan@infradead.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/class/cdc-acm.c | 23 +++-- - drivers/usb/class/usblp.c | 15 ++- - drivers/usb/core/devices.c | 7 + - drivers/usb/core/hcd.c | 25 +++--- - drivers/usb/core/hcd.h | 2 - drivers/usb/core/hub.c | 7 + - drivers/usb/core/notify.c | 15 ++- - drivers/usb/core/usb.c | 5 - - drivers/usb/image/mdc800.c | 63 ++++++++------- - drivers/usb/input/ati_remote.c | 2 - drivers/usb/media/dabusb.c | 31 ++++--- - drivers/usb/media/dabusb.h | 2 - drivers/usb/media/ov511.c | 91 +++++++++++----------- - drivers/usb/media/ov511.h | 11 +- - drivers/usb/media/se401.c | 12 +-- - drivers/usb/media/se401.h | 3 - drivers/usb/media/sn9c102.h | 5 - - drivers/usb/media/sn9c102_core.c | 156 +++++++++++++++++++-------------------- - drivers/usb/media/stv680.c | 13 +-- - drivers/usb/media/stv680.h | 2 - drivers/usb/media/usbvideo.c | 28 +++---- - drivers/usb/media/usbvideo.h | 5 - - drivers/usb/media/vicam.c | 21 ++--- - drivers/usb/media/w9968cf.c | 75 ++++++++++-------- - drivers/usb/media/w9968cf.h | 14 --- - drivers/usb/misc/idmouse.c | 25 +++--- - drivers/usb/misc/ldusb.c | 11 +- - drivers/usb/misc/legousbtower.c | 11 +- - drivers/usb/mon/mon_main.c | 19 ++-- - drivers/usb/mon/mon_text.c | 21 ++--- - drivers/usb/mon/usb_mon.h | 2 - drivers/usb/storage/scsiglue.c | 9 +- - drivers/usb/storage/usb.c | 25 +++--- - drivers/usb/storage/usb.h | 5 - - 34 files changed, 389 insertions(+), 372 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/class/cdc-acm.c -+++ gregkh-2.6/drivers/usb/class/cdc-acm.c -@@ -60,6 +60,7 @@ - #include <linux/tty_flip.h> - #include <linux/module.h> - #include <linux/smp_lock.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - #include <linux/usb.h> - #include <linux/usb_cdc.h> -@@ -80,7 +81,7 @@ static struct usb_driver acm_driver; - static struct tty_driver *acm_tty_driver; - static struct acm *acm_table[ACM_TTY_MINORS]; - --static DECLARE_MUTEX(open_sem); -+static DEFINE_MUTEX(open_mutex); - - #define ACM_READY(acm) (acm && acm->dev && acm->used) - -@@ -431,8 +432,8 @@ static int acm_tty_open(struct tty_struc - int rv = -EINVAL; - int i; - dbg("Entering acm_tty_open.\n"); -- -- down(&open_sem); -+ -+ mutex_lock(&open_mutex); - - acm = acm_table[tty->index]; - if (!acm || !acm->dev) -@@ -474,14 +475,14 @@ static int acm_tty_open(struct tty_struc - - done: - err_out: -- up(&open_sem); -+ mutex_unlock(&open_mutex); - return rv; - - full_bailout: - usb_kill_urb(acm->ctrlurb); - bail_out: - acm->used--; -- up(&open_sem); -+ mutex_unlock(&open_mutex); - return -EIO; - } - -@@ -507,7 +508,7 @@ static void acm_tty_close(struct tty_str - if (!acm || !acm->used) - return; - -- down(&open_sem); -+ mutex_lock(&open_mutex); - if (!--acm->used) { - if (acm->dev) { - acm_set_control(acm, acm->ctrlout = 0); -@@ -518,7 +519,7 @@ static void acm_tty_close(struct tty_str - } else - acm_tty_unregister(acm); - } -- up(&open_sem); -+ mutex_unlock(&open_mutex); - } - - static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) -@@ -1013,9 +1014,9 @@ static void acm_disconnect(struct usb_in - return; - } - -- down(&open_sem); -+ mutex_lock(&open_mutex); - if (!usb_get_intfdata(intf)) { -- up(&open_sem); -+ mutex_unlock(&open_mutex); - return; - } - acm->dev = NULL; -@@ -1045,11 +1046,11 @@ static void acm_disconnect(struct usb_in - - if (!acm->used) { - acm_tty_unregister(acm); -- up(&open_sem); -+ mutex_unlock(&open_mutex); - return; - } - -- up(&open_sem); -+ mutex_unlock(&open_mutex); - - if (acm->tty) - tty_hangup(acm->tty); ---- gregkh-2.6.orig/drivers/usb/class/usblp.c -+++ gregkh-2.6/drivers/usb/class/usblp.c -@@ -55,6 +55,7 @@ - #include <linux/init.h> - #include <linux/slab.h> - #include <linux/lp.h> -+#include <linux/mutex.h> - #undef DEBUG - #include <linux/usb.h> - -@@ -223,7 +224,7 @@ static int usblp_cache_device_id_string( - - /* forward reference to make our lives easier */ - static struct usb_driver usblp_driver; --static DECLARE_MUTEX(usblp_sem); /* locks the existence of usblp's */ -+static DEFINE_MUTEX(usblp_mutex); /* locks the existence of usblp's */ - - /* - * Functions for usblp control messages. -@@ -351,7 +352,7 @@ static int usblp_open(struct inode *inod - if (minor < 0) - return -ENODEV; - -- down (&usblp_sem); -+ mutex_lock (&usblp_mutex); - - retval = -ENODEV; - intf = usb_find_interface(&usblp_driver, minor); -@@ -399,7 +400,7 @@ static int usblp_open(struct inode *inod - } - } - out: -- up (&usblp_sem); -+ mutex_unlock (&usblp_mutex); - return retval; - } - -@@ -425,13 +426,13 @@ static int usblp_release(struct inode *i - { - struct usblp *usblp = file->private_data; - -- down (&usblp_sem); -+ mutex_lock (&usblp_mutex); - usblp->used = 0; - if (usblp->present) { - usblp_unlink_urbs(usblp); - } else /* finish cleanup from disconnect */ - usblp_cleanup (usblp); -- up (&usblp_sem); -+ mutex_unlock (&usblp_mutex); - return 0; - } - -@@ -1152,7 +1153,7 @@ static void usblp_disconnect(struct usb_ - - device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - -- down (&usblp_sem); -+ mutex_lock (&usblp_mutex); - down (&usblp->sem); - usblp->present = 0; - usb_set_intfdata (intf, NULL); -@@ -1166,7 +1167,7 @@ static void usblp_disconnect(struct usb_ - - if (!usblp->used) - usblp_cleanup (usblp); -- up (&usblp_sem); -+ mutex_unlock (&usblp_mutex); - } - - static struct usb_device_id usblp_ids [] = { ---- gregkh-2.6.orig/drivers/usb/core/devices.c -+++ gregkh-2.6/drivers/usb/core/devices.c -@@ -57,6 +57,7 @@ - #include <linux/usb.h> - #include <linux/smp_lock.h> - #include <linux/usbdevice_fs.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - - #include "usb.h" -@@ -570,7 +571,7 @@ static ssize_t usb_device_read(struct fi - if (!access_ok(VERIFY_WRITE, buf, nbytes)) - return -EFAULT; - -- down (&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - /* print devices for all busses */ - list_for_each_entry(bus, &usb_bus_list, bus_list) { - /* recurse through all children of the root hub */ -@@ -580,12 +581,12 @@ static ssize_t usb_device_read(struct fi - 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) { -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return ret; - } - total_written += ret; - } -- up (&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return total_written; - } - ---- gregkh-2.6.orig/drivers/usb/core/hcd.c -+++ gregkh-2.6/drivers/usb/core/hcd.c -@@ -34,6 +34,7 @@ - #include <asm/scatterlist.h> - #include <linux/device.h> - #include <linux/dma-mapping.h> -+#include <linux/mutex.h> - #include <asm/irq.h> - #include <asm/byteorder.h> - -@@ -93,7 +94,7 @@ struct usb_busmap { - static struct usb_busmap busmap; - - /* used when updating list of hcds */ --DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ -+DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ - EXPORT_SYMBOL_GPL (usb_bus_list_lock); - - /* used for controlling access to virtual root hubs */ -@@ -761,14 +762,14 @@ static int usb_register_bus(struct usb_b - { - int busnum; - -- down (&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); - if (busnum < USB_MAXBUS) { - set_bit (busnum, busmap.busmap); - bus->busnum = busnum; - } else { - printk (KERN_ERR "%s: too many buses\n", usbcore_name); -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return -E2BIG; - } - -@@ -776,7 +777,7 @@ static int usb_register_bus(struct usb_b - bus->controller, "usb_host%d", busnum); - if (IS_ERR(bus->class_dev)) { - clear_bit(busnum, busmap.busmap); -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return PTR_ERR(bus->class_dev); - } - -@@ -784,7 +785,7 @@ static int usb_register_bus(struct usb_b - - /* Add it to the local list of buses */ - list_add (&bus->bus_list, &usb_bus_list); -- up (&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - - usb_notify_add_bus(bus); - -@@ -809,9 +810,9 @@ static void usb_deregister_bus (struct u - * controller code, as well as having it call this when cleaning - * itself up - */ -- down (&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - list_del (&bus->bus_list); -- up (&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - - usb_notify_remove_bus(bus); - -@@ -844,14 +845,14 @@ static int register_root_hub (struct usb - set_bit (devnum, usb_dev->bus->devmap.devicemap); - usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - -- down (&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - usb_dev->bus->root_hub = usb_dev; - - usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); - retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); - if (retval != sizeof usb_dev->descriptor) { - usb_dev->bus->root_hub = NULL; -- up (&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - dev_dbg (parent_dev, "can't read %s device descriptor %d\n", - usb_dev->dev.bus_id, retval); - return (retval < 0) ? retval : -EMSGSIZE; -@@ -863,7 +864,7 @@ static int register_root_hub (struct usb - dev_err (parent_dev, "can't register root hub for %s, %d\n", - usb_dev->dev.bus_id, retval); - } -- up (&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - - if (retval == 0) { - spin_lock_irq (&hcd_root_hub_lock); -@@ -1891,9 +1892,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) - hcd->rh_registered = 0; - spin_unlock_irq (&hcd_root_hub_lock); - -- down(&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - usb_disconnect(&hcd->self.root_hub); -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - - hcd->poll_rh = 0; - del_timer_sync(&hcd->rh_timer); ---- gregkh-2.6.orig/drivers/usb/core/hcd.h -+++ gregkh-2.6/drivers/usb/core/hcd.h -@@ -364,7 +364,7 @@ extern void usb_set_device_state(struct - /* exported only within usbcore */ - - extern struct list_head usb_bus_list; --extern struct semaphore usb_bus_list_lock; -+extern struct mutex usb_bus_list_lock; - extern wait_queue_head_t usb_kill_urb_queue; - - extern struct usb_bus *usb_bus_get (struct usb_bus *bus); ---- gregkh-2.6.orig/drivers/usb/core/hub.c -+++ gregkh-2.6/drivers/usb/core/hub.c -@@ -22,6 +22,7 @@ - #include <linux/usb.h> - #include <linux/usbdevice_fs.h> - #include <linux/kthread.h> -+#include <linux/mutex.h> - - #include <asm/semaphore.h> - #include <asm/uaccess.h> -@@ -2162,7 +2163,7 @@ static int - hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, - int retry_counter) - { -- static DECLARE_MUTEX(usb_address0_sem); -+ static DEFINE_MUTEX(usb_address0_mutex); - - struct usb_device *hdev = hub->hdev; - int i, j, retval; -@@ -2183,7 +2184,7 @@ hub_port_init (struct usb_hub *hub, stru - if (oldspeed == USB_SPEED_LOW) - delay = HUB_LONG_RESET_TIME; - -- down(&usb_address0_sem); -+ mutex_lock(&usb_address0_mutex); - - /* Reset the device; full speed may morph to high speed */ - retval = hub_port_reset(hub, port1, udev, delay); -@@ -2381,7 +2382,7 @@ hub_port_init (struct usb_hub *hub, stru - fail: - if (retval) - hub_port_disable(hub, port1, 0); -- up(&usb_address0_sem); -+ mutex_unlock(&usb_address0_mutex); - return retval; - } - ---- gregkh-2.6.orig/drivers/usb/core/notify.c -+++ gregkh-2.6/drivers/usb/core/notify.c -@@ -13,16 +13,17 @@ - #include <linux/kernel.h> - #include <linux/notifier.h> - #include <linux/usb.h> -+#include <linux/mutex.h> - #include "usb.h" - - - static struct notifier_block *usb_notifier_list; --static DECLARE_MUTEX(usb_notifier_lock); -+static DEFINE_MUTEX(usb_notifier_lock); - - static void usb_notifier_chain_register(struct notifier_block **list, - struct notifier_block *n) - { -- down(&usb_notifier_lock); -+ mutex_lock(&usb_notifier_lock); - while (*list) { - if (n->priority > (*list)->priority) - break; -@@ -30,13 +31,13 @@ static void usb_notifier_chain_register( - } - n->next = *list; - *list = n; -- up(&usb_notifier_lock); -+ mutex_unlock(&usb_notifier_lock); - } - - static void usb_notifier_chain_unregister(struct notifier_block **nl, - struct notifier_block *n) - { -- down(&usb_notifier_lock); -+ mutex_lock(&usb_notifier_lock); - while ((*nl)!=NULL) { - if ((*nl)==n) { - *nl = n->next; -@@ -45,7 +46,7 @@ static void usb_notifier_chain_unregiste - nl=&((*nl)->next); - } - exit: -- up(&usb_notifier_lock); -+ mutex_unlock(&usb_notifier_lock); - } - - static int usb_notifier_call_chain(struct notifier_block **n, -@@ -54,7 +55,7 @@ static int usb_notifier_call_chain(struc - int ret=NOTIFY_DONE; - struct notifier_block *nb = *n; - -- down(&usb_notifier_lock); -+ mutex_lock(&usb_notifier_lock); - while (nb) { - ret = nb->notifier_call(nb,val,v); - if (ret&NOTIFY_STOP_MASK) { -@@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struc - nb = nb->next; - } - exit: -- up(&usb_notifier_lock); -+ mutex_unlock(&usb_notifier_lock); - return ret; - } - ---- gregkh-2.6.orig/drivers/usb/core/usb.c -+++ gregkh-2.6/drivers/usb/core/usb.c -@@ -33,6 +33,7 @@ - #include <linux/errno.h> - #include <linux/smp_lock.h> - #include <linux/usb.h> -+#include <linux/mutex.h> - - #include <asm/io.h> - #include <asm/scatterlist.h> -@@ -639,7 +640,7 @@ struct usb_device *usb_find_device(u16 v - struct usb_bus *bus; - struct usb_device *dev = NULL; - -- down(&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - for (buslist = usb_bus_list.next; - buslist != &usb_bus_list; - buslist = buslist->next) { -@@ -653,7 +654,7 @@ struct usb_device *usb_find_device(u16 v - goto exit; - } - exit: -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return dev; - } - ---- gregkh-2.6.orig/drivers/usb/image/mdc800.c -+++ gregkh-2.6/drivers/usb/image/mdc800.c -@@ -96,6 +96,7 @@ - #include <linux/module.h> - #include <linux/smp_lock.h> - #include <linux/wait.h> -+#include <linux/mutex.h> - - #include <linux/usb.h> - #include <linux/fs.h> -@@ -169,7 +170,7 @@ struct mdc800_data - int out_count; // Bytes in the buffer - - int open; // Camera device open ? -- struct semaphore io_lock; // IO -lock -+ struct mutex io_lock; // IO -lock - - char in [8]; // Command Input Buffer - int in_count; -@@ -497,7 +498,7 @@ static int mdc800_usb_probe (struct usb_ - - info ("Found Mustek MDC800 on USB."); - -- down (&mdc800->io_lock); -+ mutex_lock(&mdc800->io_lock); - - retval = usb_register_dev(intf, &mdc800_class); - if (retval) { -@@ -542,7 +543,7 @@ static int mdc800_usb_probe (struct usb_ - - mdc800->state=READY; - -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - - usb_set_intfdata(intf, mdc800); - return 0; -@@ -620,7 +621,7 @@ static int mdc800_device_open (struct in - int retval=0; - int errn=0; - -- down (&mdc800->io_lock); -+ mutex_lock(&mdc800->io_lock); - - if (mdc800->state == NOT_CONNECTED) - { -@@ -656,7 +657,7 @@ static int mdc800_device_open (struct in - dbg ("Mustek MDC800 device opened."); - - error_out: -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return errn; - } - -@@ -669,7 +670,7 @@ static int mdc800_device_release (struct - int retval=0; - dbg ("Mustek MDC800 device closed."); - -- down (&mdc800->io_lock); -+ mutex_lock(&mdc800->io_lock); - if (mdc800->open && (mdc800->state != NOT_CONNECTED)) - { - usb_kill_urb(mdc800->irq_urb); -@@ -682,7 +683,7 @@ static int mdc800_device_release (struct - retval=-EIO; - } - -- up(&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return retval; - } - -@@ -695,21 +696,21 @@ static ssize_t mdc800_device_read (struc - size_t left=len, sts=len; /* single transfer size */ - char __user *ptr = buf; - -- down (&mdc800->io_lock); -+ mutex_lock(&mdc800->io_lock); - if (mdc800->state == NOT_CONNECTED) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EBUSY; - } - if (mdc800->state == WORKING) - { - warn ("Illegal State \"working\" reached during read ?!"); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EBUSY; - } - if (!mdc800->open) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EBUSY; - } - -@@ -717,7 +718,7 @@ static ssize_t mdc800_device_read (struc - { - if (signal_pending (current)) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EINTR; - } - -@@ -736,7 +737,7 @@ static ssize_t mdc800_device_read (struc - if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL)) - { - err ("Can't submit download urb (status=%i)",mdc800->download_urb->status); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return len-left; - } - wait_event_timeout(mdc800->download_wait, mdc800->downloaded, -@@ -745,14 +746,14 @@ static ssize_t mdc800_device_read (struc - if (mdc800->download_urb->status != 0) - { - err ("request download-bytes fails (status=%i)",mdc800->download_urb->status); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return len-left; - } - } - else - { - /* No more bytes -> that's an error*/ -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - } -@@ -761,7 +762,7 @@ static ssize_t mdc800_device_read (struc - /* Copy Bytes */ - if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], - sts)) { -- up(&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EFAULT; - } - ptr+=sts; -@@ -770,7 +771,7 @@ static ssize_t mdc800_device_read (struc - } - } - -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return len-left; - } - -@@ -785,15 +786,15 @@ static ssize_t mdc800_device_write (stru - { - size_t i=0; - -- down (&mdc800->io_lock); -+ mutex_lock(&mdc800->io_lock); - if (mdc800->state != READY) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EBUSY; - } - if (!mdc800->open ) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EBUSY; - } - -@@ -802,13 +803,13 @@ static ssize_t mdc800_device_write (stru - unsigned char c; - if (signal_pending (current)) - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EINTR; - } - - if(get_user(c, buf+i)) - { -- up(&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EFAULT; - } - -@@ -829,7 +830,7 @@ static ssize_t mdc800_device_write (stru - } - else - { -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - -@@ -841,7 +842,7 @@ static ssize_t mdc800_device_write (stru - if (mdc800_usb_waitForIRQ (0,TO_GET_READY)) - { - err ("Camera didn't get ready.\n"); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - -@@ -853,7 +854,7 @@ static ssize_t mdc800_device_write (stru - if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL)) - { - err ("submitting write urb fails (status=%i)", mdc800->write_urb->status); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000); -@@ -861,7 +862,7 @@ static ssize_t mdc800_device_write (stru - if (mdc800->state == WORKING) - { - usb_kill_urb(mdc800->write_urb); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - -@@ -873,7 +874,7 @@ static ssize_t mdc800_device_write (stru - { - err ("call 0x07 before 0x05,0x3e"); - mdc800->state=READY; -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - mdc800->pic_len=-1; -@@ -892,7 +893,7 @@ static ssize_t mdc800_device_write (stru - if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ)) - { - err ("requesting answer from irq fails"); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - -@@ -920,7 +921,7 @@ static ssize_t mdc800_device_write (stru - if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND)) - { - err ("Command Timeout."); -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return -EIO; - } - } -@@ -930,7 +931,7 @@ static ssize_t mdc800_device_write (stru - } - i++; - } -- up (&mdc800->io_lock); -+ mutex_unlock(&mdc800->io_lock); - return i; - } - -@@ -984,7 +985,7 @@ static int __init usb_mdc800_init (void) - - mdc800->dev = NULL; - mdc800->state=NOT_CONNECTED; -- init_MUTEX (&mdc800->io_lock); -+ mutex_init (&mdc800->io_lock); - - init_waitqueue_head (&mdc800->irq_wait); - init_waitqueue_head (&mdc800->write_wait); ---- gregkh-2.6.orig/drivers/usb/input/ati_remote.c -+++ gregkh-2.6/drivers/usb/input/ati_remote.c -@@ -159,8 +159,6 @@ static const char accel[] = { 1, 2, 4, 6 - */ - #define FILTER_TIME (HZ / 20) - --static DECLARE_MUTEX(disconnect_sem); -- - struct ati_remote { - struct input_dev *idev; - struct usb_device *udev; ---- gregkh-2.6.orig/drivers/usb/media/dabusb.c -+++ gregkh-2.6/drivers/usb/media/dabusb.c -@@ -38,6 +38,7 @@ - #include <linux/delay.h> - #include <linux/usb.h> - #include <linux/smp_lock.h> -+#include <linux/mutex.h> - - #include "dabusb.h" - #include "dabfirmware.h" -@@ -570,7 +571,7 @@ static ssize_t dabusb_read (struct file - s->readptr = 0; - } - } -- err: //up(&s->mutex); -+ err: //mutex_unlock(&s->mutex); - return ret; - } - -@@ -585,10 +586,10 @@ static int dabusb_open (struct inode *in - s = &dabusb[devnum - DABUSB_MINOR]; - - dbg("dabusb_open"); -- down (&s->mutex); -+ mutex_lock(&s->mutex); - - while (!s->usbdev || s->opened) { -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - - if (file->f_flags & O_NONBLOCK) { - return -EBUSY; -@@ -598,15 +599,15 @@ static int dabusb_open (struct inode *in - if (signal_pending (current)) { - return -EAGAIN; - } -- down (&s->mutex); -+ mutex_lock(&s->mutex); - } - if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { -- up(&s->mutex); -+ mutex_unlock(&s->mutex); - err("set_interface failed"); - return -EINVAL; - } - s->opened = 1; -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - - file->f_pos = 0; - file->private_data = s; -@@ -620,10 +621,10 @@ static int dabusb_release (struct inode - - dbg("dabusb_release"); - -- down (&s->mutex); -+ mutex_lock(&s->mutex); - dabusb_stop (s); - dabusb_free_buffers (s); -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - - if (!s->remove_pending) { - if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) -@@ -648,10 +649,10 @@ static int dabusb_ioctl (struct inode *i - if (s->remove_pending) - return -EIO; - -- down (&s->mutex); -+ mutex_lock(&s->mutex); - - if (!s->usbdev) { -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - return -EIO; - } - -@@ -691,7 +692,7 @@ static int dabusb_ioctl (struct inode *i - ret = -ENOIOCTLCMD; - break; - } -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - return ret; - } - -@@ -737,7 +738,7 @@ static int dabusb_probe (struct usb_inte - - s = &dabusb[intf->minor]; - -- down (&s->mutex); -+ mutex_lock(&s->mutex); - s->remove_pending = 0; - s->usbdev = usbdev; - s->devnum = intf->minor; -@@ -760,7 +761,7 @@ static int dabusb_probe (struct usb_inte - } - dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); - usb_set_intfdata (intf, s); -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - - retval = usb_register_dev(intf, &dabusb_class); - if (retval) { -@@ -771,7 +772,7 @@ static int dabusb_probe (struct usb_inte - return 0; - - reject: -- up (&s->mutex); -+ mutex_unlock(&s->mutex); - s->usbdev = NULL; - return -ENODEV; - } -@@ -828,7 +829,7 @@ static int __init dabusb_init (void) - for (u = 0; u < NRDABUSB; u++) { - pdabusb_t s = &dabusb[u]; - memset (s, 0, sizeof (dabusb_t)); -- init_MUTEX (&s->mutex); -+ mutex_init (&s->mutex); - s->usbdev = NULL; - s->total_buffer_size = buffers; - init_waitqueue_head (&s->wait); ---- gregkh-2.6.orig/drivers/usb/media/dabusb.h -+++ gregkh-2.6/drivers/usb/media/dabusb.h -@@ -18,7 +18,7 @@ typedef enum { _stopped=0, _started } dr - - typedef struct - { -- struct semaphore mutex; -+ struct mutex mutex; - struct usb_device *usbdev; - wait_queue_head_t wait; - wait_queue_head_t remove_ok; ---- gregkh-2.6.orig/drivers/usb/media/ov511.c -+++ gregkh-2.6/drivers/usb/media/ov511.c -@@ -365,14 +365,14 @@ reg_w(struct usb_ov511 *ov, unsigned cha - - PDEBUG(5, "0x%02X:0x%02X", reg, value); - -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - ov->cbuf[0] = value; - rc = usb_control_msg(ov->dev, - usb_sndctrlpipe(ov->dev, 0), - (ov->bclass == BCL_OV518)?1:2 /* REG_IO */, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, &ov->cbuf[0], 1, 1000); -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - - if (rc < 0) - err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc)); -@@ -387,7 +387,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha - { - int rc; - -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - rc = usb_control_msg(ov->dev, - usb_rcvctrlpipe(ov->dev, 0), - (ov->bclass == BCL_OV518)?1:3 /* REG_IO */, -@@ -401,7 +401,7 @@ reg_r(struct usb_ov511 *ov, unsigned cha - PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]); - } - -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - - return rc; - } -@@ -444,7 +444,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi - - PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n); - -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - - *((__le32 *)ov->cbuf) = __cpu_to_le32(val); - -@@ -453,7 +453,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsi - 1 /* REG_IO */, - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, (__u16)reg, ov->cbuf, n, 1000); -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - - if (rc < 0) - err("reg write multiple: error %d: %s", rc, -@@ -768,14 +768,14 @@ i2c_r(struct usb_ov511 *ov, unsigned cha - { - int rc; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_read_internal(ov, reg); - else - rc = ov511_i2c_read_internal(ov, reg); - -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - - return rc; - } -@@ -785,14 +785,14 @@ i2c_w(struct usb_ov511 *ov, unsigned cha - { - int rc; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - - if (ov->bclass == BCL_OV518) - rc = ov518_i2c_write_internal(ov, reg, value); - else - rc = ov511_i2c_write_internal(ov, reg, value); - -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - - return rc; - } -@@ -842,9 +842,9 @@ i2c_w_mask(struct usb_ov511 *ov, - { - int rc; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask); -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - - return rc; - } -@@ -880,7 +880,7 @@ i2c_w_slave(struct usb_ov511 *ov, - { - int rc = 0; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - - /* Set new slave IDs */ - rc = i2c_set_slave_internal(ov, slave); -@@ -894,7 +894,7 @@ out: - if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) - err("Couldn't restore primary I2C slave"); - -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - return rc; - } - -@@ -906,7 +906,7 @@ i2c_r_slave(struct usb_ov511 *ov, - { - int rc; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - - /* Set new slave IDs */ - rc = i2c_set_slave_internal(ov, slave); -@@ -923,7 +923,7 @@ out: - if (i2c_set_slave_internal(ov, ov->primary_i2c_slave) < 0) - err("Couldn't restore primary I2C slave"); - -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - return rc; - } - -@@ -933,7 +933,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov - { - int rc; - -- down(&ov->i2c_lock); -+ mutex_lock(&ov->i2c_lock); - - rc = i2c_set_slave_internal(ov, sid); - if (rc < 0) -@@ -942,7 +942,7 @@ ov51x_set_slave_ids(struct usb_ov511 *ov - // FIXME: Is this actually necessary? - rc = ov51x_reset(ov, OV511_RESET_NOREGS); - out: -- up(&ov->i2c_lock); -+ mutex_unlock(&ov->i2c_lock); - return rc; - } - -@@ -3832,7 +3832,7 @@ ov51x_alloc(struct usb_ov511 *ov) - const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h); - - PDEBUG(4, "entered"); -- down(&ov->buf_lock); -+ mutex_lock(&ov->buf_lock); - - if (ov->buf_state == BUF_ALLOCATED) - goto out; -@@ -3879,12 +3879,12 @@ ov51x_alloc(struct usb_ov511 *ov) - - ov->buf_state = BUF_ALLOCATED; - out: -- up(&ov->buf_lock); -+ mutex_unlock(&ov->buf_lock); - PDEBUG(4, "leaving"); - return 0; - error: - ov51x_do_dealloc(ov); -- up(&ov->buf_lock); -+ mutex_unlock(&ov->buf_lock); - PDEBUG(4, "errored"); - return -ENOMEM; - } -@@ -3893,9 +3893,9 @@ static void - ov51x_dealloc(struct usb_ov511 *ov) - { - PDEBUG(4, "entered"); -- down(&ov->buf_lock); -+ mutex_lock(&ov->buf_lock); - ov51x_do_dealloc(ov); -- up(&ov->buf_lock); -+ mutex_unlock(&ov->buf_lock); - PDEBUG(4, "leaving"); - } - -@@ -3914,7 +3914,7 @@ ov51x_v4l1_open(struct inode *inode, str - - PDEBUG(4, "opening"); - -- down(&ov->lock); -+ mutex_lock(&ov->lock); - - err = -EBUSY; - if (ov->user) -@@ -3958,7 +3958,7 @@ ov51x_v4l1_open(struct inode *inode, str - ov51x_led_control(ov, 1); - - out: -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return err; - } - -@@ -3970,7 +3970,7 @@ ov51x_v4l1_close(struct inode *inode, st - - PDEBUG(4, "ov511_close"); - -- down(&ov->lock); -+ mutex_lock(&ov->lock); - - ov->user--; - ov51x_stop_isoc(ov); -@@ -3981,15 +3981,15 @@ ov51x_v4l1_close(struct inode *inode, st - if (ov->dev) - ov51x_dealloc(ov); - -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - - /* Device unplugged while open. Only a minimum of unregistration is done - * here; the disconnect callback already did the rest. */ - if (!ov->dev) { -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - - ov51x_dealloc(ov); - kfree(ov); -@@ -4449,12 +4449,12 @@ ov51x_v4l1_ioctl(struct inode *inode, st - struct usb_ov511 *ov = video_get_drvdata(vdev); - int rc; - -- if (down_interruptible(&ov->lock)) -+ if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal); - -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return rc; - } - -@@ -4468,7 +4468,7 @@ ov51x_v4l1_read(struct file *file, char - int i, rc = 0, frmx = -1; - struct ov511_frame *frame; - -- if (down_interruptible(&ov->lock)) -+ if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - PDEBUG(4, "%ld bytes, noblock=%d", count, noblock); -@@ -4604,11 +4604,11 @@ restart: - - PDEBUG(4, "read finished, returning %ld (sweet)", count); - -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return count; - - error: -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return rc; - } - -@@ -4631,14 +4631,14 @@ ov51x_v4l1_mmap(struct file *file, struc - + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))) - return -EINVAL; - -- if (down_interruptible(&ov->lock)) -+ if (mutex_lock_interruptible(&ov->lock)) - return -EINTR; - - pos = (unsigned long)ov->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return -EAGAIN; - } - start += PAGE_SIZE; -@@ -4649,7 +4649,7 @@ ov51x_v4l1_mmap(struct file *file, struc - size = 0; - } - -- up(&ov->lock); -+ mutex_unlock(&ov->lock); - return 0; - } - -@@ -5738,11 +5738,10 @@ ov51x_probe(struct usb_interface *intf, - - init_waitqueue_head(&ov->wq); - -- init_MUTEX(&ov->lock); /* to 1 == available */ -- init_MUTEX(&ov->buf_lock); -- init_MUTEX(&ov->param_lock); -- init_MUTEX(&ov->i2c_lock); -- init_MUTEX(&ov->cbuf_lock); -+ mutex_init(&ov->lock); /* to 1 == available */ -+ mutex_init(&ov->buf_lock); -+ mutex_init(&ov->i2c_lock); -+ mutex_init(&ov->cbuf_lock); - - ov->buf_state = BUF_NOT_ALLOCATED; - -@@ -5833,10 +5832,10 @@ error: - } - - if (ov->cbuf) { -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - } - - kfree(ov); -@@ -5881,10 +5880,10 @@ ov51x_disconnect(struct usb_interface *i - - /* Free the memory */ - if (ov && !ov->user) { -- down(&ov->cbuf_lock); -+ mutex_lock(&ov->cbuf_lock); - kfree(ov->cbuf); - ov->cbuf = NULL; -- up(&ov->cbuf_lock); -+ mutex_unlock(&ov->cbuf_lock); - - ov51x_dealloc(ov); - kfree(ov); ---- gregkh-2.6.orig/drivers/usb/media/ov511.h -+++ gregkh-2.6/drivers/usb/media/ov511.h -@@ -5,6 +5,7 @@ - #include <linux/videodev.h> - #include <linux/smp_lock.h> - #include <linux/usb.h> -+#include <linux/mutex.h> - - #define OV511_DEBUG /* Turn on debug messages */ - -@@ -435,7 +436,7 @@ struct usb_ov511 { - - int led_policy; /* LED: off|on|auto; OV511+ only */ - -- struct semaphore lock; /* Serializes user-accessible operations */ -+ struct mutex lock; /* Serializes user-accessible operations */ - int user; /* user count for exclusive use */ - - int streaming; /* Are we streaming Isochronous? */ -@@ -473,11 +474,9 @@ struct usb_ov511 { - int packet_size; /* Frame size per isoc desc */ - int packet_numbering; /* Is ISO frame numbering enabled? */ - -- struct semaphore param_lock; /* params lock for this camera */ -- - /* Framebuffer/sbuf management */ - int buf_state; -- struct semaphore buf_lock; -+ struct mutex buf_lock; - - struct ov51x_decomp_ops *decomp_ops; - -@@ -494,12 +493,12 @@ struct usb_ov511 { - int pal; /* Device is designed for PAL resolution */ - - /* I2C interface */ -- struct semaphore i2c_lock; /* Protect I2C controller regs */ -+ struct mutex i2c_lock; /* Protect I2C controller regs */ - unsigned char primary_i2c_slave; /* I2C write id of sensor */ - - /* Control transaction stuff */ - unsigned char *cbuf; /* Buffer for payload */ -- struct semaphore cbuf_lock; -+ struct mutex cbuf_lock; - }; - - /* Used to represent a list of values and their respective symbolic names */ ---- gregkh-2.6.orig/drivers/usb/media/se401.c -+++ gregkh-2.6/drivers/usb/media/se401.c -@@ -1157,21 +1157,21 @@ static int se401_mmap(struct file *file, - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - -- down(&se401->lock); -+ mutex_lock(&se401->lock); - - if (se401->dev == NULL) { -- up(&se401->lock); -+ mutex_unlock(&se401->lock); - return -EIO; - } - if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { -- up(&se401->lock); -+ mutex_unlock(&se401->lock); - return -EINVAL; - } - pos = (unsigned long)se401->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { -- up(&se401->lock); -+ mutex_unlock(&se401->lock); - return -EAGAIN; - } - start += PAGE_SIZE; -@@ -1181,7 +1181,7 @@ static int se401_mmap(struct file *file, - else - size = 0; - } -- up(&se401->lock); -+ mutex_unlock(&se401->lock); - - return 0; - } -@@ -1366,7 +1366,7 @@ static int se401_probe(struct usb_interf - memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); - memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); - init_waitqueue_head(&se401->wq); -- init_MUTEX(&se401->lock); -+ mutex_init(&se401->lock); - wmb(); - - if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { ---- gregkh-2.6.orig/drivers/usb/media/se401.h -+++ gregkh-2.6/drivers/usb/media/se401.h -@@ -5,6 +5,7 @@ - #include <asm/uaccess.h> - #include <linux/videodev.h> - #include <linux/smp_lock.h> -+#include <linux/mutex.h> - - #define se401_DEBUG /* Turn on debug messages */ - -@@ -189,7 +190,7 @@ struct usb_se401 { - int maxframesize; - int cframesize; /* current framesize */ - -- struct semaphore lock; -+ struct mutex lock; - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - ---- gregkh-2.6.orig/drivers/usb/media/sn9c102.h -+++ gregkh-2.6/drivers/usb/media/sn9c102.h -@@ -33,6 +33,7 @@ - #include <linux/types.h> - #include <linux/param.h> - #include <linux/rwsem.h> -+#include <linux/mutex.h> - #include <asm/semaphore.h> - - #include "sn9c102_sensor.h" -@@ -109,7 +110,7 @@ struct sn9c102_module_param { - u8 force_munmap; - }; - --static DECLARE_MUTEX(sn9c102_sysfs_lock); -+static DEFINE_MUTEX(sn9c102_sysfs_lock); - static DECLARE_RWSEM(sn9c102_disconnect); - - struct sn9c102_device { -@@ -141,7 +142,7 @@ struct sn9c102_device { - enum sn9c102_dev_state state; - u8 users; - -- struct semaphore dev_sem, fileop_sem; -+ struct mutex dev_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; - }; ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_core.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_core.c -@@ -866,18 +866,18 @@ static ssize_t sn9c102_show_reg(struct c - struct sn9c102_device* cam; - ssize_t count; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -890,18 +890,18 @@ sn9c102_store_reg(struct class_device* c - u8 index; - ssize_t count; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou8(buf, len, &count); - if (index > 0x1f || !count) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - -@@ -910,7 +910,7 @@ sn9c102_store_reg(struct class_device* c - DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -922,17 +922,17 @@ static ssize_t sn9c102_show_val(struct c - ssize_t count; - int val; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - -@@ -940,7 +940,7 @@ static ssize_t sn9c102_show_val(struct c - - DBG(3, "Read bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -954,24 +954,24 @@ sn9c102_store_val(struct class_device* c - ssize_t count; - int err; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - value = sn9c102_strtou8(buf, len, &count); - if (!count) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_write_reg(cam, value, cam->sysfs.reg); - if (err) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - -@@ -979,7 +979,7 @@ sn9c102_store_val(struct class_device* c - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -990,12 +990,12 @@ static ssize_t sn9c102_show_i2c_reg(stru - struct sn9c102_device* cam; - ssize_t count; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - -@@ -1003,7 +1003,7 @@ static ssize_t sn9c102_show_i2c_reg(stru - - DBG(3, "Read bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -1016,18 +1016,18 @@ sn9c102_store_i2c_reg(struct class_devic - u8 index; - ssize_t count; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - index = sn9c102_strtou8(buf, len, &count); - if (!count) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - -@@ -1036,7 +1036,7 @@ sn9c102_store_i2c_reg(struct class_devic - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -1048,22 +1048,22 @@ static ssize_t sn9c102_show_i2c_val(stru - ssize_t count; - int val; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - -@@ -1071,7 +1071,7 @@ static ssize_t sn9c102_show_i2c_val(stru - - DBG(3, "Read bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -1085,29 +1085,29 @@ sn9c102_store_i2c_val(struct class_devic - ssize_t count; - int err; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } - - value = sn9c102_strtou8(buf, len, &count); - if (!count) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EINVAL; - } - - err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -EIO; - } - -@@ -1115,7 +1115,7 @@ sn9c102_store_i2c_val(struct class_devic - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - return count; - } -@@ -1130,18 +1130,18 @@ sn9c102_store_green(struct class_device* - u8 value; - ssize_t count; - -- if (down_interruptible(&sn9c102_sysfs_lock)) -+ if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - return -ENODEV; - } - - bridge = cam->bridge; - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - value = sn9c102_strtou8(buf, len, &count); - if (!count) -@@ -1404,7 +1404,7 @@ static int sn9c102_init(struct sn9c102_d - } - - if (!(cam->state & DEV_INITIALIZED)) { -- init_MUTEX(&cam->fileop_sem); -+ mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); -@@ -1422,13 +1422,13 @@ static int sn9c102_init(struct sn9c102_d - - static void sn9c102_release_resources(struct sn9c102_device* cam) - { -- down(&sn9c102_sysfs_lock); -+ mutex_lock(&sn9c102_sysfs_lock); - - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - -- up(&sn9c102_sysfs_lock); -+ mutex_unlock(&sn9c102_sysfs_lock); - - kfree(cam->control_buffer); - } -@@ -1449,7 +1449,7 @@ static int sn9c102_open(struct inode* in - - cam = video_get_drvdata(video_devdata(filp)); - -- if (down_interruptible(&cam->dev_sem)) { -+ if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&sn9c102_disconnect); - return -ERESTARTSYS; - } -@@ -1461,7 +1461,7 @@ static int sn9c102_open(struct inode* in - err = -EWOULDBLOCK; - goto out; - } -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); -@@ -1473,7 +1473,7 @@ static int sn9c102_open(struct inode* in - up_read(&sn9c102_disconnect); - return -ENODEV; - } -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - } - - -@@ -1501,7 +1501,7 @@ static int sn9c102_open(struct inode* in - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); - - out: -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&sn9c102_disconnect); - return err; - } -@@ -1511,7 +1511,7 @@ static int sn9c102_release(struct inode* - { - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - -- down(&cam->dev_sem); /* prevent disconnect() to be called */ -+ mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - sn9c102_stop_transfer(cam); - -@@ -1519,7 +1519,7 @@ static int sn9c102_release(struct inode* - - if (cam->state & DEV_DISCONNECTED) { - sn9c102_release_resources(cam); -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } -@@ -1529,7 +1529,7 @@ static int sn9c102_release(struct inode* - - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - return 0; - } -@@ -1543,33 +1543,33 @@ sn9c102_read(struct file* filp, char __u - unsigned long lock_flags; - int err = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose " - "the read method"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - - if (cam->io == IO_NONE) { - if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) { - DBG(1, "read() failed, not enough memory"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; -@@ -1583,13 +1583,13 @@ sn9c102_read(struct file* filp, char __u - } - - if (!count) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - err = wait_event_interruptible -@@ -1598,15 +1598,15 @@ sn9c102_read(struct file* filp, char __u - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED) ); - if (err) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return err; - } - if (cam->state & DEV_DISCONNECTED) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - if (cam->state & DEV_MISCONFIGURED) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } -@@ -1634,7 +1634,7 @@ exit: - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return count; - } -@@ -1647,7 +1647,7 @@ static unsigned int sn9c102_poll(struct - unsigned long lock_flags; - unsigned int mask = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { -@@ -1685,12 +1685,12 @@ static unsigned int sn9c102_poll(struct - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return mask; - - error: -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return POLLERR; - } - -@@ -1724,25 +1724,25 @@ static int sn9c102_mmap(struct file* fil - void *pos; - u32 i; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - -@@ -1751,7 +1751,7 @@ static int sn9c102_mmap(struct file* fil - break; - } - if (i == cam->nbuffers) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - -@@ -1761,7 +1761,7 @@ static int sn9c102_mmap(struct file* fil - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; -@@ -1774,7 +1774,7 @@ static int sn9c102_mmap(struct file* fil - - sn9c102_vm_open(vma); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return 0; - } -@@ -2655,19 +2655,19 @@ static int sn9c102_ioctl(struct inode* i - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - int err = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - -@@ -2675,7 +2675,7 @@ static int sn9c102_ioctl(struct inode* i - - err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return err; - } -@@ -2722,7 +2722,7 @@ sn9c102_usb_probe(struct usb_interface* - goto fail; - } - -- init_MUTEX(&cam->dev_sem); -+ mutex_init(&cam->dev_mutex); - - r = sn9c102_read_reg(cam, 0x00); - if (r < 0 || r != 0x10) { -@@ -2776,7 +2776,7 @@ sn9c102_usb_probe(struct usb_interface* - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); -@@ -2786,7 +2786,7 @@ sn9c102_usb_probe(struct usb_interface* - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - goto fail; - } - -@@ -2803,7 +2803,7 @@ sn9c102_usb_probe(struct usb_interface* - - usb_set_intfdata(intf, cam); - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - return 0; - -@@ -2827,7 +2827,7 @@ static void sn9c102_usb_disconnect(struc - - down_write(&sn9c102_disconnect); - -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - -@@ -2847,7 +2847,7 @@ static void sn9c102_usb_disconnect(struc - sn9c102_release_resources(cam); - } - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); ---- gregkh-2.6.orig/drivers/usb/media/stv680.c -+++ gregkh-2.6/drivers/usb/media/stv680.c -@@ -67,6 +67,7 @@ - #include <linux/errno.h> - #include <linux/videodev.h> - #include <linux/usb.h> -+#include <linux/mutex.h> - - #include "stv680.h" - -@@ -1258,22 +1259,22 @@ static int stv680_mmap (struct file *fil - unsigned long size = vma->vm_end-vma->vm_start; - unsigned long page, pos; - -- down (&stv680->lock); -+ mutex_lock(&stv680->lock); - - if (stv680->udev == NULL) { -- up (&stv680->lock); -+ mutex_unlock(&stv680->lock); - return -EIO; - } - if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) - & ~(PAGE_SIZE - 1))) { -- up (&stv680->lock); -+ mutex_unlock(&stv680->lock); - return -EINVAL; - } - pos = (unsigned long) stv680->fbuf; - while (size > 0) { - page = vmalloc_to_pfn((void *)pos); - if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { -- up (&stv680->lock); -+ mutex_unlock(&stv680->lock); - return -EAGAIN; - } - start += PAGE_SIZE; -@@ -1283,7 +1284,7 @@ static int stv680_mmap (struct file *fil - else - size = 0; - } -- up (&stv680->lock); -+ mutex_unlock(&stv680->lock); - - return 0; - } -@@ -1409,7 +1410,7 @@ static int stv680_probe (struct usb_inte - - memcpy (stv680->vdev->name, stv680->camera_name, strlen (stv680->camera_name)); - init_waitqueue_head (&stv680->wq); -- init_MUTEX (&stv680->lock); -+ mutex_init (&stv680->lock); - wmb (); - - if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { ---- gregkh-2.6.orig/drivers/usb/media/stv680.h -+++ gregkh-2.6/drivers/usb/media/stv680.h -@@ -118,7 +118,7 @@ struct usb_stv { - int origGain; - int origMode; /* original camera mode */ - -- struct semaphore lock; /* to lock the structure */ -+ struct mutex lock; /* to lock the structure */ - int user; /* user count for exclusive use */ - int removed; /* device disconnected */ - int streaming; /* Are we streaming video? */ ---- gregkh-2.6.orig/drivers/usb/media/usbvideo.c -+++ gregkh-2.6/drivers/usb/media/usbvideo.c -@@ -714,7 +714,7 @@ int usbvideo_register( - cams->md_module = md; - if (cams->md_module == NULL) - warn("%s: module == NULL!", __FUNCTION__); -- init_MUTEX(&cams->lock); /* to 1 == available */ -+ mutex_init(&cams->lock); /* to 1 == available */ - - for (i = 0; i < num_cams; i++) { - struct uvd *up = &cams->cam[i]; -@@ -862,7 +862,7 @@ static void usbvideo_Disconnect(struct u - if (uvd->debug > 0) - info("%s(%p.)", __FUNCTION__, intf); - -- down(&uvd->lock); -+ mutex_lock(&uvd->lock); - uvd->remove_pending = 1; /* Now all ISO data will be ignored */ - - /* At this time we ask to cancel outstanding URBs */ -@@ -882,7 +882,7 @@ static void usbvideo_Disconnect(struct u - info("%s: In use, disconnect pending.", __FUNCTION__); - else - usbvideo_CameraRelease(uvd); -- up(&uvd->lock); -+ mutex_unlock(&uvd->lock); - info("USB camera disconnected."); - - usbvideo_ClientDecModCount(uvd); -@@ -929,19 +929,19 @@ static int usbvideo_find_struct(struct u - err("No usbvideo handle?"); - return -1; - } -- down(&cams->lock); -+ mutex_lock(&cams->lock); - for (u = 0; u < cams->num_cameras; u++) { - struct uvd *uvd = &cams->cam[u]; - if (!uvd->uvd_used) /* This one is free */ - { - uvd->uvd_used = 1; /* In use now */ -- init_MUTEX(&uvd->lock); /* to 1 == available */ -+ mutex_init(&uvd->lock); /* to 1 == available */ - uvd->dev = NULL; - rv = u; - break; - } - } -- up(&cams->lock); -+ mutex_unlock(&cams->lock); - return rv; - } - -@@ -983,7 +983,7 @@ struct uvd *usbvideo_AllocateDevice(stru - /* Not relying upon caller we increase module counter ourselves */ - usbvideo_ClientIncModCount(uvd); - -- down(&uvd->lock); -+ mutex_lock(&uvd->lock); - for (i=0; i < USBVIDEO_NUMSBUF; i++) { - uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); - if (uvd->sbuf[i].urb == NULL) { -@@ -1006,7 +1006,7 @@ struct uvd *usbvideo_AllocateDevice(stru - * return control to the client's probe function right now. - */ - allocate_done: -- up (&uvd->lock); -+ mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - return uvd; - } -@@ -1120,7 +1120,7 @@ static int usbvideo_v4l_open(struct inod - info("%s($%p)", __FUNCTION__, dev); - - usbvideo_ClientIncModCount(uvd); -- down(&uvd->lock); -+ mutex_lock(&uvd->lock); - - if (uvd->user) { - err("%s: Someone tried to open an already opened device!", __FUNCTION__); -@@ -1201,7 +1201,7 @@ static int usbvideo_v4l_open(struct inod - } - } - } -- up(&uvd->lock); -+ mutex_unlock(&uvd->lock); - if (errCode != 0) - usbvideo_ClientDecModCount(uvd); - if (uvd->debug > 0) -@@ -1230,7 +1230,7 @@ static int usbvideo_v4l_close(struct ino - if (uvd->debug > 1) - info("%s($%p)", __FUNCTION__, dev); - -- down(&uvd->lock); -+ mutex_lock(&uvd->lock); - GET_CALLBACK(uvd, stopDataPump)(uvd); - usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); - uvd->fbuf = NULL; -@@ -1251,7 +1251,7 @@ static int usbvideo_v4l_close(struct ino - info("usbvideo_v4l_close: Final disconnect."); - usbvideo_CameraRelease(uvd); - } -- up(&uvd->lock); -+ mutex_unlock(&uvd->lock); - usbvideo_ClientDecModCount(uvd); - - if (uvd->debug > 1) -@@ -1511,7 +1511,7 @@ static ssize_t usbvideo_v4l_read(struct - if (uvd->debug >= 1) - info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock); - -- down(&uvd->lock); -+ mutex_lock(&uvd->lock); - - /* See if a frame is completed, then use it. */ - for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { -@@ -1643,7 +1643,7 @@ static ssize_t usbvideo_v4l_read(struct - } - } - read_done: -- up(&uvd->lock); -+ mutex_unlock(&uvd->lock); - return count; - } - ---- gregkh-2.6.orig/drivers/usb/media/usbvideo.h -+++ gregkh-2.6/drivers/usb/media/usbvideo.h -@@ -19,6 +19,7 @@ - #include <linux/config.h> - #include <linux/videodev.h> - #include <linux/usb.h> -+#include <linux/mutex.h> - - /* Most helpful debugging aid */ - #define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) -@@ -213,7 +214,7 @@ struct uvd { - unsigned long flags; /* FLAGS_USBVIDEO_xxx */ - unsigned long paletteBits; /* Which palettes we accept? */ - unsigned short defaultPalette; /* What palette to use for read() */ -- struct semaphore lock; -+ struct mutex lock; - int user; /* user count for exclusive use */ - - videosize_t videosize; /* Current setting */ -@@ -272,7 +273,7 @@ struct usbvideo { - int num_cameras; /* As allocated */ - struct usb_driver usbdrv; /* Interface to the USB stack */ - char drvName[80]; /* Driver name */ -- struct semaphore lock; /* Mutex protecting camera structures */ -+ struct mutex lock; /* Mutex protecting camera structures */ - struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */ - struct video_device vdt; /* Video device template */ - struct uvd *cam; /* Array of camera structures */ ---- gregkh-2.6.orig/drivers/usb/media/vicam.c -+++ gregkh-2.6/drivers/usb/media/vicam.c -@@ -42,6 +42,7 @@ - #include <linux/vmalloc.h> - #include <linux/slab.h> - #include <linux/proc_fs.h> -+#include <linux/mutex.h> - #include "usbvideo.h" - - // #define VICAM_DEBUG -@@ -407,7 +408,7 @@ struct vicam_camera { - struct usb_device *udev; // usb device - - /* guard against simultaneous accesses to the camera */ -- struct semaphore cam_lock; -+ struct mutex cam_lock; - - int is_initialized; - u8 open_count; -@@ -461,12 +462,12 @@ static int send_control_msg(struct vicam - u16 size) - { - int status = -ENODEV; -- down(&cam->cam_lock); -+ mutex_lock(&cam->cam_lock); - if (cam->udev) { - status = __send_control_msg(cam, request, value, - index, cp, size); - } -- up(&cam->cam_lock); -+ mutex_unlock(&cam->cam_lock); - return status; - } - static int -@@ -831,13 +832,13 @@ vicam_close(struct inode *inode, struct - rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); - kfree(cam->cntrlbuf); - -- down(&cam->cam_lock); -+ mutex_lock(&cam->cam_lock); - - cam->open_count--; - open_count = cam->open_count; - udev = cam->udev; - -- up(&cam->cam_lock); -+ mutex_unlock(&cam->cam_lock); - - if (!open_count && !udev) { - kfree(cam); -@@ -960,7 +961,7 @@ read_frame(struct vicam_camera *cam, int - request[8] = 0; - // bytes 9-15 do not seem to affect exposure or image quality - -- down(&cam->cam_lock); -+ mutex_lock(&cam->cam_lock); - - if (!cam->udev) { - goto done; -@@ -985,7 +986,7 @@ read_frame(struct vicam_camera *cam, int - } - - done: -- up(&cam->cam_lock); -+ mutex_unlock(&cam->cam_lock); - } - - static ssize_t -@@ -1309,7 +1310,7 @@ vicam_probe( struct usb_interface *intf, - - cam->shutter_speed = 15; - -- init_MUTEX(&cam->cam_lock); -+ mutex_init(&cam->cam_lock); - - memcpy(&cam->vdev, &vicam_template, - sizeof (vicam_template)); -@@ -1351,7 +1352,7 @@ vicam_disconnect(struct usb_interface *i - - /* stop the camera from being used */ - -- down(&cam->cam_lock); -+ mutex_lock(&cam->cam_lock); - - /* mark the camera as gone */ - -@@ -1368,7 +1369,7 @@ vicam_disconnect(struct usb_interface *i - - open_count = cam->open_count; - -- up(&cam->cam_lock); -+ mutex_unlock(&cam->cam_lock); - - if (!open_count) { - kfree(cam); ---- gregkh-2.6.orig/drivers/usb/media/w9968cf.c -+++ gregkh-2.6/drivers/usb/media/w9968cf.c -@@ -47,6 +47,13 @@ - #include "w9968cf.h" - #include "w9968cf_decoder.h" - -+static struct w9968cf_vpp_t* w9968cf_vpp; -+static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); -+ -+static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ -+static DEFINE_MUTEX(w9968cf_devlist_mutex); /* semaphore for list traversal */ -+ -+static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ - - - /**************************************************************************** -@@ -2418,7 +2425,7 @@ w9968cf_configure_camera(struct w9968cf_ - enum w9968cf_model_id mod_id, - const unsigned short dev_nr) - { -- init_MUTEX(&cam->fileop_sem); -+ mutex_init(&cam->fileop_mutex); - init_waitqueue_head(&cam->open); - spin_lock_init(&cam->urb_lock); - spin_lock_init(&cam->flist_lock); -@@ -2646,7 +2653,7 @@ static void w9968cf_adjust_configuration - --------------------------------------------------------------------------*/ - static void w9968cf_release_resources(struct w9968cf_device* cam) - { -- down(&w9968cf_devlist_sem); -+ mutex_lock(&w9968cf_devlist_mutex); - - DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) - -@@ -2657,7 +2664,7 @@ static void w9968cf_release_resources(st - kfree(cam->control_buffer); - kfree(cam->data_buffer); - -- up(&w9968cf_devlist_sem); -+ mutex_unlock(&w9968cf_devlist_mutex); - } - - -@@ -2677,14 +2684,14 @@ static int w9968cf_open(struct inode* in - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - if (cam->sensor == CC_UNKNOWN) { - DBG(2, "No supported image sensor has been detected by the " - "'ovcamchip' module for the %s (/dev/video%d). Make " - "sure it is loaded *before* (re)connecting the camera.", - symbolic(camlist, cam->id), cam->v4ldev->minor) -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return -ENODEV; - } -@@ -2693,11 +2700,11 @@ static int w9968cf_open(struct inode* in - DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", - symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) - if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return -EWOULDBLOCK; - } -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->disconnected || - !cam->users); -@@ -2709,7 +2716,7 @@ static int w9968cf_open(struct inode* in - up_read(&w9968cf_disconnect); - return -ENODEV; - } -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - } - - DBG(5, "Opening '%s', /dev/video%d ...", -@@ -2738,7 +2745,7 @@ static int w9968cf_open(struct inode* in - - DBG(5, "Video device is open") - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - - return 0; -@@ -2746,7 +2753,7 @@ static int w9968cf_open(struct inode* in - deallocate_memory: - w9968cf_deallocate_memory(cam); - DBG(2, "Failed to open the video device") -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&w9968cf_disconnect); - return err; - } -@@ -2758,13 +2765,13 @@ static int w9968cf_release(struct inode* - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - -- down(&cam->dev_sem); /* prevent disconnect() to be called */ -+ mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - w9968cf_stop_transfer(cam); - - if (cam->disconnected) { - w9968cf_release_resources(cam); -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } -@@ -2774,7 +2781,7 @@ static int w9968cf_release(struct inode* - wake_up_interruptible_nr(&cam->open, 1); - - DBG(5, "Video device closed") -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - return 0; - } - -@@ -2791,18 +2798,18 @@ w9968cf_read(struct file* filp, char __u - if (filp->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->disconnected) { - DBG(2, "Device not present") -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->misconfigured) { - DBG(2, "The camera is misconfigured. Close and open it again.") -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - -@@ -2817,11 +2824,11 @@ w9968cf_read(struct file* filp, char __u - cam->frame[1].status == F_READY || - cam->disconnected); - if (err) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return err; - } - if (cam->disconnected) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - -@@ -2835,7 +2842,7 @@ w9968cf_read(struct file* filp, char __u - - if (copy_to_user(buf, fr->buffer, count)) { - fr->status = F_UNUSED; -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EFAULT; - } - *f_pos += count; -@@ -2844,7 +2851,7 @@ w9968cf_read(struct file* filp, char __u - - DBG(5, "%zu bytes read", count) - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return count; - } - -@@ -2898,24 +2905,24 @@ w9968cf_ioctl(struct inode* inode, struc - - cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp)); - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->disconnected) { - DBG(2, "Device not present") -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->misconfigured) { - DBG(2, "The camera is misconfigured. Close and open it again.") -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return err; - } - -@@ -3502,8 +3509,8 @@ w9968cf_usb_probe(struct usb_interface* - if (!cam) - return -ENOMEM; - -- init_MUTEX(&cam->dev_sem); -- down(&cam->dev_sem); -+ mutex_init(&cam->dev_mutex); -+ mutex_lock(&cam->dev_mutex); - - cam->usbdev = udev; - /* NOTE: a local copy is used to avoid possible race conditions */ -@@ -3515,10 +3522,10 @@ w9968cf_usb_probe(struct usb_interface* - simcams = W9968CF_SIMCAMS; - - /* How many cameras are connected ? */ -- down(&w9968cf_devlist_sem); -+ mutex_lock(&w9968cf_devlist_mutex); - list_for_each(ptr, &w9968cf_dev_list) - sc++; -- up(&w9968cf_devlist_sem); -+ mutex_unlock(&w9968cf_devlist_mutex); - - if (sc >= simcams) { - DBG(2, "Device rejected: too many connected cameras " -@@ -3578,9 +3585,9 @@ w9968cf_usb_probe(struct usb_interface* - w9968cf_configure_camera(cam, udev, mod_id, dev_nr); - - /* Add a new entry into the list of V4L registered devices */ -- down(&w9968cf_devlist_sem); -+ mutex_lock(&w9968cf_devlist_mutex); - list_add(&cam->v4llist, &w9968cf_dev_list); -- up(&w9968cf_devlist_sem); -+ mutex_unlock(&w9968cf_devlist_mutex); - dev_nr = (dev_nr < W9968CF_MAX_DEVICES-1) ? dev_nr+1 : 0; - - w9968cf_turn_on_led(cam); -@@ -3588,7 +3595,7 @@ w9968cf_usb_probe(struct usb_interface* - w9968cf_i2c_init(cam); - - usb_set_intfdata(intf, cam); -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - return 0; - - fail: /* Free unused memory */ -@@ -3596,7 +3603,7 @@ fail: /* Free unused memory */ - kfree(cam->data_buffer); - if (cam->v4ldev) - video_device_release(cam->v4ldev); -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - kfree(cam); - return err; - } -@@ -3611,7 +3618,7 @@ static void w9968cf_usb_disconnect(struc - - if (cam) { - /* Prevent concurrent accesses to data */ -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - cam->disconnected = 1; - -@@ -3630,7 +3637,7 @@ static void w9968cf_usb_disconnect(struc - } else - w9968cf_release_resources(cam); - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); ---- gregkh-2.6.orig/drivers/usb/media/w9968cf.h -+++ gregkh-2.6/drivers/usb/media/w9968cf.h -@@ -32,7 +32,7 @@ - #include <linux/param.h> - #include <linux/types.h> - #include <linux/rwsem.h> --#include <asm/semaphore.h> -+#include <linux/mutex.h> - - #include <media/ovcamchip.h> - -@@ -194,14 +194,6 @@ enum w9968cf_vpp_flag { - VPP_UYVY_TO_RGBX = 0x08, - }; - --static struct w9968cf_vpp_t* w9968cf_vpp; --static DECLARE_WAIT_QUEUE_HEAD(w9968cf_vppmod_wait); -- --static LIST_HEAD(w9968cf_dev_list); /* head of V4L registered cameras list */ --static DECLARE_MUTEX(w9968cf_devlist_sem); /* semaphore for list traversal */ -- --static DECLARE_RWSEM(w9968cf_disconnect); /* prevent races with open() */ -- - /* Main device driver structure */ - struct w9968cf_device { - struct device dev; /* device structure */ -@@ -277,8 +269,8 @@ struct w9968cf_device { - struct i2c_client* sensor_client; - - /* Locks */ -- struct semaphore dev_sem, /* for probe, disconnect,open and close */ -- fileop_sem; /* for read and ioctl */ -+ struct mutex dev_mutex, /* for probe, disconnect,open and close */ -+ fileop_mutex; /* for read and ioctl */ - spinlock_t urb_lock, /* for submit_urb() and unlink_urb() */ - flist_lock; /* for requested frame list accesses */ - wait_queue_head_t open, wait_queue; ---- gregkh-2.6.orig/drivers/usb/misc/idmouse.c -+++ gregkh-2.6/drivers/usb/misc/idmouse.c -@@ -25,6 +25,7 @@ - #include <linux/module.h> - #include <linux/smp_lock.h> - #include <linux/completion.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - #include <linux/usb.h> - -@@ -121,7 +122,7 @@ static struct usb_driver idmouse_driver - }; - - /* prevent races between open() and disconnect() */ --static DECLARE_MUTEX(disconnect_sem); -+static DEFINE_MUTEX(disconnect_mutex); - - static int idmouse_create_image(struct usb_idmouse *dev) - { -@@ -213,18 +214,18 @@ static int idmouse_open(struct inode *in - int result = 0; - - /* prevent disconnects */ -- down(&disconnect_sem); -+ mutex_lock(&disconnect_mutex); - - /* get the interface from minor number and driver information */ - interface = usb_find_interface (&idmouse_driver, iminor (inode)); - if (!interface) { -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return -ENODEV; - } - /* get the device information block from the interface */ - dev = usb_get_intfdata(interface); - if (!dev) { -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return -ENODEV; - } - -@@ -258,7 +259,7 @@ error: - up(&dev->sem); - - /* unlock the disconnect semaphore */ -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return result; - } - -@@ -267,12 +268,12 @@ static int idmouse_release(struct inode - struct usb_idmouse *dev; - - /* prevent a race condition with open() */ -- down(&disconnect_sem); -+ mutex_lock(&disconnect_mutex); - - dev = (struct usb_idmouse *) file->private_data; - - if (dev == NULL) { -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return -ENODEV; - } - -@@ -282,7 +283,7 @@ static int idmouse_release(struct inode - /* are we really open? */ - if (dev->open <= 0) { - up(&dev->sem); -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return -ENODEV; - } - -@@ -292,12 +293,12 @@ static int idmouse_release(struct inode - /* the device was unplugged before the file was released */ - up(&dev->sem); - idmouse_delete(dev); -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return 0; - } - - up(&dev->sem); -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - return 0; - } - -@@ -399,7 +400,7 @@ static void idmouse_disconnect(struct us - struct usb_idmouse *dev; - - /* prevent races with open() */ -- down(&disconnect_sem); -+ mutex_lock(&disconnect_mutex); - - /* get device structure */ - dev = usb_get_intfdata(interface); -@@ -421,7 +422,7 @@ static void idmouse_disconnect(struct us - if (!dev->open) - idmouse_delete(dev); - -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - - info("%s disconnected", DRIVER_DESC); - } ---- gregkh-2.6.orig/drivers/usb/misc/ldusb.c -+++ gregkh-2.6/drivers/usb/misc/ldusb.c -@@ -33,6 +33,7 @@ - #include <linux/init.h> - #include <linux/slab.h> - #include <linux/module.h> -+#include <linux/mutex.h> - - #include <asm/uaccess.h> - #include <linux/input.h> -@@ -172,7 +173,7 @@ struct ld_usb { - }; - - /* prevent races between open() and disconnect() */ --static DECLARE_MUTEX(disconnect_sem); -+static DEFINE_MUTEX(disconnect_mutex); - - static struct usb_driver ld_usb_driver; - -@@ -293,7 +294,7 @@ static int ld_usb_open(struct inode *ino - nonseekable_open(inode, file); - subminor = iminor(inode); - -- down(&disconnect_sem); -+ mutex_lock(&disconnect_mutex); - - interface = usb_find_interface(&ld_usb_driver, subminor); - -@@ -355,7 +356,7 @@ unlock_exit: - up(&dev->sem); - - unlock_disconnect_exit: -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - - return retval; - } -@@ -740,7 +741,7 @@ static void ld_usb_disconnect(struct usb - struct ld_usb *dev; - int minor; - -- down(&disconnect_sem); -+ mutex_lock(&disconnect_mutex); - - dev = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); -@@ -761,7 +762,7 @@ static void ld_usb_disconnect(struct usb - up(&dev->sem); - } - -- up(&disconnect_sem); -+ mutex_unlock(&disconnect_mutex); - - dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", - (minor - USB_LD_MINOR_BASE)); ---- gregkh-2.6.orig/drivers/usb/misc/legousbtower.c -+++ gregkh-2.6/drivers/usb/misc/legousbtower.c -@@ -83,6 +83,7 @@ - #include <linux/module.h> - #include <linux/smp_lock.h> - #include <linux/completion.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - #include <linux/usb.h> - #include <linux/poll.h> -@@ -256,7 +257,7 @@ static void tower_disconnect (struct usb - - - /* prevent races between open() and disconnect */ --static DECLARE_MUTEX (disconnect_sem); -+static DEFINE_MUTEX (disconnect_mutex); - - /* file operations needed when we register this driver */ - static struct file_operations tower_fops = { -@@ -349,7 +350,7 @@ static int tower_open (struct inode *ino - nonseekable_open(inode, file); - subminor = iminor(inode); - -- down (&disconnect_sem); -+ mutex_lock (&disconnect_mutex); - - interface = usb_find_interface (&tower_driver, subminor); - -@@ -427,7 +428,7 @@ unlock_exit: - up (&dev->sem); - - unlock_disconnect_exit: -- up (&disconnect_sem); -+ mutex_unlock (&disconnect_mutex); - - dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); - -@@ -1005,7 +1006,7 @@ static void tower_disconnect (struct usb - - dbg(2, "%s: enter", __FUNCTION__); - -- down (&disconnect_sem); -+ mutex_lock (&disconnect_mutex); - - dev = usb_get_intfdata (interface); - usb_set_intfdata (interface, NULL); -@@ -1027,7 +1028,7 @@ static void tower_disconnect (struct usb - up (&dev->sem); - } - -- up (&disconnect_sem); -+ mutex_unlock (&disconnect_mutex); - - info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); - ---- gregkh-2.6.orig/drivers/usb/mon/mon_main.c -+++ gregkh-2.6/drivers/usb/mon/mon_main.c -@@ -12,6 +12,7 @@ - #include <linux/debugfs.h> - #include <linux/smp_lock.h> - #include <linux/notifier.h> -+#include <linux/mutex.h> - - #include "usb_mon.h" - #include "../core/hcd.h" -@@ -23,7 +24,7 @@ static void mon_dissolve(struct mon_bus - static void mon_bus_drop(struct kref *r); - static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus); - --DECLARE_MUTEX(mon_lock); -+DEFINE_MUTEX(mon_lock); - - static struct dentry *mon_dir; /* /dbg/usbmon */ - static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ -@@ -196,14 +197,14 @@ static void mon_bus_remove(struct usb_bu - { - struct mon_bus *mbus = ubus->mon_bus; - -- down(&mon_lock); -+ mutex_lock(&mon_lock); - list_del(&mbus->bus_link); - debugfs_remove(mbus->dent_t); - debugfs_remove(mbus->dent_s); - - mon_dissolve(mbus, ubus); - kref_put(&mbus->ref, mon_bus_drop); -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - } - - static int mon_notify(struct notifier_block *self, unsigned long action, -@@ -307,9 +308,9 @@ static void mon_bus_init(struct dentry * - goto err_create_s; - mbus->dent_s = d; - -- down(&mon_lock); -+ mutex_lock(&mon_lock); - list_add_tail(&mbus->bus_link, &mon_buses); -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - return; - - err_create_s: -@@ -347,11 +348,11 @@ static int __init mon_init(void) - - usb_register_notify(&mon_nb); - -- down(&usb_bus_list_lock); -+ mutex_lock(&usb_bus_list_lock); - list_for_each_entry (ubus, &usb_bus_list, bus_list) { - mon_bus_init(mondir, ubus); - } -- up(&usb_bus_list_lock); -+ mutex_unlock(&usb_bus_list_lock); - return 0; - } - -@@ -363,7 +364,7 @@ static void __exit mon_exit(void) - usb_unregister_notify(&mon_nb); - usb_mon_deregister(); - -- down(&mon_lock); -+ mutex_lock(&mon_lock); - while (!list_empty(&mon_buses)) { - p = mon_buses.next; - mbus = list_entry(p, struct mon_bus, bus_link); -@@ -387,7 +388,7 @@ static void __exit mon_exit(void) - mon_dissolve(mbus, mbus->u_bus); - kref_put(&mbus->ref, mon_bus_drop); - } -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - - debugfs_remove(mon_dir); - } ---- gregkh-2.6.orig/drivers/usb/mon/mon_text.c -+++ gregkh-2.6/drivers/usb/mon/mon_text.c -@@ -8,6 +8,7 @@ - #include <linux/list.h> - #include <linux/usb.h> - #include <linux/time.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - - #include "usb_mon.h" -@@ -54,7 +55,7 @@ struct mon_reader_text { - wait_queue_head_t wait; - int printf_size; - char *printf_buf; -- struct semaphore printf_lock; -+ struct mutex printf_lock; - - char slab_name[SLAB_NAME_SZ]; - }; -@@ -208,7 +209,7 @@ static int mon_text_open(struct inode *i - struct mon_reader_text *rp; - int rc; - -- down(&mon_lock); -+ mutex_lock(&mon_lock); - mbus = inode->u.generic_ip; - ubus = mbus->u_bus; - -@@ -220,7 +221,7 @@ static int mon_text_open(struct inode *i - memset(rp, 0, sizeof(struct mon_reader_text)); - INIT_LIST_HEAD(&rp->e_list); - init_waitqueue_head(&rp->wait); -- init_MUTEX(&rp->printf_lock); -+ mutex_init(&rp->printf_lock); - - rp->printf_size = PRINTF_DFL; - rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL); -@@ -247,7 +248,7 @@ static int mon_text_open(struct inode *i - mon_reader_add(mbus, &rp->r); - - file->private_data = rp; -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - return 0; - - // err_busy: -@@ -257,7 +258,7 @@ err_slab: - err_alloc_pr: - kfree(rp); - err_alloc: -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - return rc; - } - -@@ -301,7 +302,7 @@ static ssize_t mon_text_read(struct file - set_current_state(TASK_RUNNING); - remove_wait_queue(&rp->wait, &waita); - -- down(&rp->printf_lock); -+ mutex_lock(&rp->printf_lock); - cnt = 0; - pbuf = rp->printf_buf; - limit = rp->printf_size; -@@ -358,7 +359,7 @@ static ssize_t mon_text_read(struct file - - if (copy_to_user(buf, rp->printf_buf, cnt)) - cnt = -EFAULT; -- up(&rp->printf_lock); -+ mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return cnt; - } -@@ -371,12 +372,12 @@ static int mon_text_release(struct inode - struct list_head *p; - struct mon_event_text *ep; - -- down(&mon_lock); -+ mutex_lock(&mon_lock); - mbus = inode->u.generic_ip; - - if (mbus->nreaders <= 0) { - printk(KERN_ERR TAG ": consistency error on close\n"); -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - return 0; - } - mon_reader_del(mbus, &rp->r); -@@ -402,7 +403,7 @@ static int mon_text_release(struct inode - kfree(rp->printf_buf); - kfree(rp); - -- up(&mon_lock); -+ mutex_unlock(&mon_lock); - return 0; - } - ---- gregkh-2.6.orig/drivers/usb/mon/usb_mon.h -+++ gregkh-2.6/drivers/usb/mon/usb_mon.h -@@ -49,7 +49,7 @@ void mon_reader_del(struct mon_bus *mbus - */ - extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); - --extern struct semaphore mon_lock; -+extern struct mutex mon_lock; - - extern struct file_operations mon_fops_text; - extern struct file_operations mon_fops_stat; ---- gregkh-2.6.orig/drivers/usb/storage/scsiglue.c -+++ gregkh-2.6/drivers/usb/storage/scsiglue.c -@@ -47,6 +47,7 @@ - - #include <linux/slab.h> - #include <linux/module.h> -+#include <linux/mutex.h> - - #include <scsi/scsi.h> - #include <scsi/scsi_cmnd.h> -@@ -271,9 +272,9 @@ static int device_reset(struct scsi_cmnd - US_DEBUGP("%s called\n", __FUNCTION__); - - /* lock the device pointers and do the reset */ -- down(&(us->dev_semaphore)); -+ mutex_lock(&(us->dev_mutex)); - result = us->transport_reset(us); -- up(&(us->dev_semaphore)); -+ mutex_unlock(&us->dev_mutex); - - return result < 0 ? FAILED : SUCCESS; - } -@@ -286,9 +287,9 @@ static int bus_reset(struct scsi_cmnd *s - - US_DEBUGP("%s called\n", __FUNCTION__); - -- down(&(us->dev_semaphore)); -+ mutex_lock(&(us->dev_mutex)); - result = usb_stor_port_reset(us); -- up(&(us->dev_semaphore)); -+ mutex_unlock(&us->dev_mutex); - - return result < 0 ? FAILED : SUCCESS; - } ---- gregkh-2.6.orig/drivers/usb/storage/usb.c -+++ gregkh-2.6/drivers/usb/storage/usb.c -@@ -55,6 +55,7 @@ - #include <linux/init.h> - #include <linux/slab.h> - #include <linux/kthread.h> -+#include <linux/mutex.h> - - #include <scsi/scsi.h> - #include <scsi/scsi_cmnd.h> -@@ -188,7 +189,7 @@ static int storage_suspend(struct usb_in - struct us_data *us = usb_get_intfdata(iface); - - /* Wait until no command is running */ -- down(&us->dev_semaphore); -+ mutex_lock(&us->dev_mutex); - - US_DEBUGP("%s\n", __FUNCTION__); - if (us->suspend_resume_hook) -@@ -198,7 +199,7 @@ static int storage_suspend(struct usb_in - /* When runtime PM is working, we'll set a flag to indicate - * whether we should autoresume when a SCSI request arrives. */ - -- up(&us->dev_semaphore); -+ mutex_unlock(&us->dev_mutex); - return 0; - } - -@@ -206,14 +207,14 @@ static int storage_resume(struct usb_int - { - struct us_data *us = usb_get_intfdata(iface); - -- down(&us->dev_semaphore); -+ mutex_lock(&us->dev_mutex); - - US_DEBUGP("%s\n", __FUNCTION__); - if (us->suspend_resume_hook) - (us->suspend_resume_hook)(us, US_RESUME); - iface->dev.power.power_state.event = PM_EVENT_ON; - -- up(&us->dev_semaphore); -+ mutex_unlock(&us->dev_mutex); - return 0; - } - -@@ -276,12 +277,12 @@ static int usb_stor_control_thread(void - US_DEBUGP("*** thread awakened.\n"); - - /* lock the device pointers */ -- down(&(us->dev_semaphore)); -+ mutex_lock(&(us->dev_mutex)); - - /* if the device has disconnected, we are free to exit */ - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - US_DEBUGP("-- exiting\n"); -- up(&(us->dev_semaphore)); -+ mutex_unlock(&us->dev_mutex); - break; - } - -@@ -370,7 +371,7 @@ SkipForAbort: - scsi_unlock(host); - - /* unlock the device pointers */ -- up(&(us->dev_semaphore)); -+ mutex_unlock(&us->dev_mutex); - } /* for (;;) */ - - scsi_host_put(host); -@@ -815,8 +816,8 @@ static void quiesce_and_remove_host(stru - * The thread will exit when it sees the DISCONNECTING flag. */ - - /* Wait for the current command to finish, then remove the host */ -- down(&us->dev_semaphore); -- up(&us->dev_semaphore); -+ mutex_lock(&us->dev_mutex); -+ mutex_unlock(&us->dev_mutex); - - /* queuecommand won't accept any new commands and the control - * thread won't execute a previously-queued command. If there -@@ -870,9 +871,9 @@ retry: - /* For bulk-only devices, determine the max LUN value */ - if (us->protocol == US_PR_BULK && - !(us->flags & US_FL_SINGLE_LUN)) { -- down(&us->dev_semaphore); -+ mutex_lock(&us->dev_mutex); - us->max_lun = usb_stor_Bulk_max_lun(us); -- up(&us->dev_semaphore); -+ mutex_unlock(&us->dev_mutex); - } - scsi_scan_host(us_to_host(us)); - printk(KERN_DEBUG "usb-storage: device scan complete\n"); -@@ -912,7 +913,7 @@ static int storage_probe(struct usb_inte - - us = host_to_us(host); - memset(us, 0, sizeof(struct us_data)); -- init_MUTEX(&(us->dev_semaphore)); -+ mutex_init(&(us->dev_mutex)); - init_MUTEX_LOCKED(&(us->sema)); - init_completion(&(us->notify)); - init_waitqueue_head(&us->delay_wait); ---- gregkh-2.6.orig/drivers/usb/storage/usb.h -+++ gregkh-2.6/drivers/usb/storage/usb.h -@@ -49,6 +49,7 @@ - #include <linux/blkdev.h> - #include <linux/smp_lock.h> - #include <linux/completion.h> -+#include <linux/mutex.h> - #include <scsi/scsi_host.h> - - struct us_data; -@@ -103,9 +104,9 @@ typedef void (*pm_hook)(struct us_data * - struct us_data { - /* The device we're working with - * It's important to note: -- * (o) you must hold dev_semaphore to change pusb_dev -+ * (o) you must hold dev_mutex to change pusb_dev - */ -- struct semaphore dev_semaphore; /* protect pusb_dev */ -+ struct mutex dev_mutex; /* protect pusb_dev */ - struct usb_device *pusb_dev; /* this usb_device */ - struct usb_interface *pusb_intf; /* this interface */ - struct us_unusual_dev *unusual_dev; /* device-filter entry */ diff --git a/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch b/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch deleted file mode 100644 index fb56e59c9d5eb..0000000000000 --- a/usb/usb-core-and-hcds-don-t-put_device-while-atomic.patch +++ /dev/null @@ -1,160 +0,0 @@ -From stern@rowland.harvard.edu Thu Jan 19 07:46:36 2006 -Date: Thu, 19 Jan 2006 10:46:27 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -cc: David Brownell <david-b@pacbell.net>, Olav Kongas <ok@artecdesign.ee> -Subject: [PATCH] USB core and HCDs: don't put_device while atomic -Message-ID: <Pine.LNX.4.44L0.0601191036380.4622-100000@iolanthe.rowland.org> - -This patch (as640) removes several put_device and the corresponding -get_device calls from the USB core and HCDs. Some of the puts were done -in atomic contexts, and none of them are needed since the core now -guarantees that every endpoint will be disabled and every URB completed -before a USB device is released. - - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Acked-by: David Brownell <david-b@pacbell.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/hcd.c | 2 -- - drivers/usb/host/ehci-mem.c | 1 - - drivers/usb/host/ehci-q.c | 2 +- - drivers/usb/host/ehci-sched.c | 6 ++---- - drivers/usb/host/isp116x-hcd.c | 3 +-- - drivers/usb/host/sl811-hcd.c | 3 +-- - drivers/usb/host/uhci-q.c | 2 -- - 7 files changed, 5 insertions(+), 14 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/hcd.c -+++ gregkh-2.6/drivers/usb/core/hcd.c -@@ -1105,7 +1105,6 @@ static void urb_unlink (struct urb *urb) - spin_lock_irqsave (&hcd_data_lock, flags); - list_del_init (&urb->urb_list); - spin_unlock_irqrestore (&hcd_data_lock, flags); -- usb_put_dev (urb->dev); - } - - -@@ -1145,7 +1144,6 @@ static int hcd_submit_urb (struct urb *u - case HC_STATE_RUNNING: - case HC_STATE_RESUMING: - doit: -- usb_get_dev (urb->dev); - list_add_tail (&urb->urb_list, &ep->urb_list); - status = 0; - break; ---- gregkh-2.6.orig/drivers/usb/host/ehci-mem.c -+++ gregkh-2.6/drivers/usb/host/ehci-mem.c -@@ -75,7 +75,6 @@ static void qh_destroy (struct kref *kre - } - if (qh->dummy) - ehci_qtd_free (ehci, qh->dummy); -- usb_put_dev (qh->dev); - dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); - } - ---- gregkh-2.6.orig/drivers/usb/host/ehci-q.c -+++ gregkh-2.6/drivers/usb/host/ehci-q.c -@@ -702,7 +702,7 @@ qh_make ( - } - - /* support for tt scheduling, and access to toggles */ -- qh->dev = usb_get_dev (urb->dev); -+ qh->dev = urb->dev; - - /* using TT? */ - switch (urb->dev->speed) { ---- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c -+++ gregkh-2.6/drivers/usb/host/ehci-sched.c -@@ -1399,7 +1399,7 @@ itd_complete ( - */ - - /* give urb back to the driver ... can be out-of-order */ -- dev = usb_get_dev (urb->dev); -+ dev = urb->dev; - ehci_urb_done (ehci, urb, regs); - urb = NULL; - -@@ -1418,7 +1418,6 @@ itd_complete ( - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); - } - iso_stream_put (ehci, stream); -- usb_put_dev (dev); - - return 1; - } -@@ -1765,7 +1764,7 @@ sitd_complete ( - */ - - /* give urb back to the driver */ -- dev = usb_get_dev (urb->dev); -+ dev = urb->dev; - ehci_urb_done (ehci, urb, regs); - urb = NULL; - -@@ -1784,7 +1783,6 @@ sitd_complete ( - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); - } - iso_stream_put (ehci, stream); -- usb_put_dev (dev); - - return 1; - } ---- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c -+++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c -@@ -724,7 +724,7 @@ static int isp116x_urb_enqueue(struct us - ep = hep->hcpriv; - else { - INIT_LIST_HEAD(&ep->schedule); -- ep->udev = usb_get_dev(udev); -+ ep->udev = udev; - ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); - usb_settoggle(udev, epnum, is_out, 0); -@@ -891,7 +891,6 @@ static void isp116x_endpoint_disable(str - if (!list_empty(&hep->urb_list)) - WARN("ep %p not empty?\n", ep); - -- usb_put_dev(ep->udev); - kfree(ep); - hep->hcpriv = NULL; - } ---- gregkh-2.6.orig/drivers/usb/host/sl811-hcd.c -+++ gregkh-2.6/drivers/usb/host/sl811-hcd.c -@@ -853,7 +853,7 @@ static int sl811h_urb_enqueue( - - } else { - INIT_LIST_HEAD(&ep->schedule); -- ep->udev = usb_get_dev(udev); -+ ep->udev = udev; - ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); - ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE; -@@ -1052,7 +1052,6 @@ sl811h_endpoint_disable(struct usb_hcd * - if (!list_empty(&hep->urb_list)) - WARN("ep %p not empty?\n", ep); - -- usb_put_dev(ep->udev); - kfree(ep); - hep->hcpriv = NULL; - } ---- gregkh-2.6.orig/drivers/usb/host/uhci-q.c -+++ gregkh-2.6/drivers/usb/host/uhci-q.c -@@ -179,7 +179,6 @@ static struct uhci_qh *uhci_alloc_qh(str - qh->hep = hep; - qh->udev = udev; - hep->hcpriv = qh; -- usb_get_dev(udev); - - } else { /* Skeleton QH */ - qh->state = QH_STATE_ACTIVE; -@@ -197,7 +196,6 @@ static void uhci_free_qh(struct uhci_hcd - list_del(&qh->node); - if (qh->udev) { - qh->hep->hcpriv = NULL; -- usb_put_dev(qh->udev); - uhci_free_td(uhci, qh->dummy_td); - } - dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); diff --git a/usb/usb-cp2101-add-new-device-ids.patch b/usb/usb-cp2101-add-new-device-ids.patch deleted file mode 100644 index e7dbd888bffbc..0000000000000 --- a/usb/usb-cp2101-add-new-device-ids.patch +++ /dev/null @@ -1,37 +0,0 @@ -From craig@microtron.org.uk Sat Mar 11 03:26:16 2006 -From: Craig Shelley <craig@microtron.org.uk> -Subject: USB: cp2101: add new device IDs -To: linux-usb-devel@lists.sourceforge.net -Cc: Greg KH <greg@kroah.com> -Date: Sat, 11 Mar 2006 11:29:02 +0000 -Message-Id: <1142076542.19343.30.camel@teratron.lan.etheus.net> - -This patch adds a new device ID to the cp2101 driver - -Signed-off-by: Craig Shelley <craig@microtron.org.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/usb/serial/cp2101.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/serial/cp2101.c -+++ gregkh-2.6/drivers/usb/serial/cp2101.c -@@ -32,7 +32,7 @@ - /* - * Version Information - */ --#define DRIVER_VERSION "v0.06" -+#define DRIVER_VERSION "v0.07" - #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" - - /* -@@ -58,6 +58,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, 0x803B) }, /* Pololu USB-serial converter */ - { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ - { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ - { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ diff --git a/usb/usb-credits-add-credits-about-the-zc0301-and-et61x51-usb-drivers.patch b/usb/usb-credits-add-credits-about-the-zc0301-and-et61x51-usb-drivers.patch deleted file mode 100644 index 44a149c6b1d66..0000000000000 --- a/usb/usb-credits-add-credits-about-the-zc0301-and-et61x51-usb-drivers.patch +++ /dev/null @@ -1,29 +0,0 @@ -From luca.risolia@studio.unibo.it Tue Feb 7 15:49:05 2006 -Date: Wed, 8 Feb 2006 00:50:59 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: CREDITS: Add credits about the ZC0301 and ET61X[12]51 USB drivers -Message-ID: <20060208005059.GA10459@studio.unibo.it> -Content-Disposition: inline - -This patch adds credits about the ZC0301 and ET61X[12]51 USB drivers -which have been included in the mainline kernel recently. - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - CREDITS | 2 ++ - 1 file changed, 2 insertions(+) - ---- gregkh-2.6.orig/CREDITS -+++ gregkh-2.6/CREDITS -@@ -2814,6 +2814,8 @@ E: luca.risolia@studio.unibo.it - P: 1024D/FCE635A4 88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4 - D: V4L driver for W996[87]CF JPEG USB Dual Mode Camera Chips - D: V4L2 driver for SN9C10x PC Camera Controllers -+D: V4L2 driver for ET61X151 and ET61X251 PC Camera Controllers -+D: V4L2 driver for ZC0301 Image Processor and Control Chip - S: Via Liberta' 41/A - S: Osio Sotto, 24046, Bergamo - S: Italy diff --git a/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch b/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch deleted file mode 100644 index 22986520f932f..0000000000000 --- a/usb/usb-drivers-usb-core-message.c-make-usb_get_string-static.patch +++ /dev/null @@ -1,52 +0,0 @@ -From bunk@stusta.de Tue Nov 8 13:17:46 2005 -Date: Tue, 8 Nov 2005 21:05:43 +0100 -From: Adrian Bunk <bunk@stusta.de> -To: Greg KH <gregkh@suse.de> -Subject: USB: drivers/usb/core/message.c: make usb_get_string() static -Message-ID: <20051108200543.GF3847@stusta.de> -Content-Disposition: inline - -After the removal of usb-midi.c, there's no longer any external user of -usb_get_string(). - - -Signed-off-by: Adrian Bunk <bunk@stusta.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/message.c | 5 ++--- - include/linux/usb.h | 2 -- - 2 files changed, 2 insertions(+), 5 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/message.c -+++ gregkh-2.6/drivers/usb/core/message.c -@@ -631,8 +631,8 @@ int usb_get_descriptor(struct usb_device - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ --int usb_get_string(struct usb_device *dev, unsigned short langid, -- unsigned char index, void *buf, int size) -+static int usb_get_string(struct usb_device *dev, unsigned short langid, -+ unsigned char index, void *buf, int size) - { - int i; - int result; -@@ -1488,7 +1488,6 @@ EXPORT_SYMBOL(usb_sg_wait); - // synchronous control message convenience routines - EXPORT_SYMBOL(usb_get_descriptor); - EXPORT_SYMBOL(usb_get_status); --EXPORT_SYMBOL(usb_get_string); - EXPORT_SYMBOL(usb_string); - - // synchronous calls that also maintain usbcore state ---- gregkh-2.6.orig/include/linux/usb.h -+++ gregkh-2.6/include/linux/usb.h -@@ -1018,8 +1018,6 @@ extern int usb_get_descriptor(struct usb - unsigned char descindex, void *buf, int size); - extern int usb_get_status(struct usb_device *dev, - int type, int target, void *data); --extern int usb_get_string(struct usb_device *dev, -- unsigned short langid, unsigned char index, void *buf, int size); - extern int usb_string(struct usb_device *dev, int index, - char *buf, size_t size); - diff --git a/usb/usb-ehci-and-freescale-83xx-quirk.patch b/usb/usb-ehci-and-freescale-83xx-quirk.patch deleted file mode 100644 index dcd4bf5cd741d..0000000000000 --- a/usb/usb-ehci-and-freescale-83xx-quirk.patch +++ /dev/null @@ -1,94 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: EHCI and Freescale 83xx quirk -Date: Fri, 20 Jan 2006 13:57:52 -0800 -Message-Id: <200601201357.52344.david-b@pacbell.net> - -From: Kumar Gala <galak@gate.crashing.org> - -On the MPC834x processors the multiport host (MPH) EHCI controller has an -erratum in which the port number in the queue head expects to be 0..N-1 -instead of 1..N. If we are on one of these chips we subtract one from -the port number before putting it into the queue head. - -Signed-off-by: Kumar Gala <galak@kernel.crashing.org> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-fsl.c | 10 ++++++++++ - drivers/usb/host/ehci-q.c | 9 ++++++++- - drivers/usb/host/ehci.h | 15 +++++++++++++++ - 3 files changed, 33 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-fsl.c -+++ gregkh-2.6/drivers/usb/host/ehci-fsl.c -@@ -198,6 +198,16 @@ static void mpc83xx_usb_setup(struct usb - mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); - - if (pdata->operating_mode == FSL_USB2_MPH_HOST) { -+ unsigned int chip, rev, svr; -+ -+ svr = mfspr(SPRN_SVR); -+ chip = svr >> 16; -+ rev = (svr >> 4) & 0xf; -+ -+ /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ -+ if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055)) -+ ehci->has_fsl_port_bug = 1; -+ - if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); - if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) ---- gregkh-2.6.orig/drivers/usb/host/ehci-q.c -+++ gregkh-2.6/drivers/usb/host/ehci-q.c -@@ -721,7 +721,14 @@ qh_make ( - info1 |= maxp << 16; - - info2 |= (EHCI_TUNE_MULT_TT << 30); -- info2 |= urb->dev->ttport << 23; -+ -+ /* Some Freescale processors have an erratum in which the -+ * port number in the queue head was 0..N-1 instead of 1..N. -+ */ -+ if (ehci_has_fsl_portno_bug(ehci)) -+ info2 |= (urb->dev->ttport-1) << 23; -+ else -+ info2 |= urb->dev->ttport << 23; - - /* set the address of the TT; for TDI's integrated - * root hub tt, leave it zeroed. ---- gregkh-2.6.orig/drivers/usb/host/ehci.h -+++ gregkh-2.6/drivers/usb/host/ehci.h -@@ -88,8 +88,11 @@ struct ehci_hcd { /* one per controlle - unsigned long next_statechange; - u32 command; - -+ /* SILICON QUIRKS */ - unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ - unsigned no_selective_suspend:1; -+ unsigned has_fsl_port_bug:1; /* FreeScale */ -+ - u8 sbrn; /* packed release number */ - - /* irq statistics */ -@@ -639,6 +642,18 @@ ehci_port_speed(struct ehci_hcd *ehci, u - - /*-------------------------------------------------------------------------*/ - -+#ifdef CONFIG_PPC_83xx -+/* Some Freescale processors have an erratum in which the TT -+ * port number in the queue head was 0..N-1 instead of 1..N. -+ */ -+#define ehci_has_fsl_portno_bug(e) ((e)->has_fsl_port_bug) -+#else -+#define ehci_has_fsl_portno_bug(e) (0) -+#endif -+ -+ -+/*-------------------------------------------------------------------------*/ -+ - #ifndef DEBUG - #define STUB_DEBUG_FILES - #endif /* DEBUG */ diff --git a/usb/usb-ehci-and-nf2-quirk.patch b/usb/usb-ehci-and-nf2-quirk.patch deleted file mode 100644 index 3305ef7a7e64d..0000000000000 --- a/usb/usb-ehci-and-nf2-quirk.patch +++ /dev/null @@ -1,120 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: David Brownell <david-b@pacbell.net> -Subject: USB: EHCI and NF2 quirk -To: Greg KH <greg@kroah.com> -Date: Fri, 20 Jan 2006 13:55:14 -0800 -Message-Id: <200601201355.14378.david-b@pacbell.net> - -This teaches the EHCI driver about a quirk seen in older NForce2 chips, -adding a workaround to ignore selective suspend requests. Bus-wide -(so-called "global") suspend still works, as does USB wakeup of a -root hub that's globally suspended. - -There's still a hole in this support though. Strictly speaking, this -should _fail_ selective suspend requests, rather than ignoring them, -since doing it this way means that devices which should be able to issue -remote wakeup are not going to be able to do that. For now, we'll just -live with that problem ... since usbcore expects to do selective suspend -on the way towards a full bus suspend, and usbcore needs to be able to -do full bus suspend. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-hub.c | 4 ++++ - drivers/usb/host/ehci-pci.c | 25 ++++++++++++++++++++++++- - drivers/usb/host/ehci.h | 3 ++- - 3 files changed, 30 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-hub.c -+++ gregkh-2.6/drivers/usb/host/ehci-hub.c -@@ -359,6 +359,8 @@ static int ehci_hub_control ( - case USB_PORT_FEAT_SUSPEND: - if (temp & PORT_RESET) - goto error; -+ if (ehci->no_selective_suspend) -+ break; - if (temp & PORT_SUSPEND) { - if ((temp & PORT_PE) == 0) - goto error; -@@ -514,6 +516,8 @@ static int ehci_hub_control ( - temp &= ~PORT_RWC_BITS; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: -+ if (ehci->no_selective_suspend) -+ break; - if ((temp & PORT_PE) == 0 - || (temp & PORT_RESET) != 0) - goto error; ---- gregkh-2.6.orig/drivers/usb/host/ehci-pci.c -+++ gregkh-2.6/drivers/usb/host/ehci-pci.c -@@ -106,11 +106,11 @@ static int ehci_pci_setup(struct usb_hcd - } - break; - case PCI_VENDOR_ID_NVIDIA: -+ switch (pdev->device) { - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ -- switch (pdev->device) { - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ -@@ -120,6 +120,14 @@ static int ehci_pci_setup(struct usb_hcd - ehci_warn(ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; -+ /* Some NForce2 chips have problems with selective suspend; -+ * fixed in newer silicon. -+ */ -+ case 0x0068: -+ pci_read_config_dword(pdev, PCI_REVISION_ID, &temp); -+ if ((temp & 0xff) < 0xa4) -+ ehci->no_selective_suspend = 1; -+ break; - } - break; - } -@@ -163,6 +171,21 @@ static int ehci_pci_setup(struct usb_hcd - device_init_wakeup(&pdev->dev, 1); - } - -+#ifdef CONFIG_USB_SUSPEND -+ /* REVISIT: the controller works fine for wakeup iff the root hub -+ * itself is "globally" suspended, but usbcore currently doesn't -+ * understand such things. -+ * -+ * System suspend currently expects to be able to suspend the entire -+ * device tree, device-at-a-time. If we failed selective suspend -+ * reports, system suspend would fail; so the root hub code must claim -+ * success. That's lying to usbcore, and it matters for for runtime -+ * PM scenarios with selective suspend and remote wakeup... -+ */ -+ if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) -+ ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); -+#endif -+ - retval = ehci_pci_reinit(ehci, pdev); - done: - return retval; ---- gregkh-2.6.orig/drivers/usb/host/ehci.h -+++ gregkh-2.6/drivers/usb/host/ehci.h -@@ -89,6 +89,8 @@ struct ehci_hcd { /* one per controlle - u32 command; - - unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ -+ unsigned no_selective_suspend:1; -+ u8 sbrn; /* packed release number */ - - /* irq statistics */ - #ifdef EHCI_STATS -@@ -97,7 +99,6 @@ struct ehci_hcd { /* one per controlle - #else - # define COUNT(x) do {} while (0) - #endif -- u8 sbrn; /* packed release number */ - }; - - /* convert between an HCD pointer and the corresponding EHCI_HCD */ diff --git a/usb/usb-ehci-for-au1200.patch b/usb/usb-ehci-for-au1200.patch deleted file mode 100644 index 7ab53dc8f9d12..0000000000000 --- a/usb/usb-ehci-for-au1200.patch +++ /dev/null @@ -1,425 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: Jordan Crouse <jordan.crouse@amd.com> -To: Greg KH <greg@kroah.com> -Subject: USB: EHCI for AU1200 -Date: Fri, 20 Jan 2006 14:06:09 -0800 -Message-Id: <200601201406.10265.david-b@pacbell.net> - - -ALCHEMY: Add EHCI support for AU1200 - -Updated by removing the OHCI support - -Signed-off-by: Jordan Crouse <jordan.crouse@amd.com> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - arch/mips/au1000/common/cputable.c | 2 - arch/mips/au1000/common/platform.c | 2 - drivers/usb/Kconfig | 9 - drivers/usb/host/Kconfig | 2 - drivers/usb/host/ehci-au1xxx.c | 297 +++++++++++++++++++++ - drivers/usb/host/ehci-hcd.c | 11 - include/asm-mips/mach-mips/cpu-feature-overrides.h | 4 - 7 files changed, 319 insertions(+), 8 deletions(-) - ---- gregkh-2.6.orig/arch/mips/au1000/common/cputable.c -+++ gregkh-2.6/arch/mips/au1000/common/cputable.c -@@ -38,7 +38,7 @@ struct cpu_spec cpu_specs[] = { - { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1 }, - { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1 }, - { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0 }, -- { 0xffffffff, 0x04030201, "Au1200 AC", 0, 1 }, -+ { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0 }, - { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0 }, - }; - ---- gregkh-2.6.orig/arch/mips/au1000/common/platform.c -+++ gregkh-2.6/arch/mips/au1000/common/platform.c -@@ -278,9 +278,7 @@ static struct platform_device *au1xxx_pl - &au1100_lcd_device, - #endif - #ifdef CONFIG_SOC_AU1200 --#if 0 /* fixme */ - &au1xxx_usb_ehci_device, --#endif - &au1xxx_usb_gdt_device, - &au1xxx_usb_otg_device, - &au1200_lcd_device, ---- gregkh-2.6.orig/drivers/usb/Kconfig -+++ gregkh-2.6/drivers/usb/Kconfig -@@ -10,8 +10,8 @@ menu "USB support" - config USB_ARCH_HAS_HCD - boolean - default y if USB_ARCH_HAS_OHCI -+ default y if USB_ARCH_HAS_EHCI - default y if ARM # SL-811 -- default y if PPC_83xx - default PCI - - # many non-PCI SOC chips embed OHCI -@@ -31,6 +31,13 @@ config USB_ARCH_HAS_OHCI - # more: - default PCI - -+# some non-PCI hcds implement EHCI -+config USB_ARCH_HAS_EHCI -+ boolean -+ default y if PPC_83xx -+ default y if SOC_AU1200 -+ default PCI -+ - # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. - config USB - tristate "Support for Host-side USB" ---- gregkh-2.6.orig/drivers/usb/host/Kconfig -+++ gregkh-2.6/drivers/usb/host/Kconfig -@@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" - - config USB_EHCI_HCD - tristate "EHCI HCD (USB 2.0) support" -- depends on USB && (PCI || PPC_83xx) -+ depends on USB && USB_ARCH_HAS_EHCI - ---help--- - The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 - "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. ---- /dev/null -+++ gregkh-2.6/drivers/usb/host/ehci-au1xxx.c -@@ -0,0 +1,297 @@ -+/* -+ * EHCI HCD (Host Controller Driver) for USB. -+ * -+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> -+ * -+ * Bus Glue for AMD Alchemy Au1xxx -+ * -+ * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org> -+ * -+ * Modified for AMD Alchemy Au1200 EHC -+ * by K.Boge <karsten.boge@amd.com> -+ * -+ * This file is licenced under the GPL. -+ */ -+ -+#include <linux/platform_device.h> -+#include <asm/mach-au1x00/au1000.h> -+ -+#ifndef CONFIG_SOC_AU1200 -+#error "this Alchemy chip doesn't have EHCI" -+#else /* Au1200 */ -+ -+#define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) -+#define USB_MCFG_PFEN (1<<31) -+#define USB_MCFG_RDCOMB (1<<30) -+#define USB_MCFG_SSDEN (1<<23) -+#define USB_MCFG_PHYPLLEN (1<<19) -+#define USB_MCFG_EHCCLKEN (1<<17) -+#define USB_MCFG_UCAM (1<<7) -+#define USB_MCFG_EBMEN (1<<3) -+#define USB_MCFG_EMEMEN (1<<2) -+ -+#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) -+ -+#ifdef CONFIG_DMA_COHERENT -+#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ -+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ -+ | USB_MCFG_SSDEN | USB_MCFG_UCAM \ -+ | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) -+#else -+#define USBH_ENABLE_INIT (USBH_ENABLE_CE \ -+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ -+ | USB_MCFG_SSDEN \ -+ | USB_MCFG_EBMEN | USB_MCFG_EMEMEN) -+#endif -+#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) -+ -+#endif /* Au1200 */ -+ -+extern int usb_disabled(void); -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void au1xxx_start_ehc(struct platform_device *dev) -+{ -+ pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n"); -+ -+ /* write HW defaults again in case Yamon cleared them */ -+ if (au_readl(USB_HOST_CONFIG) == 0) { -+ au_writel(0x00d02000, USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ } -+ /* enable host controller */ -+ au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), -+ USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ -+ pr_debug(__FILE__ ": Clock to USB host has been enabled\n"); -+} -+ -+static void au1xxx_stop_ehc(struct platform_device *dev) -+{ -+ pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n"); -+ -+ /* Disable mem */ -+ au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ udelay(1000); -+ /* Disable clock */ -+ au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG), -+ USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* configure so an HC device and id are always provided */ -+/* always called with process context; sleeping is OK */ -+ -+/** -+ * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs -+ * Context: !in_interrupt() -+ * -+ * Allocates basic resources for this USB host controller, and -+ * then invokes the start() method for the HCD associated with it -+ * through the hotplug entry's driver_data. -+ * -+ */ -+int usb_ehci_au1xxx_probe(const struct hc_driver *driver, -+ struct usb_hcd **hcd_out, struct platform_device *dev) -+{ -+ int retval; -+ struct usb_hcd *hcd; -+ struct ehci_hcd *ehci; -+ -+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) -+ -+ /* Au1200 AB USB does not support coherent memory */ -+ if (!(read_c0_prid() & 0xff)) { -+ pr_info("%s: this is chip revision AB!\n", dev->dev.name); -+ pr_info("%s: update your board or re-configure the kernel\n", -+ dev->dev.name); -+ return -ENODEV; -+ } -+#endif -+ -+ au1xxx_start_ehc(dev); -+ -+ if (dev->resource[1].flags != IORESOURCE_IRQ) { -+ pr_debug("resource[1] is not IORESOURCE_IRQ"); -+ retval = -ENOMEM; -+ } -+ hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx"); -+ if (!hcd) -+ return -ENOMEM; -+ hcd->rsrc_start = dev->resource[0].start; -+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; -+ -+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -+ pr_debug("request_mem_region failed"); -+ retval = -EBUSY; -+ goto err1; -+ } -+ -+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -+ if (!hcd->regs) { -+ pr_debug("ioremap failed"); -+ retval = -ENOMEM; -+ goto err2; -+ } -+ -+ ehci = hcd_to_ehci(hcd); -+ ehci->caps = hcd->regs; -+ ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); -+ /* cache this readonly data; minimize chip reads */ -+ ehci->hcs_params = readl(&ehci->caps->hcs_params); -+ -+ /* ehci_hcd_init(hcd_to_ehci(hcd)); */ -+ -+ retval = -+ usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); -+ if (retval == 0) -+ return retval; -+ -+ au1xxx_stop_ehc(dev); -+ iounmap(hcd->regs); -+err2: -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+err1: -+ usb_put_hcd(hcd); -+ return retval; -+} -+ -+/* may be called without controller electrically present */ -+/* may be called with controller, bus, and devices active */ -+ -+/** -+ * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs -+ * @dev: USB Host Controller being removed -+ * Context: !in_interrupt() -+ * -+ * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking -+ * the HCD's stop() method. It is always called from a thread -+ * context, normally "rmmod", "apmd", or something similar. -+ * -+ */ -+void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) -+{ -+ usb_remove_hcd(hcd); -+ iounmap(hcd->regs); -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ usb_put_hcd(hcd); -+ au1xxx_stop_ehc(dev); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static const struct hc_driver ehci_au1xxx_hc_driver = { -+ .description = hcd_name, -+ .product_desc = "Au1xxx EHCI", -+ .hcd_priv_size = sizeof(struct ehci_hcd), -+ -+ /* -+ * generic hardware linkage -+ */ -+ .irq = ehci_irq, -+ .flags = HCD_MEMORY | HCD_USB2, -+ -+ /* -+ * basic lifecycle operations -+ */ -+ .reset = ehci_init, -+ .start = ehci_run, -+ .stop = ehci_stop, -+ -+ /* -+ * 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 -+ .hub_suspend = ehci_hub_suspend, -+ .hub_resume = ehci_hub_resume, -+#endif -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int ehci_hcd_au1xxx_drv_probe(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct usb_hcd *hcd = NULL; -+ int ret; -+ -+ pr_debug("In ehci_hcd_au1xxx_drv_probe\n"); -+ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev); -+ return ret; -+} -+ -+static int ehci_hcd_au1xxx_drv_remove(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ -+ usb_ehci_au1xxx_remove(hcd, pdev); -+ return 0; -+} -+ -+ /*TBD*/ -+/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ -+ return 0; -+} -+static int ehci_hcd_au1xxx_drv_resume(struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct usb_hcd *hcd = dev_get_drvdata(dev); -+ -+ return 0; -+} -+*/ -+static struct device_driver ehci_hcd_au1xxx_driver = { -+ .name = "au1xxx-ehci", -+ .bus = &platform_bus_type, -+ .probe = ehci_hcd_au1xxx_drv_probe, -+ .remove = ehci_hcd_au1xxx_drv_remove, -+ /*.suspend = ehci_hcd_au1xxx_drv_suspend, */ -+ /*.resume = ehci_hcd_au1xxx_drv_resume, */ -+}; -+ -+static int __init ehci_hcd_au1xxx_init(void) -+{ -+ pr_debug(DRIVER_INFO " (Au1xxx)\n"); -+ -+ return driver_register(&ehci_hcd_au1xxx_driver); -+} -+ -+static void __exit ehci_hcd_au1xxx_cleanup(void) -+{ -+ driver_unregister(&ehci_hcd_au1xxx_driver); -+} -+ -+module_init(ehci_hcd_au1xxx_init); -+module_exit(ehci_hcd_au1xxx_cleanup); ---- gregkh-2.6.orig/drivers/usb/host/ehci-hcd.c -+++ gregkh-2.6/drivers/usb/host/ehci-hcd.c -@@ -889,14 +889,19 @@ MODULE_LICENSE ("GPL"); - - #ifdef CONFIG_PCI - #include "ehci-pci.c" -+#define EHCI_BUS_GLUED - #endif - - #ifdef CONFIG_PPC_83xx - #include "ehci-fsl.c" -+#define EHCI_BUS_GLUED - #endif - --#if !(defined(CONFIG_PCI) || \ -- defined(CONFIG_PPC_83xx) \ -- ) -+#ifdef CONFIG_SOC_AU1X00 -+#include "ehci-au1xxx.c" -+#define EHCI_BUS_GLUED -+#endif -+ -+#ifndef EHCI_BUS_GLUED - #error "missing bus glue for ehci-hcd" - #endif ---- gregkh-2.6.orig/include/asm-mips/mach-mips/cpu-feature-overrides.h -+++ gregkh-2.6/include/asm-mips/mach-mips/cpu-feature-overrides.h -@@ -29,7 +29,11 @@ - /* #define cpu_has_prefetch ? */ - #define cpu_has_mcheck 1 - /* #define cpu_has_ejtag ? */ -+#ifdef CONFIG_CPU_HAS_LLSC - #define cpu_has_llsc 1 -+#else -+#define cpu_has_llsc 0 -+#endif - /* #define cpu_has_vtag_icache ? */ - /* #define cpu_has_dc_aliases ? */ - /* #define cpu_has_ic_fills_f_dc ? */ diff --git a/usb/usb-ehci-for-freescale-83xx.patch b/usb/usb-ehci-for-freescale-83xx.patch deleted file mode 100644 index 9d29889daa8df..0000000000000 --- a/usb/usb-ehci-for-freescale-83xx.patch +++ /dev/null @@ -1,503 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: EHCI for Freescale 83xx -Date: Fri, 20 Jan 2006 13:53:38 -0800 -Cc: linux-usb-devel@lists.sourceforge.net -Message-Id: <200601201353.38733.david-b@pacbell.net> - -From: Randy Vinson <rvinson@mvista.com> - -Adding a Host Mode USB driver for the Freescale 83xx. - -This driver supports both the Dual-Role (DR) controller and the -Multi-Port-Host (MPH) controller present in the Freescale MPC8349. It has -been tested with the MPC8349CDS reference system. This driver depends on -platform support code for setting up the pins on the device package in a -manner appropriate for the board in use. Note that this patch requires -selecting the EHCI controller option under the USB Host menu. - -Signed-off-by: Randy Vinson <rvinson@mvista.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/Kconfig | 1 - drivers/usb/host/Kconfig | 2 - drivers/usb/host/ehci-fsl.c | 357 ++++++++++++++++++++++++++++++++++++++++++++ - drivers/usb/host/ehci-fsl.h | 37 ++++ - drivers/usb/host/ehci-hcd.c | 8 - include/linux/fsl_devices.h | 27 +++ - 6 files changed, 430 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/Kconfig -+++ gregkh-2.6/drivers/usb/Kconfig -@@ -11,6 +11,7 @@ config USB_ARCH_HAS_HCD - boolean - default y if USB_ARCH_HAS_OHCI - default y if ARM # SL-811 -+ default y if PPC_83xx - default PCI - - # many non-PCI SOC chips embed OHCI ---- gregkh-2.6.orig/drivers/usb/host/Kconfig -+++ gregkh-2.6/drivers/usb/host/Kconfig -@@ -6,7 +6,7 @@ comment "USB Host Controller Drivers" - - config USB_EHCI_HCD - tristate "EHCI HCD (USB 2.0) support" -- depends on USB && PCI -+ depends on USB && (PCI || PPC_83xx) - ---help--- - The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 - "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. ---- /dev/null -+++ gregkh-2.6/drivers/usb/host/ehci-fsl.c -@@ -0,0 +1,357 @@ -+/* -+ * (C) Copyright David Brownell 2000-2002 -+ * Copyright (c) 2005 MontaVista Software -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided -+ * by Hunter Wu. -+ */ -+ -+#include <linux/platform_device.h> -+#include <linux/fsl_devices.h> -+ -+#include "ehci-fsl.h" -+ -+/* FIXME: Power Managment is un-ported so temporarily disable it */ -+#undef CONFIG_PM -+ -+/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ -+ -+/* configure so an HC device and id are always provided */ -+/* always called with process context; sleeping is OK */ -+ -+/** -+ * usb_hcd_fsl_probe - initialize FSL-based HCDs -+ * @drvier: Driver to be used for this HCD -+ * @pdev: USB Host Controller being probed -+ * Context: !in_interrupt() -+ * -+ * Allocates basic resources for this USB host controller. -+ * -+ */ -+int usb_hcd_fsl_probe(const struct hc_driver *driver, -+ struct platform_device *pdev) -+{ -+ struct fsl_usb2_platform_data *pdata; -+ struct usb_hcd *hcd; -+ struct resource *res; -+ int irq; -+ int retval; -+ unsigned int temp; -+ -+ pr_debug("initializing FSL-SOC USB Controller\n"); -+ -+ /* Need platform data for setup */ -+ pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; -+ if (!pdata) { -+ dev_err(&pdev->dev, -+ "No platform data for %s.\n", pdev->dev.bus_id); -+ return -ENODEV; -+ } -+ -+ /* -+ * This is a host mode driver, verify that we're supposed to be -+ * in host mode. -+ */ -+ if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || -+ (pdata->operating_mode == FSL_USB2_MPH_HOST))) { -+ dev_err(&pdev->dev, -+ "Non Host Mode configured for %s. Wrong driver linked.\n", -+ pdev->dev.bus_id); -+ 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 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); -+ retval = -ENODEV; -+ 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, -+ driver->description)) { -+ dev_dbg(&pdev->dev, "controller already in use\n"); -+ retval = -EBUSY; -+ goto err2; -+ } -+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); -+ -+ if (hcd->regs == NULL) { -+ dev_dbg(&pdev->dev, "error mapping memory\n"); -+ retval = -EFAULT; -+ goto err3; -+ } -+ -+ /* Enable USB controller */ -+ temp = in_be32(hcd->regs + 0x500); -+ out_be32(hcd->regs + 0x500, temp | 0x4); -+ -+ /* Set to Host mode */ -+ temp = in_le32(hcd->regs + 0x1a8); -+ out_le32(hcd->regs + 0x1a8, temp | 0x3); -+ -+ retval = usb_add_hcd(hcd, irq, SA_SHIRQ); -+ if (retval != 0) -+ goto err4; -+ return retval; -+ -+ err4: -+ iounmap(hcd->regs); -+ err3: -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ err2: -+ usb_put_hcd(hcd); -+ err1: -+ dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); -+ return retval; -+} -+ -+/* may be called without controller electrically present */ -+/* may be called with controller, bus, and devices active */ -+ -+/** -+ * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs -+ * @dev: USB Host Controller being removed -+ * Context: !in_interrupt() -+ * -+ * Reverses the effect of usb_hcd_fsl_probe(). -+ * -+ */ -+void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) -+{ -+ usb_remove_hcd(hcd); -+ iounmap(hcd->regs); -+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -+ usb_put_hcd(hcd); -+} -+ -+static void mpc83xx_setup_phy(struct ehci_hcd *ehci, -+ enum fsl_usb2_phy_modes phy_mode, -+ unsigned int port_offset) -+{ -+ u32 portsc = readl(&ehci->regs->port_status[port_offset]); -+ portsc &= ~PORT_PTS_MSK; -+ switch (phy_mode) { -+ case FSL_USB2_PHY_ULPI: -+ portsc |= PORT_PTS_ULPI; -+ break; -+ case FSL_USB2_PHY_SERIAL: -+ portsc |= PORT_PTS_SERIAL; -+ break; -+ case FSL_USB2_PHY_UTMI_WIDE: -+ portsc |= PORT_PTS_PTW; -+ /* fall through */ -+ case FSL_USB2_PHY_UTMI: -+ portsc |= PORT_PTS_UTMI; -+ break; -+ case FSL_USB2_PHY_NONE: -+ break; -+ } -+ writel(portsc, &ehci->regs->port_status[port_offset]); -+} -+ -+static void mpc83xx_usb_setup(struct usb_hcd *hcd) -+{ -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ struct fsl_usb2_platform_data *pdata; -+ void __iomem *non_ehci = hcd->regs; -+ -+ pdata = -+ (struct fsl_usb2_platform_data *)hcd->self.controller-> -+ platform_data; -+ /* Enable PHY interface in the control reg. */ -+ out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004); -+ out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); -+ -+ if (pdata->operating_mode == FSL_USB2_DR_HOST) -+ mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); -+ -+ if (pdata->operating_mode == FSL_USB2_MPH_HOST) { -+ if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) -+ mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); -+ if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) -+ mpc83xx_setup_phy(ehci, pdata->phy_mode, 1); -+ } -+ -+ /* put controller in host mode. */ -+ writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE); -+ out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); -+ out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); -+ out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); -+} -+ -+/* called after powerup, by probe or system-pm "wakeup" */ -+static int ehci_fsl_reinit(struct ehci_hcd *ehci) -+{ -+ mpc83xx_usb_setup(ehci_to_hcd(ehci)); -+ ehci_port_power(ehci, 0); -+ -+ return 0; -+} -+ -+/* called during probe() after chip reset completes */ -+static int ehci_fsl_setup(struct usb_hcd *hcd) -+{ -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ int retval; -+ -+ /* EHCI registers start at offset 0x100 */ -+ ehci->caps = hcd->regs + 0x100; -+ ehci->regs = hcd->regs + 0x100 + -+ HC_LENGTH(readl(&ehci->caps->hc_capbase)); -+ dbg_hcs_params(ehci, "reset"); -+ dbg_hcc_params(ehci, "reset"); -+ -+ /* cache this readonly data; minimize chip reads */ -+ ehci->hcs_params = readl(&ehci->caps->hcs_params); -+ -+ retval = ehci_halt(ehci); -+ if (retval) -+ return retval; -+ -+ /* data structure init */ -+ retval = ehci_init(hcd); -+ if (retval) -+ return retval; -+ -+ ehci->is_tdi_rh_tt = 1; -+ -+ ehci->sbrn = 0x20; -+ -+ ehci_reset(ehci); -+ -+ retval = ehci_fsl_reinit(ehci); -+ return retval; -+} -+ -+static const struct hc_driver ehci_fsl_hc_driver = { -+ .description = hcd_name, -+ .product_desc = "Freescale On-Chip EHCI Host Controller", -+ .hcd_priv_size = sizeof(struct ehci_hcd), -+ -+ /* -+ * generic hardware linkage -+ */ -+ .irq = ehci_irq, -+ .flags = HCD_USB2, -+ -+ /* -+ * basic lifecycle operations -+ */ -+ .reset = ehci_fsl_setup, -+ .start = ehci_run, -+#ifdef CONFIG_PM -+ .suspend = ehci_bus_suspend, -+ .resume = ehci_bus_resume, -+#endif -+ .stop = ehci_stop, -+ -+ /* -+ * 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 ehci_fsl_drv_probe(struct platform_device *pdev) -+{ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev); -+} -+ -+static int ehci_fsl_drv_remove(struct platform_device *pdev) -+{ -+ struct usb_hcd *hcd = platform_get_drvdata(pdev); -+ -+ usb_hcd_fsl_remove(hcd, pdev); -+ -+ return 0; -+} -+ -+static struct platform_driver ehci_fsl_dr_driver = { -+ .probe = ehci_fsl_drv_probe, -+ .remove = ehci_fsl_drv_remove, -+ .driver = { -+ .name = "fsl-usb2-dr", -+ }, -+}; -+ -+static struct platform_driver ehci_fsl_mph_driver = { -+ .probe = ehci_fsl_drv_probe, -+ .remove = ehci_fsl_drv_remove, -+ .driver = { -+ .name = "fsl-usb2-mph", -+ }, -+}; -+ -+static int __init ehci_fsl_init(void) -+{ -+ int retval; -+ -+ pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", -+ hcd_name, -+ sizeof(struct ehci_qh), sizeof(struct ehci_qtd), -+ sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); -+ -+ retval = platform_driver_register(&ehci_fsl_dr_driver); -+ if (retval) -+ return retval; -+ -+ return platform_driver_register(&ehci_fsl_mph_driver); -+} -+ -+static void __exit ehci_fsl_cleanup(void) -+{ -+ platform_driver_unregister(&ehci_fsl_mph_driver); -+ platform_driver_unregister(&ehci_fsl_dr_driver); -+} -+ -+module_init(ehci_fsl_init); -+module_exit(ehci_fsl_cleanup); ---- /dev/null -+++ gregkh-2.6/drivers/usb/host/ehci-fsl.h -@@ -0,0 +1,37 @@ -+/* Copyright (c) 2005 freescale semiconductor -+ * Copyright (c) 2005 MontaVista Software -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+#ifndef _EHCI_FSL_H -+#define _EHCI_FSL_H -+ -+/* offsets for the non-ehci registers in the FSL SOC USB controller */ -+#define FSL_SOC_USB_ULPIVP 0x170 -+#define FSL_SOC_USB_PORTSC1 0x184 -+#define PORT_PTS_MSK (3<<30) -+#define PORT_PTS_UTMI (0<<30) -+#define PORT_PTS_ULPI (2<<30) -+#define PORT_PTS_SERIAL (3<<30) -+#define PORT_PTS_PTW (1<<28) -+#define FSL_SOC_USB_PORTSC2 0x188 -+#define FSL_SOC_USB_USBMODE 0x1a8 -+#define FSL_SOC_USB_SNOOP1 0x400 /* NOTE: big-endian */ -+#define FSL_SOC_USB_SNOOP2 0x404 /* NOTE: big-endian */ -+#define FSL_SOC_USB_AGECNTTHRSH 0x408 /* NOTE: big-endian */ -+#define FSL_SOC_USB_SICTRL 0x40c /* NOTE: big-endian */ -+#define FSL_SOC_USB_PRICTRL 0x410 /* NOTE: big-endian */ -+#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ -+#endif /* _EHCI_FSL_H */ ---- gregkh-2.6.orig/drivers/usb/host/ehci-hcd.c -+++ gregkh-2.6/drivers/usb/host/ehci-hcd.c -@@ -891,6 +891,12 @@ MODULE_LICENSE ("GPL"); - #include "ehci-pci.c" - #endif - --#if !defined(CONFIG_PCI) -+#ifdef CONFIG_PPC_83xx -+#include "ehci-fsl.c" -+#endif -+ -+#if !(defined(CONFIG_PCI) || \ -+ defined(CONFIG_PPC_83xx) \ -+ ) - #error "missing bus glue for ehci-hcd" - #endif ---- gregkh-2.6.orig/include/linux/fsl_devices.h -+++ gregkh-2.6/include/linux/fsl_devices.h -@@ -83,5 +83,32 @@ struct fsl_i2c_platform_data { - #define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001 - #define FSL_I2C_DEV_CLOCK_5200 0x00000002 - -+ -+enum fsl_usb2_operating_modes { -+ FSL_USB2_MPH_HOST, -+ FSL_USB2_DR_HOST, -+ FSL_USB2_DR_DEVICE, -+ FSL_USB2_DR_OTG, -+}; -+ -+enum fsl_usb2_phy_modes { -+ FSL_USB2_PHY_NONE, -+ FSL_USB2_PHY_ULPI, -+ FSL_USB2_PHY_UTMI, -+ FSL_USB2_PHY_UTMI_WIDE, -+ FSL_USB2_PHY_SERIAL, -+}; -+ -+struct fsl_usb2_platform_data { -+ /* board specific information */ -+ enum fsl_usb2_operating_modes operating_mode; -+ enum fsl_usb2_phy_modes phy_mode; -+ unsigned int port_enables; -+}; -+ -+/* Flags in fsl_usb2_mph_platform_data */ -+#define FSL_USB2_PORT0_ENABLED 0x00000001 -+#define FSL_USB2_PORT1_ENABLED 0x00000002 -+ - #endif /* _FSL_DEVICE_H_ */ - #endif /* __KERNEL__ */ diff --git a/usb/usb-ehci-full-speed-iso-bugfixes.patch b/usb/usb-ehci-full-speed-iso-bugfixes.patch deleted file mode 100644 index 5c2091449a28e..0000000000000 --- a/usb/usb-ehci-full-speed-iso-bugfixes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:14 2006 -From: Clemens Ladisch <clemens@ladisch.de> -To: Greg KH <greg@kroah.com> -Subject: USB: EHCI full speed ISO bugfixes -Date: Fri, 20 Jan 2006 13:49:10 -0800 -Cc: <clemens@ladisch.de> -Message-Id: <200601201349.10841.david-b@pacbell.net> - - -This patch replaces the split ISO raw_mask calculation code in the -iso_stream_init() function that computed incorrect numbers of high -speed transactions for both input and output transfers. - -In the output case, it added a superfluous start-split transaction for -all maxmimum packet sizes that are a multiple of 188. - -In the input case, it forgot to add complete-split transactions for all -microframes covered by the full speed transaction, and the additional -complete-split transaction needed for the case when full speed data -starts arriving near the end of a microframe. - -These changes don't affect the lack of full speed bandwidth, but at -least it removes the MMF errors that the HC raised with some input -streams. - -Signed-off-by: Clemens Ladisch <clemens@ladisch.de> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-sched.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c -+++ gregkh-2.6/drivers/usb/host/ehci-sched.c -@@ -707,6 +707,7 @@ iso_stream_init ( - } else { - u32 addr; - int think_time; -+ int hs_transfers; - - addr = dev->ttport << 24; - if (!ehci_is_TDI(ehci) -@@ -719,6 +720,7 @@ iso_stream_init ( - think_time = dev->tt ? dev->tt->think_time : 0; - stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time ( - dev->speed, is_input, 1, maxp)); -+ hs_transfers = max (1u, (maxp + 187) / 188); - if (is_input) { - u32 tmp; - -@@ -727,12 +729,11 @@ iso_stream_init ( - stream->usecs = HS_USECS_ISO (1); - stream->raw_mask = 1; - -- /* pessimistic c-mask */ -- tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp) -- / (125 * 1000); -- stream->raw_mask |= 3 << (tmp + 9); -+ /* c-mask as specified in USB 2.0 11.18.4 3.c */ -+ tmp = (1 << (hs_transfers + 2)) - 1; -+ stream->raw_mask |= tmp << (8 + 2); - } else -- stream->raw_mask = smask_out [maxp / 188]; -+ stream->raw_mask = smask_out [hs_transfers - 1]; - bandwidth = stream->usecs + stream->c_usecs; - bandwidth /= 1 << (interval + 2); - diff --git a/usb/usb-ehci-unlink-tweaks.patch b/usb/usb-ehci-unlink-tweaks.patch deleted file mode 100644 index ea676fd543258..0000000000000 --- a/usb/usb-ehci-unlink-tweaks.patch +++ /dev/null @@ -1,44 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: EHCI unlink tweaks -Date: Fri, 20 Jan 2006 14:35:55 -0800 -Message-Id: <200601201435.56129.david-b@pacbell.net> - -This patch modifies the behavior of the EHCI driver in an unlink path -that seems to be causing various issues on some systems. Those problems -have included issues with disconnection, driver unbinding, and similar -cases where urb unlinking would just not work right. - -This patch should help avoid those problems by not turning off the async -(control/bulk) schedule until it's not expecting an "async advance" IRQ, -which comes from the processing passing the schedule head. Whether the -driver attempts to do such things is dependent on system timings, so -many folk would never have seen these problems. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-q.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-q.c -+++ gregkh-2.6/drivers/usb/host/ehci-q.c -@@ -1022,12 +1022,14 @@ static void start_unlink_async (struct e - /* stop async schedule right now? */ - if (unlikely (qh == ehci->async)) { - /* can't get here without STS_ASS set */ -- if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) { -+ if (ehci_to_hcd(ehci)->state != HC_STATE_HALT -+ && !ehci->reclaim) { -+ /* ... and CMD_IAAD clear */ - writel (cmd & ~CMD_ASE, &ehci->regs->command); - wmb (); - // handshake later, if we need to -+ timer_action_done (ehci, TIMER_ASYNC_OFF); - } -- timer_action_done (ehci, TIMER_ASYNC_OFF); - return; - } - diff --git a/usb/usb-et61x51-driver-updates.patch b/usb/usb-et61x51-driver-updates.patch deleted file mode 100644 index 27d200d631932..0000000000000 --- a/usb/usb-et61x51-driver-updates.patch +++ /dev/null @@ -1,1211 +0,0 @@ -From luca.risolia@studio.unibo.it Fri Feb 24 21:52:39 2006 -Date: Sat, 25 Feb 2006 06:54:18 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: ET61X[12]51 driver updates -Message-ID: <20060225065418.GB31623@studio.unibo.it> -Content-Disposition: inline - -USB: ET61X[12]51 driver updates - -Changes: + new, - removed, * cleanup, @ bugfix - -@ Fix stream_interrupt() -@ Fix vidioc_enum_input() and split vidioc_gs_input() -@ Need usb_get|put_dev() when disconnecting, if the device is open -* Use wait_event_interruptible_timeout() instead of wait_event_interruptible() - when waiting for video frames -* replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream) -* Cleanups and updates in the documentation -* Use mutexes instead of semaphores -+ Use per-device sensor structures -+ Add support for PAS202BCA image sensors -+ Add frame_timeout module parameter - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/et61x251.txt | 10 - drivers/usb/media/et61x251.h | 28 ++ - drivers/usb/media/et61x251_core.c | 321 +++++++++++++++++--------------- - drivers/usb/media/et61x251_sensor.h | 5 - drivers/usb/media/et61x251_tas5130d1b.c | 10 - 5 files changed, 213 insertions(+), 161 deletions(-) - ---- gregkh-2.6.orig/Documentation/usb/et61x251.txt -+++ gregkh-2.6/Documentation/usb/et61x251.txt -@@ -176,6 +176,14 @@ Description: Force the application to - 1 = force memory unmapping (save memory) - Default: 0 - ------------------------------------------------------------------------------- -+Name: frame_timeout -+Type: uint array (min = 0, max = 64) -+Syntax: <n[,...]> -+Description: Timeout for a video frame in seconds. This parameter is -+ specific for each detected camera. This parameter can be -+ changed at runtime thanks to the /sys filesystem interface. -+Default: 2 -+------------------------------------------------------------------------------- - Name: debug - Type: ushort - Syntax: <n> -@@ -266,7 +274,7 @@ the V4L2 interface. - - - 10. Notes for V4L2 application developers --======================================== -+========================================= - This driver follows the V4L2 API specifications. In particular, it enforces two - rules: - ---- gregkh-2.6.orig/drivers/usb/media/et61x251.h -+++ gregkh-2.6/drivers/usb/media/et61x251.h -@@ -33,7 +33,9 @@ - #include <linux/types.h> - #include <linux/param.h> - #include <linux/rwsem.h> --#include <asm/semaphore.h> -+#include <linux/mutex.h> -+#include <linux/stddef.h> -+#include <linux/string.h> - - #include "et61x251_sensor.h" - -@@ -51,6 +53,7 @@ - #define ET61X251_ALTERNATE_SETTING 13 - #define ET61X251_URB_TIMEOUT msecs_to_jiffies(2 * ET61X251_ISO_PACKETS) - #define ET61X251_CTRL_TIMEOUT 100 -+#define ET61X251_FRAME_TIMEOUT 2 - - /*****************************************************************************/ - -@@ -127,15 +130,16 @@ struct et61x251_sysfs_attr { - - struct et61x251_module_param { - u8 force_munmap; -+ u16 frame_timeout; - }; - --static DECLARE_MUTEX(et61x251_sysfs_lock); -+static DEFINE_MUTEX(et61x251_sysfs_lock); - static DECLARE_RWSEM(et61x251_disconnect); - - struct et61x251_device { - struct video_device* v4ldev; - -- struct et61x251_sensor* sensor; -+ struct et61x251_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[ET61X251_URBS]; -@@ -157,19 +161,28 @@ struct et61x251_device { - enum et61x251_dev_state state; - u8 users; - -- struct semaphore dev_sem, fileop_sem; -+ struct mutex dev_mutex, fileop_mutex; - spinlock_t queue_lock; - wait_queue_head_t open, wait_frame, wait_stream; - }; - - /*****************************************************************************/ - -+struct et61x251_device* -+et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) -+{ -+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) -+ return cam; -+ -+ return NULL; -+} -+ -+ - void - et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor) - { -- cam->sensor = sensor; -- cam->sensor->usbdev = cam->usbdev; -+ memcpy(&cam->sensor, sensor, sizeof(struct et61x251_sensor)); - } - - /*****************************************************************************/ -@@ -212,7 +225,8 @@ do { - - #undef PDBG - #define PDBG(fmt, args...) \ --dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) -+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ -+ __FUNCTION__, __LINE__ , ## args) - - #undef PDBGG - #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ ---- gregkh-2.6.orig/drivers/usb/media/et61x251_core.c -+++ gregkh-2.6/drivers/usb/media/et61x251_core.c -@@ -25,11 +25,9 @@ - #include <linux/moduleparam.h> - #include <linux/errno.h> - #include <linux/slab.h> --#include <linux/string.h> - #include <linux/device.h> - #include <linux/fs.h> - #include <linux/delay.h> --#include <linux/stddef.h> - #include <linux/compiler.h> - #include <linux/ioctl.h> - #include <linux/poll.h> -@@ -50,8 +48,8 @@ - #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" - #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" - #define ET61X251_MODULE_LICENSE "GPL" --#define ET61X251_MODULE_VERSION "1:1.01" --#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) -+#define ET61X251_MODULE_VERSION "1:1.02" -+#define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) - - /*****************************************************************************/ - -@@ -90,6 +88,16 @@ MODULE_PARM_DESC(force_munmap, - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -+static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = -+ ET61X251_FRAME_TIMEOUT}; -+module_param_array(frame_timeout, uint, NULL, 0644); -+MODULE_PARM_DESC(frame_timeout, -+ "\n<n[,...]> Timeout for a video frame in seconds." -+ "\nThis parameter is specific for each detected camera." -+ "\nDefault value is " -+ __MODULE_STRING(ET61X251_FRAME_TIMEOUT)"." -+ "\n"); -+ - #ifdef ET61X251_DEBUG - static unsigned short debug = ET61X251_DEBUG_LEVEL; - module_param(debug, ushort, 0644); -@@ -111,8 +119,8 @@ static u32 - et61x251_request_buffers(struct et61x251_device* cam, u32 count, - enum et61x251_io_method io) - { -- struct v4l2_pix_format* p = &(cam->sensor->pix_format); -- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); -+ struct v4l2_pix_format* p = &(cam->sensor.pix_format); -+ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : -@@ -268,8 +276,8 @@ et61x251_i2c_try_read(struct et61x251_de - int err = 0, res; - - data[0] = address; -- data[1] = cam->sensor->i2c_slave_id; -- data[2] = cam->sensor->rsta | 0x10; -+ data[1] = cam->sensor.i2c_slave_id; -+ data[2] = cam->sensor.rsta | 0x10; - data[3] = !(et61x251_read_reg(cam, 0x8b) & 0x02); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 4, ET61X251_CTRL_TIMEOUT); -@@ -301,8 +309,8 @@ et61x251_i2c_try_write(struct et61x251_d - int err = 0, res; - - data[0] = address; -- data[1] = cam->sensor->i2c_slave_id; -- data[2] = cam->sensor->rsta | 0x12; -+ data[1] = cam->sensor.i2c_slave_id; -+ data[2] = cam->sensor.rsta | 0x12; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) -@@ -334,9 +342,6 @@ et61x251_i2c_raw_write(struct et61x251_d - u8* data = cam->control_buffer; - int err = 0, res; - -- if (!cam->sensor) -- return -1; -- - data[0] = data2; - data[1] = data3; - data[2] = data4; -@@ -350,8 +355,8 @@ et61x251_i2c_raw_write(struct et61x251_d - err += res; - - data[0] = address; -- data[1] = cam->sensor->i2c_slave_id; -- data[2] = cam->sensor->rsta | 0x02 | (n << 4); -+ data[1] = cam->sensor.i2c_slave_id; -+ data[2] = cam->sensor.rsta | 0x02 | (n << 4); - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00, 0x41, - 0, 0x88, data, 3, ET61X251_CTRL_TIMEOUT); - if (res < 0) -@@ -364,11 +369,11 @@ et61x251_i2c_raw_write(struct et61x251_d - if (res < 0) - err += res; - -- err += et61x251_i2c_wait(cam, cam->sensor); -+ err += et61x251_i2c_wait(cam, &cam->sensor); - - if (err) - DBG(3, "I2C raw write failed for %s image sensor", -- cam->sensor->name); -+ cam->sensor.name); - - PDBGG("I2C raw write: %u bytes, address = 0x%02X, data1 = 0x%02X, " - "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X," -@@ -382,19 +387,13 @@ et61x251_i2c_raw_write(struct et61x251_d - - int et61x251_i2c_read(struct et61x251_device* cam, u8 address) - { -- if (!cam->sensor) -- return -1; -- -- return et61x251_i2c_try_read(cam, cam->sensor, address); -+ return et61x251_i2c_try_read(cam, &cam->sensor, address); - } - - - int et61x251_i2c_write(struct et61x251_device* cam, u8 address, u8 value) - { -- if (!cam->sensor) -- return -1; -- -- return et61x251_i2c_try_write(cam, cam->sensor, address, value); -+ return et61x251_i2c_try_write(cam, &cam->sensor, address, value); - } - - /*****************************************************************************/ -@@ -417,7 +416,7 @@ static void et61x251_urb_complete(struct - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) -@@ -435,9 +434,9 @@ static void et61x251_urb_complete(struct - (*f) = list_entry(cam->inqueue.next, struct et61x251_frame_t, - frame); - -- imagesize = (cam->sensor->pix_format.width * -- cam->sensor->pix_format.height * -- cam->sensor->pix_format.priv) / 8; -+ imagesize = (cam->sensor.pix_format.width * -+ cam->sensor.pix_format.height * -+ cam->sensor.pix_format.priv) / 8; - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int len, status; -@@ -476,7 +475,7 @@ start_of_frame: - - if ((*f)->state == F_GRABBING) { - if (sof && (*f)->buf.bytesused) { -- if (cam->sensor->pix_format.pixelformat == -+ if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) - goto end_of_frame; - else { -@@ -521,7 +520,7 @@ end_of_frame: - goto resubmit_urb; - - if (sof && -- cam->sensor->pix_format.pixelformat == -+ cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_ET61X251) - goto start_of_frame; - } -@@ -650,21 +649,21 @@ static int et61x251_stop_transfer(struct - - static int et61x251_stream_interrupt(struct et61x251_device* cam) - { -- int err = 0; -+ long timeout; - - cam->stream = STREAM_INTERRUPT; -- err = wait_event_timeout(cam->wait_stream, -- (cam->stream == STREAM_OFF) || -- (cam->state & DEV_DISCONNECTED), -- ET61X251_URB_TIMEOUT); -+ timeout = wait_event_timeout(cam->wait_stream, -+ (cam->stream == STREAM_OFF) || -+ (cam->state & DEV_DISCONNECTED), -+ ET61X251_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; -- else if (err) { -+ else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", - cam->v4ldev->minor); -- return err; -+ return -EIO; - } - - return 0; -@@ -709,18 +708,18 @@ static ssize_t et61x251_show_reg(struct - struct et61x251_device* cam; - ssize_t count; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - count = sprintf(buf, "%u\n", cam->sysfs.reg); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -733,18 +732,18 @@ et61x251_store_reg(struct class_device* - u8 index; - ssize_t count; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - index = et61x251_strtou8(buf, len, &count); - if (index > 0x8e || !count) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - -@@ -753,7 +752,7 @@ et61x251_store_reg(struct class_device* - DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); - DBG(3, "Written bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -765,17 +764,17 @@ static ssize_t et61x251_show_val(struct - ssize_t count; - int val; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - -@@ -783,7 +782,7 @@ static ssize_t et61x251_show_val(struct - - DBG(3, "Read bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -797,24 +796,24 @@ et61x251_store_val(struct class_device* - ssize_t count; - int err; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - value = et61x251_strtou8(buf, len, &count); - if (!count) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - err = et61x251_write_reg(cam, value, cam->sysfs.reg); - if (err) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - -@@ -822,7 +821,7 @@ et61x251_store_val(struct class_device* - cam->sysfs.reg, value); - DBG(3, "Written bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -833,12 +832,12 @@ static ssize_t et61x251_show_i2c_reg(str - struct et61x251_device* cam; - ssize_t count; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - -@@ -846,7 +845,7 @@ static ssize_t et61x251_show_i2c_reg(str - - DBG(3, "Read bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -859,18 +858,18 @@ et61x251_store_i2c_reg(struct class_devi - u8 index; - ssize_t count; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - - index = et61x251_strtou8(buf, len, &count); - if (!count) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - -@@ -879,7 +878,7 @@ et61x251_store_i2c_reg(struct class_devi - DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg); - DBG(3, "Written bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -891,22 +890,22 @@ static ssize_t et61x251_show_i2c_val(str - ssize_t count; - int val; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - -- if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { -- up(&et61x251_sysfs_lock); -+ if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENOSYS; - } - - if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - -@@ -914,7 +913,7 @@ static ssize_t et61x251_show_i2c_val(str - - DBG(3, "Read bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -928,29 +927,29 @@ et61x251_store_i2c_val(struct class_devi - ssize_t count; - int err; - -- if (down_interruptible(&et61x251_sysfs_lock)) -+ if (mutex_lock_interruptible(&et61x251_sysfs_lock)) - return -ERESTARTSYS; - - cam = video_get_drvdata(to_video_device(cd)); - if (!cam) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENODEV; - } - -- if (!(cam->sensor->sysfs_ops & ET61X251_I2C_READ)) { -- up(&et61x251_sysfs_lock); -+ if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { -+ mutex_unlock(&et61x251_sysfs_lock); - return -ENOSYS; - } - - value = et61x251_strtou8(buf, len, &count); - if (!count) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EINVAL; - } - - err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); - if (err) { -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - return -EIO; - } - -@@ -958,7 +957,7 @@ et61x251_store_i2c_val(struct class_devi - cam->sysfs.i2c_reg, value); - DBG(3, "Written bytes: %zd", count); - -- up(&et61x251_sysfs_lock); -+ mutex_unlock(&et61x251_sysfs_lock); - - return count; - } -@@ -980,7 +979,7 @@ static void et61x251_create_sysfs(struct - - video_device_create_file(v4ldev, &class_device_attr_reg); - video_device_create_file(v4ldev, &class_device_attr_val); -- if (cam->sensor && cam->sensor->sysfs_ops) { -+ if (cam->sensor.sysfs_ops) { - video_device_create_file(v4ldev, &class_device_attr_i2c_reg); - video_device_create_file(v4ldev, &class_device_attr_i2c_val); - } -@@ -1048,7 +1047,7 @@ static int et61x251_set_scale(struct et6 - static int - et61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + - s->active_pixel.left), - fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + -@@ -1076,7 +1075,7 @@ et61x251_set_crop(struct et61x251_device - - static int et61x251_init(struct et61x251_device* cam) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; -@@ -1143,7 +1142,7 @@ static int et61x251_init(struct et61x251 - } - - if (!(cam->state & DEV_INITIALIZED)) { -- init_MUTEX(&cam->fileop_sem); -+ mutex_init(&cam->fileop_mutex); - spin_lock_init(&cam->queue_lock); - init_waitqueue_head(&cam->wait_frame); - init_waitqueue_head(&cam->wait_stream); -@@ -1161,13 +1160,15 @@ static int et61x251_init(struct et61x251 - - static void et61x251_release_resources(struct et61x251_device* cam) - { -- down(&et61x251_sysfs_lock); -+ mutex_lock(&et61x251_sysfs_lock); - - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - -- up(&et61x251_sysfs_lock); -+ usb_put_dev(cam->usbdev); -+ -+ mutex_unlock(&et61x251_sysfs_lock); - - kfree(cam->control_buffer); - } -@@ -1188,7 +1189,7 @@ static int et61x251_open(struct inode* i - - cam = video_get_drvdata(video_devdata(filp)); - -- if (down_interruptible(&cam->dev_sem)) { -+ if (mutex_lock_interruptible(&cam->dev_mutex)) { - up_read(&et61x251_disconnect); - return -ERESTARTSYS; - } -@@ -1200,7 +1201,7 @@ static int et61x251_open(struct inode* i - err = -EWOULDBLOCK; - goto out; - } -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - err = wait_event_interruptible_exclusive(cam->open, - cam->state & DEV_DISCONNECTED - || !cam->users); -@@ -1212,7 +1213,7 @@ static int et61x251_open(struct inode* i - up_read(&et61x251_disconnect); - return -ENODEV; - } -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - } - - -@@ -1240,7 +1241,7 @@ static int et61x251_open(struct inode* i - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); - - out: -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - up_read(&et61x251_disconnect); - return err; - } -@@ -1250,7 +1251,7 @@ static int et61x251_release(struct inode - { - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - -- down(&cam->dev_sem); /* prevent disconnect() to be called */ -+ mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */ - - et61x251_stop_transfer(cam); - -@@ -1258,7 +1259,7 @@ static int et61x251_release(struct inode - - if (cam->state & DEV_DISCONNECTED) { - et61x251_release_resources(cam); -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; - } -@@ -1268,7 +1269,7 @@ static int et61x251_release(struct inode - - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - return 0; - } -@@ -1281,28 +1282,29 @@ et61x251_read(struct file* filp, char __ - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - struct et61x251_frame_t* f, * i; - unsigned long lock_flags; -+ long timeout; - int err = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io == IO_MMAP) { - DBG(3, "Close and open the device again to choose the read " - "method"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - -@@ -1310,7 +1312,7 @@ et61x251_read(struct file* filp, char __ - if (!et61x251_request_buffers(cam, cam->nreadbuffers, - IO_READ)) { - DBG(1, "read() failed, not enough memory"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENOMEM; - } - cam->io = IO_READ; -@@ -1324,30 +1326,32 @@ et61x251_read(struct file* filp, char __ - } - - if (!count) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return 0; - } - - if (list_empty(&cam->outqueue)) { - if (filp->f_flags & O_NONBLOCK) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } -- err = wait_event_interruptible -- ( cam->wait_frame, -- (!list_empty(&cam->outqueue)) || -- (cam->state & DEV_DISCONNECTED) || -- (cam->state & DEV_MISCONFIGURED) ); -- if (err) { -- up(&cam->fileop_sem); -- return err; -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); -+ if (timeout < 0) { -+ mutex_unlock(&cam->fileop_mutex); -+ return timeout; - } - if (cam->state & DEV_DISCONNECTED) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } -- if (cam->state & DEV_MISCONFIGURED) { -- up(&cam->fileop_sem); -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) { -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - } -@@ -1375,7 +1379,7 @@ exit: - PDBGG("Frame #%lu, bytes read: %zu", - (unsigned long)f->buf.index, count); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return err ? err : count; - } -@@ -1388,7 +1392,7 @@ static unsigned int et61x251_poll(struct - unsigned long lock_flags; - unsigned int mask = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return POLLERR; - - if (cam->state & DEV_DISCONNECTED) { -@@ -1426,12 +1430,12 @@ static unsigned int et61x251_poll(struct - if (!list_empty(&cam->outqueue)) - mask |= POLLIN | POLLRDNORM; - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return mask; - - error: -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return POLLERR; - } - -@@ -1465,25 +1469,25 @@ static int et61x251_mmap(struct file* fi - void *pos; - u32 i; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - - if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || - size != PAGE_ALIGN(cam->frame[0].buf.length)) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - -@@ -1492,7 +1496,7 @@ static int et61x251_mmap(struct file* fi - break; - } - if (i == cam->nbuffers) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EINVAL; - } - -@@ -1502,7 +1506,7 @@ static int et61x251_mmap(struct file* fi - pos = cam->frame[i].bufmem; - while (size > 0) { /* size is page-aligned */ - if (vm_insert_page(vma, start, vmalloc_to_page(pos))) { -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } - start += PAGE_SIZE; -@@ -1515,7 +1519,7 @@ static int et61x251_mmap(struct file* fi - - et61x251_vm_open(vma); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return 0; - } -@@ -1557,6 +1561,7 @@ et61x251_vidioc_enuminput(struct et61x25 - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); -+ i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; -@@ -1566,7 +1571,19 @@ et61x251_vidioc_enuminput(struct et61x25 - - - static int --et61x251_vidioc_gs_input(struct et61x251_device* cam, void __user * arg) -+et61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg) -+{ -+ int index = 0; -+ -+ if (copy_to_user(arg, &index, sizeof(index))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+et61x251_vidioc_s_input(struct et61x251_device* cam, void __user * arg) - { - int index; - -@@ -1583,7 +1600,7 @@ et61x251_vidioc_gs_input(struct et61x251 - static int - et61x251_vidioc_query_ctrl(struct et61x251_device* cam, void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - -@@ -1605,7 +1622,7 @@ et61x251_vidioc_query_ctrl(struct et61x2 - static int - et61x251_vidioc_g_ctrl(struct et61x251_device* cam, void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; -@@ -1637,7 +1654,7 @@ exit: - static int - et61x251_vidioc_s_ctrl(struct et61x251_device* cam, void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; -@@ -1650,6 +1667,8 @@ et61x251_vidioc_s_ctrl(struct et61x251_d - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { -+ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) -+ return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; -@@ -1669,7 +1688,7 @@ et61x251_vidioc_s_ctrl(struct et61x251_d - static int - et61x251_vidioc_cropcap(struct et61x251_device* cam, void __user * arg) - { -- struct v4l2_cropcap* cc = &(cam->sensor->cropcap); -+ struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; -@@ -1685,7 +1704,7 @@ et61x251_vidioc_cropcap(struct et61x251_ - static int - et61x251_vidioc_g_crop(struct et61x251_device* cam, void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; -@@ -1702,7 +1721,7 @@ et61x251_vidioc_g_crop(struct et61x251_d - static int - et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); -@@ -1843,7 +1862,7 @@ static int - et61x251_vidioc_g_fmt(struct et61x251_device* cam, void __user * arg) - { - struct v4l2_format format; -- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); -+ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; -@@ -1868,7 +1887,7 @@ static int - et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, - void __user * arg) - { -- struct et61x251_sensor* s = cam->sensor; -+ struct et61x251_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); -@@ -2155,7 +2174,7 @@ et61x251_vidioc_dqbuf(struct et61x251_de - struct v4l2_buffer b; - struct et61x251_frame_t *f; - unsigned long lock_flags; -- int err = 0; -+ long timeout; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; -@@ -2168,16 +2187,18 @@ et61x251_vidioc_dqbuf(struct et61x251_de - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; -- err = wait_event_interruptible -- ( cam->wait_frame, -- (!list_empty(&cam->outqueue)) || -- (cam->state & DEV_DISCONNECTED) || -- (cam->state & DEV_MISCONFIGURED) ); -- if (err) -- return err; -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); -+ if (timeout < 0) -+ return timeout; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; -- if (cam->state & DEV_MISCONFIGURED) -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) - return -EIO; - } - -@@ -2309,8 +2330,10 @@ static int et61x251_ioctl_v4l2(struct in - return et61x251_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: -+ return et61x251_vidioc_g_input(cam, arg); -+ - case VIDIOC_S_INPUT: -- return et61x251_vidioc_gs_input(cam, arg); -+ return et61x251_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return et61x251_vidioc_query_ctrl(cam, arg); -@@ -2393,19 +2416,19 @@ static int et61x251_ioctl(struct inode* - struct et61x251_device* cam = video_get_drvdata(video_devdata(filp)); - int err = 0; - -- if (down_interruptible(&cam->fileop_sem)) -+ if (mutex_lock_interruptible(&cam->fileop_mutex)) - return -ERESTARTSYS; - - if (cam->state & DEV_DISCONNECTED) { - DBG(1, "Device not present"); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } - - if (cam->state & DEV_MISCONFIGURED) { - DBG(1, "The camera is misconfigured. Close and open it " - "again."); -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - return -EIO; - } - -@@ -2413,7 +2436,7 @@ static int et61x251_ioctl(struct inode* - - err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); - -- up(&cam->fileop_sem); -+ mutex_unlock(&cam->fileop_mutex); - - return err; - } -@@ -2459,7 +2482,7 @@ et61x251_usb_probe(struct usb_interface* - goto fail; - } - -- init_MUTEX(&cam->dev_sem); -+ mutex_init(&cam->dev_mutex); - - DBG(2, "ET61X[12]51 PC Camera Controller detected " - "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); -@@ -2470,8 +2493,8 @@ et61x251_usb_probe(struct usb_interface* - break; - } - -- if (!err && cam->sensor) -- DBG(2, "%s image sensor detected", cam->sensor->name); -+ if (!err) -+ DBG(2, "%s image sensor detected", cam->sensor.name); - else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; -@@ -2492,7 +2515,7 @@ et61x251_usb_probe(struct usb_interface* - cam->v4ldev->release = video_device_release; - video_set_drvdata(cam->v4ldev, cam); - -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER, - video_nr[dev_nr]); -@@ -2502,13 +2525,14 @@ et61x251_usb_probe(struct usb_interface* - DBG(1, "Free /dev/videoX node not found"); - video_nr[dev_nr] = -1; - dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - goto fail; - } - - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; -+ cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; - -@@ -2519,7 +2543,7 @@ et61x251_usb_probe(struct usb_interface* - - usb_set_intfdata(intf, cam); - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - return 0; - -@@ -2543,7 +2567,7 @@ static void et61x251_usb_disconnect(stru - - down_write(&et61x251_disconnect); - -- down(&cam->dev_sem); -+ mutex_lock(&cam->dev_mutex); - - DBG(2, "Disconnecting %s...", cam->v4ldev->name); - -@@ -2557,13 +2581,14 @@ static void et61x251_usb_disconnect(stru - et61x251_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); -+ usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - et61x251_release_resources(cam); - } - -- up(&cam->dev_sem); -+ mutex_unlock(&cam->dev_mutex); - - if (!cam->users) - kfree(cam); ---- gregkh-2.6.orig/drivers/usb/media/et61x251_sensor.h -+++ gregkh-2.6/drivers/usb/media/et61x251_sensor.h -@@ -42,6 +42,9 @@ static int (*et61x251_sensor_table[])(st - NULL, \ - }; - -+extern struct et61x251_device* -+et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id); -+ - extern void - et61x251_attach_sensor(struct et61x251_device* cam, - struct et61x251_sensor* sensor); -@@ -105,8 +108,6 @@ struct et61x251_sensor { - int (*set_pix_format)(struct et61x251_device* cam, - const struct v4l2_pix_format* pix); - -- const struct usb_device* usbdev; -- - /* Private */ - struct v4l2_queryctrl _qctrl[ET61X251_MAX_CTRLS]; - struct v4l2_rect _rect; ---- gregkh-2.6.orig/drivers/usb/media/et61x251_tas5130d1b.c -+++ gregkh-2.6/drivers/usb/media/et61x251_tas5130d1b.c -@@ -126,12 +126,16 @@ static struct et61x251_sensor tas5130d1b - - int et61x251_probe_tas5130d1b(struct et61x251_device* cam) - { -- /* This sensor has no identifiers, so let's attach it anyway */ -- et61x251_attach_sensor(cam, &tas5130d1b); -+ const struct usb_device_id tas5130d1b_id_table[] = { -+ { USB_DEVICE(0x102c, 0x6251), }, -+ { } -+ }; - - /* Sensor detection is based on USB pid/vid */ -- if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6251) -+ if (!et61x251_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - -+ et61x251_attach_sensor(cam, &tas5130d1b); -+ - return 0; - } diff --git a/usb/usb-ethernet-gadget-driver-section-fixups.patch b/usb/usb-ethernet-gadget-driver-section-fixups.patch deleted file mode 100644 index a4e78ff61afd0..0000000000000 --- a/usb/usb-ethernet-gadget-driver-section-fixups.patch +++ /dev/null @@ -1,145 +0,0 @@ -From david-b@pacbell.net Sat Feb 18 12:51:14 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <gregkh@suse.de> -Subject: USB: ethernet gadget driver section fixups -Date: Sat, 18 Feb 2006 12:31:23 -0800 -Cc: Aras Vaichas <arasv@magellan-technology.com> -Message-Id: <200602181231.23445.david-b@pacbell.net> - -From: Aras Vaichas <arasv@magellan-technology.com> - -This patch allows you to set the iSerialNumber field in the -usb_device_descriptor structure for your USB ethernet gadget. - -It also changes the parameters shown through sysfs so they're -no longer declared as __initdata, preventing potential oopses. - -That's most useful for the Ethernet addresses, which may in -some cases be random "locally administered" addresses. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/ether.c | 38 +++++++++++++++++++++++++++----------- - 1 file changed, 27 insertions(+), 11 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/ether.c -+++ gregkh-2.6/drivers/usb/gadget/ether.c -@@ -182,33 +182,37 @@ struct eth_dev { - * parameters are in UTF-8 (superset of ASCII's 7 bit characters). - */ - --static ushort __initdata idVendor; -+static ushort idVendor; - module_param(idVendor, ushort, S_IRUGO); - MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - --static ushort __initdata idProduct; -+static ushort idProduct; - module_param(idProduct, ushort, S_IRUGO); - MODULE_PARM_DESC(idProduct, "USB Product ID"); - --static ushort __initdata bcdDevice; -+static ushort bcdDevice; - module_param(bcdDevice, ushort, S_IRUGO); - MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - --static char *__initdata iManufacturer; -+static char *iManufacturer; - module_param(iManufacturer, charp, S_IRUGO); - MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - --static char *__initdata iProduct; -+static char *iProduct; - module_param(iProduct, charp, S_IRUGO); - MODULE_PARM_DESC(iProduct, "USB Product string"); - -+static char *iSerialNumber; -+module_param(iSerialNumber, charp, S_IRUGO); -+MODULE_PARM_DESC(iSerialNumber, "SerialNumber"); -+ - /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ --static char *__initdata dev_addr; -+static char *dev_addr; - module_param(dev_addr, charp, S_IRUGO); - MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); - - /* this address is invisible to ifconfig */ --static char *__initdata host_addr; -+static char *host_addr; - module_param(host_addr, charp, S_IRUGO); - MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); - -@@ -403,6 +407,7 @@ static inline int BITRATE(struct usb_gad - #define STRING_CDC 7 - #define STRING_SUBSET 8 - #define STRING_RNDIS 9 -+#define STRING_SERIALNUMBER 10 - - /* holds our biggest descriptor (or RNDIS response) */ - #define USB_BUFSIZ 256 -@@ -870,6 +875,7 @@ static inline void __init hs_subset_desc - - static char manufacturer [50]; - static char product_desc [40] = DRIVER_DESC; -+static char serial_number [20]; - - #ifdef DEV_CONFIG_CDC - /* address that the host will use ... usually assigned at random */ -@@ -880,6 +886,7 @@ static char ethaddr [2 * ETH_ALEN + 1 - static struct usb_string strings [] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, -+ { STRING_SERIALNUMBER, serial_number, }, - { STRING_DATA, "Ethernet Data", }, - #ifdef DEV_CONFIG_CDC - { STRING_CDC, "CDC Ethernet", }, -@@ -2162,7 +2169,7 @@ static u8 __init nibble (unsigned char c - return 0; - } - --static void __init get_ether_addr (const char *str, u8 *dev_addr) -+static int __init get_ether_addr(const char *str, u8 *dev_addr) - { - if (str) { - unsigned i; -@@ -2177,9 +2184,10 @@ static void __init get_ether_addr (const - dev_addr [i] = num; - } - if (is_valid_ether_addr (dev_addr)) -- return; -+ return 0; - } - random_ether_addr(dev_addr); -+ return 1; - } - - static int __init -@@ -2277,6 +2285,10 @@ eth_bind (struct usb_gadget *gadget) - strlcpy (manufacturer, iManufacturer, sizeof manufacturer); - if (iProduct) - strlcpy (product_desc, iProduct, sizeof product_desc); -+ if (iSerialNumber) { -+ device_desc.iSerialNumber = STRING_SERIALNUMBER, -+ strlcpy(serial_number, iSerialNumber, sizeof serial_number); -+ } - - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset (gadget); -@@ -2386,9 +2398,13 @@ autoconf_fail: - * The host side address is used with CDC and RNDIS, and commonly - * ends up in a persistent config database. - */ -- get_ether_addr(dev_addr, net->dev_addr); -+ if (get_ether_addr(dev_addr, net->dev_addr)) -+ dev_warn(&gadget->dev, -+ "using random %s ethernet address\n", "self"); - if (cdc || rndis) { -- get_ether_addr(host_addr, dev->host_mac); -+ if (get_ether_addr(host_addr, dev->host_mac)) -+ dev_warn(&gadget->dev, -+ "using random %s ethernet address\n", "host"); - #ifdef DEV_CONFIG_CDC - snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", - dev->host_mac [0], dev->host_mac [1], diff --git a/usb/usb-fix-check_ctrlrecip-to-allow-control-transfers-in-state-address.patch b/usb/usb-fix-check_ctrlrecip-to-allow-control-transfers-in-state-address.patch deleted file mode 100644 index 91a2942744afd..0000000000000 --- a/usb/usb-fix-check_ctrlrecip-to-allow-control-transfers-in-state-address.patch +++ /dev/null @@ -1,41 +0,0 @@ -From akpm@osdl.org Sat Mar 11 00:19:34 2006 -Message-Id: <200603110819.k2B8J2q3023867@shell0.pdx.osdl.net> -From: Horst Schirmeier <horst@schirmeier.com> -Subject: USB: fix check_ctrlrecip to allow control transfers in state ADDRESS -To: horst@schirmeier.com, david-b@pacbell.net, greg@kroah.com, - stern@rowland.harvard.edu, mm-commits@vger.kernel.org -Date: Sat, 11 Mar 2006 00:16:55 -0800 - - -From: Horst Schirmeier <horst@schirmeier.com> - -check_ctrlrecip() disallows any control transfers if the device is -deconfigured (in configuration 0, ie. state ADDRESS). This for example -makes it impossible to read the device descriptors without configuring the -device, although most standard device requests are allowed in this state by -the spec. This patch allows control transfers for the ADDRESS state, too. - -Signed-off-by: Horst Schirmeier <horst@schirmeier.com> -Cc: Alan Stern <stern@rowland.harvard.edu> -Cc: David Brownell <david-b@pacbell.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - - ---- - drivers/usb/core/devio.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/core/devio.c -+++ gregkh-2.6/drivers/usb/core/devio.c -@@ -493,7 +493,8 @@ static int check_ctrlrecip(struct dev_st - { - int ret = 0; - -- if (ps->dev->state != USB_STATE_CONFIGURED) -+ if (ps->dev->state != USB_STATE_ADDRESS -+ && ps->dev->state != USB_STATE_CONFIGURED) - return -EHOSTUNREACH; - if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) - return 0; diff --git a/usb/usb-fix-irda-usb-use-after-use.patch b/usb/usb-fix-irda-usb-use-after-use.patch deleted file mode 100644 index 68dd9debca1eb..0000000000000 --- a/usb/usb-fix-irda-usb-use-after-use.patch +++ /dev/null @@ -1,47 +0,0 @@ -From akpm@osdl.org Wed Mar 15 14:55:13 2006 -Message-Id: <200603152255.k2FMt0sE006736@shell0.pdx.osdl.net> -From: Eugene Teo <eugene.teo@eugeneteo.net> -Subject: USB: Fix irda-usb use after use -To: eugene.teo@eugeneteo.net, davem@davemloft.net, greg@kroah.com -Date: Wed, 15 Mar 2006 14:57:19 -0800 - -From: Eugene Teo <eugene.teo@eugeneteo.net> - -Don't read from free'd memory after calling netif_rx(). docopy is used as -a boolean (0 and 1) so unsigned int is sufficient. - -Coverity bug #928 - -Signed-off-by: Eugene Teo <eugene.teo@eugeneteo.net> -Cc: "David S. Miller" <davem@davemloft.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - - drivers/net/irda/irda-usb.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/net/irda/irda-usb.c -+++ gregkh-2.6/drivers/net/irda/irda-usb.c -@@ -740,7 +740,7 @@ static void irda_usb_receive(struct urb - struct sk_buff *newskb; - struct sk_buff *dataskb; - struct urb *next_urb; -- int docopy; -+ unsigned int len, docopy; - - IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length); - -@@ -851,10 +851,11 @@ static void irda_usb_receive(struct urb - dataskb->dev = self->netdev; - dataskb->mac.raw = dataskb->data; - dataskb->protocol = htons(ETH_P_IRDA); -+ len = dataskb->len; - netif_rx(dataskb); - - /* Keep stats up to date */ -- self->stats.rx_bytes += dataskb->len; -+ self->stats.rx_bytes += len; - self->stats.rx_packets++; - self->netdev->last_rx = jiffies; - diff --git a/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch b/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch deleted file mode 100644 index 39e777d5c9bde..0000000000000 --- a/usb/usb-fix-masking-bug-initialization-of-freescale-ehci-controller.patch +++ /dev/null @@ -1,32 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Tue Jan 24 08:41:21 2006 -From: Kumar Gala <galak@kernel.crashing.org> -To: linux-usb-devel@lists.sourceforge.net -Subject: USB: Fix masking bug initialization of Freescale EHCI controller -Cc: Kumar Gala <galak@gate.crashing.org>, dbrownell@users.sourceforge.net, Randy Vinson <rvinson@mvista.com> -Content-Disposition: inline -Message-Id: <200601240811.27539.david-b@pacbell.net> -Date: Tue, 24 Jan 2006 08:11:27 -0800 - -In setting up the of PHY we masked off too many bits, instead just -initialize PORTSC for the type of PHY we are using. - -Signed-off-by: Kumar Gala <galak@kernel.crashing.org> -Acked-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-fsl.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-fsl.c -+++ gregkh-2.6/drivers/usb/host/ehci-fsl.c -@@ -160,8 +160,7 @@ static void mpc83xx_setup_phy(struct ehc - enum fsl_usb2_phy_modes phy_mode, - unsigned int port_offset) - { -- u32 portsc = readl(&ehci->regs->port_status[port_offset]); -- portsc &= ~PORT_PTS_MSK; -+ u32 portsc = 0; - switch (phy_mode) { - case FSL_USB2_PHY_ULPI: - portsc |= PORT_PTS_ULPI; diff --git a/usb/usb-fix-warning-in-drivers-usb-media-ov511.c.patch b/usb/usb-fix-warning-in-drivers-usb-media-ov511.c.patch deleted file mode 100644 index 176062ebd0ac7..0000000000000 --- a/usb/usb-fix-warning-in-drivers-usb-media-ov511.c.patch +++ /dev/null @@ -1,33 +0,0 @@ -From kernel-janitors-bounces@lists.osdl.org Wed Feb 15 13:45:49 2006 -From: Matthew Martin <lihnucks@gmail.com> -To: kernel-janitors@lists.osdl.org -Date: Wed, 15 Feb 2006 15:41:25 -0600 -Message-Id: <1140039685.14352.1.camel@localhost.localdomain> -Subject: USB: Fix warning in drivers/usb/media/ov511.c - -Gcc 4.0.2 had the warning: - -drivers/usb/media/ov511.c: In function 'show_exposure': -drivers/usb/media/ov511.c:5642: warning: 'exp' may be used uninitialized -in this function - -Here is the patch to fix that warning. - -Signed-off-by: Matthew Martin <lihnucks@gmail.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/media/ov511.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/media/ov511.c -+++ gregkh-2.6/drivers/usb/media/ov511.c -@@ -5639,7 +5639,7 @@ static CLASS_DEVICE_ATTR(hue, S_IRUGO, s - static ssize_t show_exposure(struct class_device *cd, char *buf) - { - struct usb_ov511 *ov = cd_to_ov(cd); -- unsigned char exp; -+ unsigned char exp = 0; - - if (!ov->dev) - return -ENODEV; diff --git a/usb/usb-ftdi_sio-add-icom-id1-usb-product-and-vendor-ids.patch b/usb/usb-ftdi_sio-add-icom-id1-usb-product-and-vendor-ids.patch deleted file mode 100644 index 68a4802b110d3..0000000000000 --- a/usb/usb-ftdi_sio-add-icom-id1-usb-product-and-vendor-ids.patch +++ /dev/null @@ -1,50 +0,0 @@ -From bottoms@airborne.nrl.navy.mil Tue Mar 14 15:44:28 2006 -Message-ID: <17431.21847.295167.980061@airborne.nrl.navy.mil> -Date: Tue, 14 Mar 2006 18:44:23 -0500 -From: "A. Maitland Bottoms" <bottoms@debian.org> -To: Greg KH <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, - Kuba Ober <kuba@mareimbrium.org> -Cc: Vojtech Pavlik <vojtech@suse.cz> -Subject: USB: ftdi_sio: add Icom ID1 USB product and vendor ids - -From: "A. Maitland Bottoms" <bottoms@debian.org> - -The Icom ID-1 1.2 GHz band digital transceiver is a new radio -that has a USB interface. With this patch, the ftdi_sio driver -will report "Detected FT8U232AM" and provide a serial device -interface. - -Signed-off-by: "A. Maitland Bottoms" <bottoms@debian.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/serial/ftdi_sio.c | 1 + - drivers/usb/serial/ftdi_sio.h | 7 +++++++ - 2 files changed, 8 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c -+++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c -@@ -492,6 +492,7 @@ static struct usb_device_id id_table_com - { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_777_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_WESTREX_MODEL_8900F_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, -+ { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, - { }, /* Optional parameter entry */ - { } /* Terminating entry */ - }; ---- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.h -+++ gregkh-2.6/drivers/usb/serial/ftdi_sio.h -@@ -146,6 +146,13 @@ - #define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ - - /* -+ * Icom ID-1 digital transceiver -+ */ -+ -+#define ICOM_ID1_VID 0x0C26 -+#define ICOM_ID1_PID 0x0004 -+ -+/* - * DSS-20 Sync Station for Sony Ericsson P800 - */ - diff --git a/usb/usb-gadget-driver-section-fixups.patch b/usb/usb-gadget-driver-section-fixups.patch deleted file mode 100644 index 82ea27ecd63cb..0000000000000 --- a/usb/usb-gadget-driver-section-fixups.patch +++ /dev/null @@ -1,147 +0,0 @@ -From david-b@pacbell.net Sat Feb 18 12:51:14 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <gregkh@suse.de> -Subject: USB: gadget driver section fixups -Date: Sat, 18 Feb 2006 12:31:05 -0800 -Message-Id: <200602181231.05193.david-b@pacbell.net> - - -This adds __init section annotations to gadget driver bind() routines to -remove calls from .text into .init sections (for endpoint autoconfig). -Likewise it adds __exit section annotations to their unbind() routines. - -The specification of the gadget driver register/unregister functions is -updated to explicitly allow use of those sections. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/ether.c | 4 ++-- - drivers/usb/gadget/file_storage.c | 4 ++-- - drivers/usb/gadget/serial.c | 6 +++--- - drivers/usb/gadget/zero.c | 6 +++--- - include/linux/usb_gadget.h | 7 +++++-- - 5 files changed, 15 insertions(+), 12 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/ether.c -+++ gregkh-2.6/drivers/usb/gadget/ether.c -@@ -2125,7 +2125,7 @@ eth_req_free (struct usb_ep *ep, struct - } - - --static void -+static void __exit - eth_unbind (struct usb_gadget *gadget) - { - struct eth_dev *dev = get_gadget_data (gadget); -@@ -2532,7 +2532,7 @@ static struct usb_gadget_driver eth_driv - - .function = (char *) driver_desc, - .bind = eth_bind, -- .unbind = eth_unbind, -+ .unbind = __exit_p(eth_unbind), - - .setup = eth_setup, - .disconnect = eth_disconnect, ---- gregkh-2.6.orig/drivers/usb/gadget/file_storage.c -+++ gregkh-2.6/drivers/usb/gadget/file_storage.c -@@ -3678,7 +3678,7 @@ static void lun_release(struct device *d - kref_put(&fsg->ref, fsg_release); - } - --static void fsg_unbind(struct usb_gadget *gadget) -+static void __exit fsg_unbind(struct usb_gadget *gadget) - { - struct fsg_dev *fsg = get_gadget_data(gadget); - int i; -@@ -4064,7 +4064,7 @@ static struct usb_gadget_driver fsg_dri - #endif - .function = (char *) longname, - .bind = fsg_bind, -- .unbind = fsg_unbind, -+ .unbind = __exit_p(fsg_unbind), - .disconnect = fsg_disconnect, - .setup = fsg_setup, - .suspend = fsg_suspend, ---- gregkh-2.6.orig/drivers/usb/gadget/serial.c -+++ gregkh-2.6/drivers/usb/gadget/serial.c -@@ -369,7 +369,7 @@ static struct usb_gadget_driver gs_gadge - #endif /* CONFIG_USB_GADGET_DUALSPEED */ - .function = GS_LONG_NAME, - .bind = gs_bind, -- .unbind = gs_unbind, -+ .unbind = __exit_p(gs_unbind), - .setup = gs_setup, - .disconnect = gs_disconnect, - .driver = { -@@ -1413,7 +1413,7 @@ requeue: - * Called on module load. Allocates and initializes the device - * structure and a control request. - */ --static int gs_bind(struct usb_gadget *gadget) -+static int __init gs_bind(struct usb_gadget *gadget) - { - int ret; - struct usb_ep *ep; -@@ -1538,7 +1538,7 @@ autoconf_fail: - * Called on module unload. Frees the control request and device - * structure. - */ --static void gs_unbind(struct usb_gadget *gadget) -+static void __exit gs_unbind(struct usb_gadget *gadget) - { - struct gs_dev *dev = get_gadget_data(gadget); - ---- gregkh-2.6.orig/drivers/usb/gadget/zero.c -+++ gregkh-2.6/drivers/usb/gadget/zero.c -@@ -1119,7 +1119,7 @@ zero_autoresume (unsigned long _dev) - - /*-------------------------------------------------------------------------*/ - --static void -+static void __exit - zero_unbind (struct usb_gadget *gadget) - { - struct zero_dev *dev = get_gadget_data (gadget); -@@ -1136,7 +1136,7 @@ zero_unbind (struct usb_gadget *gadget) - set_gadget_data (gadget, NULL); - } - --static int -+static int __init - zero_bind (struct usb_gadget *gadget) - { - struct zero_dev *dev; -@@ -1288,7 +1288,7 @@ static struct usb_gadget_driver zero_dri - #endif - .function = (char *) longname, - .bind = zero_bind, -- .unbind = zero_unbind, -+ .unbind = __exit_p(zero_unbind), - - .setup = zero_setup, - .disconnect = zero_disconnect, ---- gregkh-2.6.orig/include/linux/usb_gadget.h -+++ gregkh-2.6/include/linux/usb_gadget.h -@@ -801,7 +801,9 @@ struct usb_gadget_driver { - * Call this in your gadget driver's module initialization function, - * to tell the underlying usb controller driver about your driver. - * The driver's bind() function will be called to bind it to a -- * gadget. This function must be called in a context that can sleep. -+ * gadget before this registration call returns. It's expected that -+ * the bind() functions will be in init sections. -+ * This function must be called in a context that can sleep. - */ - int usb_gadget_register_driver (struct usb_gadget_driver *driver); - -@@ -814,7 +816,8 @@ int usb_gadget_register_driver (struct u - * going away. If the controller is connected to a USB host, - * it will first disconnect(). The driver is also requested - * to unbind() and clean up any device state, before this procedure -- * finally returns. -+ * finally returns. It's expected that the unbind() functions -+ * will in in exit sections, so may not be linked in some kernels. - * This function must be called in a context that can sleep. - */ - int usb_gadget_unregister_driver (struct usb_gadget_driver *driver); diff --git a/usb/usb-initdata-fixes.patch b/usb/usb-initdata-fixes.patch deleted file mode 100644 index e02037ee9504b..0000000000000 --- a/usb/usb-initdata-fixes.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: fix initdata issue in isp116x-hcd - -As found by Sam's scripts. - -Cc: Sam Ravnborg <sam@ravnborg.org> -Cc: David Brownell <david-b@pacbell.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/isp116x-hcd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/host/isp116x-hcd.c -+++ gregkh-2.6/drivers/usb/host/isp116x-hcd.c -@@ -1552,7 +1552,7 @@ static struct hc_driver isp116x_hc_drive - - /*----------------------------------------------------------------*/ - --static int __init_or_module isp116x_remove(struct platform_device *pdev) -+static int isp116x_remove(struct platform_device *pdev) - { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct isp116x *isp116x; diff --git a/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch b/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch deleted file mode 100644 index 4691e5d8f105b..0000000000000 --- a/usb/usb-kzalloc-conversion-for-rest-of-drivers-usb.patch +++ /dev/null @@ -1,690 +0,0 @@ -From snakebyte@gmx.de Mon Feb 27 12:29:47 2006 -From: Eric Sesterhenn <snakebyte@gmx.de> -To: Greg KH <gregkh@suse.de> -Cc: kernel-janitors@lists.osdl.org -Subject: USB: kzalloc() conversion for rest of drivers/usb -Date: Mon, 27 Feb 2006 21:29:43 +0100 -Message-Id: <1141072183.32324.0.camel@alice> - - -Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ehci-mem.c | 10 +++------- - drivers/usb/host/ehci-sched.c | 3 +-- - drivers/usb/host/hc_crisv10.c | 12 ++++-------- - drivers/usb/media/ov511.c | 4 +--- - drivers/usb/media/pwc/pwc-if.c | 3 +-- - drivers/usb/media/se401.c | 4 +--- - drivers/usb/media/stv680.c | 7 ++----- - drivers/usb/misc/auerswald.c | 6 ++---- - drivers/usb/misc/usblcd.c | 3 +-- - drivers/usb/misc/usbtest.c | 9 +++------ - drivers/usb/mon/mon_main.c | 3 +-- - drivers/usb/mon/mon_text.c | 3 +-- - drivers/usb/net/zd1201.c | 9 +++------ - drivers/usb/serial/cp2101.c | 4 +--- - drivers/usb/serial/cypress_m8.c | 3 +-- - drivers/usb/serial/ftdi_sio.c | 3 +-- - drivers/usb/serial/garmin_gps.c | 3 +-- - drivers/usb/serial/io_edgeport.c | 3 +-- - drivers/usb/serial/io_ti.c | 6 ++---- - drivers/usb/serial/ir-usb.c | 3 +-- - drivers/usb/serial/keyspan.c | 6 ++---- - drivers/usb/serial/kobil_sct.c | 16 +++++----------- - drivers/usb/serial/mct_u232.c | 3 +-- - drivers/usb/serial/option.c | 3 +-- - drivers/usb/serial/pl2303.c | 6 ++---- - drivers/usb/serial/ti_usb_3410_5052.c | 3 +-- - drivers/usb/serial/usb-serial.c | 6 ++---- - drivers/usb/serial/visor.c | 3 +-- - drivers/usb/storage/isd200.c | 2 +- - 29 files changed, 48 insertions(+), 101 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ehci-mem.c -+++ gregkh-2.6/drivers/usb/host/ehci-mem.c -@@ -220,13 +220,9 @@ static int ehci_mem_init (struct ehci_hc - ehci->periodic [i] = EHCI_LIST_END; - - /* software shadow of hardware table */ -- ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags); -- if (ehci->pshadow == NULL) { -- goto fail; -- } -- memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *)); -- -- return 0; -+ ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); -+ if (ehci->pshadow != NULL) -+ return 0; - - fail: - ehci_dbg (ehci, "couldn't init memory\n"); ---- gregkh-2.6.orig/drivers/usb/host/ehci-sched.c -+++ gregkh-2.6/drivers/usb/host/ehci-sched.c -@@ -864,9 +864,8 @@ iso_sched_alloc (unsigned packets, gfp_t - int size = sizeof *iso_sched; - - size += packets * sizeof (struct ehci_iso_packet); -- iso_sched = kmalloc (size, mem_flags); -+ iso_sched = kzalloc(size, mem_flags); - if (likely (iso_sched != NULL)) { -- memset(iso_sched, 0, size); - INIT_LIST_HEAD (&iso_sched->td_list); - } - return iso_sched; ---- gregkh-2.6.orig/drivers/usb/host/hc_crisv10.c -+++ gregkh-2.6/drivers/usb/host/hc_crisv10.c -@@ -2137,10 +2137,9 @@ static int etrax_usb_submit_bulk_urb(str - urb->status = -EINPROGRESS; - - /* Setup the hcpriv data. */ -- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); -+ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); - /* This sets rx_offset to 0. */ -- memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); - urb_priv->urb_state = NOT_STARTED; - urb->hcpriv = urb_priv; - -@@ -2475,10 +2474,9 @@ static int etrax_usb_submit_ctrl_urb(str - urb->status = -EINPROGRESS; - - /* Setup the hcpriv data. */ -- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); -+ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); - /* This sets rx_offset to 0. */ -- memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); - urb_priv->urb_state = NOT_STARTED; - urb->hcpriv = urb_priv; - -@@ -2767,9 +2765,8 @@ static void etrax_usb_add_to_intr_sb_lis - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - interval = urb->interval; - -- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); -+ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); -- memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); - urb->hcpriv = urb_priv; - - first_ep = &TxIntrEPList[0]; -@@ -2997,9 +2994,8 @@ static void etrax_usb_add_to_isoc_sb_lis - - prev_sb_desc = next_sb_desc = temp_sb_desc = NULL; - -- urb_priv = kmalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC); -+ urb_priv = kzalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC); - assert(urb_priv != NULL); -- memset(urb_priv, 0, sizeof(etrax_urb_priv_t)); - - urb->hcpriv = urb_priv; - urb_priv->epid = epid; ---- gregkh-2.6.orig/drivers/usb/media/ov511.c -+++ gregkh-2.6/drivers/usb/media/ov511.c -@@ -5686,13 +5686,11 @@ ov51x_probe(struct usb_interface *intf, - if (idesc->bInterfaceSubClass != 0x00) - return -ENODEV; - -- if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { -+ if ((ov = kzalloc(sizeof(*ov), GFP_KERNEL)) == NULL) { - err("couldn't kmalloc ov struct"); - goto error_out; - } - -- memset(ov, 0, sizeof(*ov)); -- - ov->dev = dev; - ov->iface = idesc->bInterfaceNumber; - ov->led_policy = led; ---- gregkh-2.6.orig/drivers/usb/media/pwc/pwc-if.c -+++ gregkh-2.6/drivers/usb/media/pwc/pwc-if.c -@@ -1867,12 +1867,11 @@ static int usb_pwc_probe(struct usb_inte - Info("Warning: more than 1 configuration available.\n"); - - /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ -- pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL); -+ pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL); - if (pdev == NULL) { - Err("Oops, could not allocate memory for pwc_device.\n"); - return -ENOMEM; - } -- memset(pdev, 0, sizeof(struct pwc_device)); - pdev->type = type_id; - pdev->vsize = default_size; - pdev->vframes = default_fps; ---- gregkh-2.6.orig/drivers/usb/media/se401.c -+++ gregkh-2.6/drivers/usb/media/se401.c -@@ -1345,13 +1345,11 @@ static int se401_probe(struct usb_interf - /* We found one */ - info("SE401 camera found: %s", camera_name); - -- if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { -+ if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { - err("couldn't kmalloc se401 struct"); - return -ENOMEM; - } - -- memset(se401, 0, sizeof(*se401)); -- - se401->dev = dev; - se401->iface = interface->bInterfaceNumber; - se401->camera_name = camera_name; ---- gregkh-2.6.orig/drivers/usb/media/stv680.c -+++ gregkh-2.6/drivers/usb/media/stv680.c -@@ -318,12 +318,11 @@ static int stv_init (struct usb_stv *stv - unsigned char *buffer; - unsigned long int bufsize; - -- buffer = kmalloc (40, GFP_KERNEL); -+ buffer = kzalloc (40, GFP_KERNEL); - if (buffer == NULL) { - PDEBUG (0, "STV(e): Out of (small buf) memory"); - return -1; - } -- memset (buffer, 0, 40); - udelay (100); - - /* set config 1, interface 0, alternate 0 */ -@@ -1388,14 +1387,12 @@ static int stv680_probe (struct usb_inte - goto error; - } - /* We found one */ -- if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { -+ if ((stv680 = kzalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { - PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); - retval = -ENOMEM; - goto error; - } - -- memset (stv680, 0, sizeof (*stv680)); -- - stv680->udev = dev; - stv680->camera_name = camera_name; - ---- gregkh-2.6.orig/drivers/usb/misc/auerswald.c -+++ gregkh-2.6/drivers/usb/misc/auerswald.c -@@ -570,10 +570,9 @@ static int auerchain_setup (pauerchain_t - - /* fill the list of free elements */ - for (;numElements; numElements--) { -- acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL); -+ acep = kzalloc(sizeof(auerchainelement_t), GFP_KERNEL); - if (!acep) - goto ac_fail; -- memset (acep, 0, sizeof (auerchainelement_t)); - INIT_LIST_HEAD (&acep->list); - list_add_tail (&acep->list, &acp->free_list); - } -@@ -761,10 +760,9 @@ static int auerbuf_setup (pauerbufctl_t - - /* fill the list of free elements */ - for (;numElements; numElements--) { -- bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL); -+ bep = kzalloc(sizeof(auerbuf_t), GFP_KERNEL); - if (!bep) - goto bl_fail; -- memset (bep, 0, sizeof (auerbuf_t)); - bep->list = bcp; - INIT_LIST_HEAD (&bep->buff_list); - bep->bufp = kmalloc (bufsize, GFP_KERNEL); ---- gregkh-2.6.orig/drivers/usb/misc/usblcd.c -+++ gregkh-2.6/drivers/usb/misc/usblcd.c -@@ -270,12 +270,11 @@ static int lcd_probe(struct usb_interfac - int retval = -ENOMEM; - - /* allocate memory for our device state and initialize it */ -- dev = kmalloc(sizeof(*dev), GFP_KERNEL); -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - err("Out of memory"); - goto error; - } -- memset(dev, 0x00, sizeof(*dev)); - kref_init(&dev->kref); - - dev->udev = usb_get_dev(interface_to_usbdev(interface)); ---- gregkh-2.6.orig/drivers/usb/misc/usbtest.c -+++ gregkh-2.6/drivers/usb/misc/usbtest.c -@@ -382,12 +382,11 @@ alloc_sglist (int nents, int max, int va - for (i = 0; i < nents; i++) { - char *buf; - -- buf = kmalloc (size, SLAB_KERNEL); -+ buf = kzalloc (size, SLAB_KERNEL); - if (!buf) { - free_sglist (sg, i); - return NULL; - } -- memset (buf, 0, size); - - /* kmalloc pages are always physically contiguous! */ - sg_init_one(&sg[i], buf, size); -@@ -842,10 +841,9 @@ test_ctrl_queue (struct usbtest_dev *dev - * as with bulk/intr sglists, sglen is the queue depth; it also - * controls which subtests run (more tests than sglen) or rerun. - */ -- urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL); -+ urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL); - if (!urb) - return -ENOMEM; -- memset (urb, 0, param->sglen * sizeof (struct urb *)); - for (i = 0; i < param->sglen; i++) { - int pipe = usb_rcvctrlpipe (udev, 0); - unsigned len; -@@ -1865,10 +1863,9 @@ usbtest_probe (struct usb_interface *int - } - #endif - -- dev = kmalloc (sizeof *dev, SLAB_KERNEL); -+ dev = kzalloc(sizeof(*dev), SLAB_KERNEL); - if (!dev) - return -ENOMEM; -- memset (dev, 0, sizeof *dev); - info = (struct usbtest_info *) id->driver_info; - dev->info = info; - init_MUTEX (&dev->sem); ---- gregkh-2.6.orig/drivers/usb/mon/mon_main.c -+++ gregkh-2.6/drivers/usb/mon/mon_main.c -@@ -277,9 +277,8 @@ static void mon_bus_init(struct dentry * - char name[NAMESZ]; - int rc; - -- if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) -+ if ((mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL) - goto err_alloc; -- memset(mbus, 0, sizeof(struct mon_bus)); - kref_init(&mbus->ref); - spin_lock_init(&mbus->lock); - INIT_LIST_HEAD(&mbus->r_list); ---- gregkh-2.6.orig/drivers/usb/mon/mon_text.c -+++ gregkh-2.6/drivers/usb/mon/mon_text.c -@@ -213,12 +213,11 @@ static int mon_text_open(struct inode *i - mbus = inode->u.generic_ip; - ubus = mbus->u_bus; - -- rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL); -+ rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL); - if (rp == NULL) { - rc = -ENOMEM; - goto err_alloc; - } -- memset(rp, 0, sizeof(struct mon_reader_text)); - INIT_LIST_HEAD(&rp->e_list); - init_waitqueue_head(&rp->wait); - mutex_init(&rp->printf_lock); ---- gregkh-2.6.orig/drivers/usb/net/zd1201.c -+++ gregkh-2.6/drivers/usb/net/zd1201.c -@@ -621,10 +621,9 @@ static int zd1201_drvr_start(struct zd12 - __le16 zdmax; - unsigned char *buffer; - -- buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL); -+ buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); - if (!buffer) - return -ENOMEM; -- memset(buffer, 0, ZD1201_RXSIZE); - - usb_fill_bulk_urb(zd->rx_urb, zd->usb, - usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, -@@ -1750,11 +1749,9 @@ static int zd1201_probe(struct usb_inter - - usb = interface_to_usbdev(interface); - -- zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL); -- if (!zd) { -+ zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); -+ if (!zd) - return -ENOMEM; -- } -- memset(zd, 0, sizeof(struct zd1201)); - zd->ap = ap; - zd->usb = usb; - zd->removed = 0; ---- gregkh-2.6.orig/drivers/usb/serial/cp2101.c -+++ gregkh-2.6/drivers/usb/serial/cp2101.c -@@ -169,9 +169,7 @@ static int cp2101_get_config(struct usb_ - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - -- buf = kmalloc (length * sizeof(u32), GFP_KERNEL); -- memset(buf, 0, length * sizeof(u32)); -- -+ buf = kcalloc(length, sizeof(u32), GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); - return -ENOMEM; ---- gregkh-2.6.orig/drivers/usb/serial/cypress_m8.c -+++ gregkh-2.6/drivers/usb/serial/cypress_m8.c -@@ -435,11 +435,10 @@ static int generic_startup (struct usb_s - - dbg("%s - port %d", __FUNCTION__, serial->port[0]->number); - -- priv = kmalloc(sizeof (struct cypress_private), GFP_KERNEL); -+ priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - -- memset(priv, 0x00, sizeof (struct cypress_private)); - spin_lock_init(&priv->lock); - priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE); - if (priv->buf == NULL) { ---- gregkh-2.6.orig/drivers/usb/serial/ftdi_sio.c -+++ gregkh-2.6/drivers/usb/serial/ftdi_sio.c -@@ -1141,12 +1141,11 @@ static int ftdi_sio_attach (struct usb_s - - dbg("%s",__FUNCTION__); - -- priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); -+ priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL); - if (!priv){ - err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private)); - return -ENOMEM; - } -- memset(priv, 0, sizeof(*priv)); - - spin_lock_init(&priv->rx_lock); - init_waitqueue_head(&priv->delta_msr_wait); ---- gregkh-2.6.orig/drivers/usb/serial/garmin_gps.c -+++ gregkh-2.6/drivers/usb/serial/garmin_gps.c -@@ -1422,12 +1422,11 @@ static int garmin_attach (struct usb_ser - - dbg("%s", __FUNCTION__); - -- garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); -+ garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); - if (garmin_data_p == NULL) { - dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset (garmin_data_p, 0, sizeof(struct garmin_data)); - init_timer(&garmin_data_p->timer); - spin_lock_init(&garmin_data_p->lock); - INIT_LIST_HEAD(&garmin_data_p->pktlist); ---- gregkh-2.6.orig/drivers/usb/serial/io_edgeport.c -+++ gregkh-2.6/drivers/usb/serial/io_edgeport.c -@@ -2725,12 +2725,11 @@ static int edge_startup (struct usb_seri - dev = serial->dev; - - /* create our private serial structure */ -- edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); -+ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); - if (edge_serial == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset (edge_serial, 0, sizeof(struct edgeport_serial)); - spin_lock_init(&edge_serial->es_lock); - edge_serial->serial = serial; - usb_set_serial_data(serial, edge_serial); ---- gregkh-2.6.orig/drivers/usb/serial/io_ti.c -+++ gregkh-2.6/drivers/usb/serial/io_ti.c -@@ -2727,12 +2727,11 @@ static int edge_startup (struct usb_seri - dev = serial->dev; - - /* create our private serial structure */ -- edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); -+ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); - if (edge_serial == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset (edge_serial, 0, sizeof(struct edgeport_serial)); - sema_init(&edge_serial->es_sem, 1); - edge_serial->serial = serial; - usb_set_serial_data(serial, edge_serial); -@@ -2745,12 +2744,11 @@ static int edge_startup (struct usb_seri - - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { -- edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); -+ edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); - goto cleanup; - } -- memset (edge_port, 0, sizeof(struct edgeport_port)); - spin_lock_init(&edge_port->ep_lock); - edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE); - if (edge_port->ep_out_buf == NULL) { ---- gregkh-2.6.orig/drivers/usb/serial/ir-usb.c -+++ gregkh-2.6/drivers/usb/serial/ir-usb.c -@@ -184,10 +184,9 @@ static struct irda_class_desc *irda_usb_ - struct irda_class_desc *desc; - int ret; - -- desc = kmalloc(sizeof (struct irda_class_desc), GFP_KERNEL); -+ desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL); - if (desc == NULL) - return NULL; -- memset(desc, 0, sizeof(struct irda_class_desc)); - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), - IU_REQ_GET_CLASS_DESC, ---- gregkh-2.6.orig/drivers/usb/serial/keyspan.c -+++ gregkh-2.6/drivers/usb/serial/keyspan.c -@@ -2250,12 +2250,11 @@ static int keyspan_startup (struct usb_s - } - - /* Setup private data for serial driver */ -- s_priv = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); -+ s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); - if (!s_priv) { - dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__); - return -ENOMEM; - } -- memset(s_priv, 0, sizeof(struct keyspan_serial_private)); - - s_priv->device_details = d_details; - usb_set_serial_data(serial, s_priv); -@@ -2263,12 +2262,11 @@ static int keyspan_startup (struct usb_s - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; -- p_priv = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); -+ p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); - if (!p_priv) { - dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i); - return (1); - } -- memset(p_priv, 0, sizeof(struct keyspan_port_private)); - p_priv->device_details = d_details; - usb_set_serial_port_data(port, p_priv); - } ---- gregkh-2.6.orig/drivers/usb/serial/kobil_sct.c -+++ gregkh-2.6/drivers/usb/serial/kobil_sct.c -@@ -255,11 +255,9 @@ static int kobil_open (struct usb_serial - } - - // allocate memory for transfer buffer -- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); -+ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (! transfer_buffer) { - return -ENOMEM; -- } else { -- memset(transfer_buffer, 0, transfer_buffer_length); - } - - // allocate write_urb -@@ -383,11 +381,10 @@ static void kobil_read_int_callback( str - - // BEGIN DEBUG - /* -- dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); -+ dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); - if (! dbg_data) { - return; - } -- memset(dbg_data, 0, (3 * purb->actual_length + 10)); - for (i = 0; i < purb->actual_length; i++) { - sprintf(dbg_data +3*i, "%02X ", data[i]); - } -@@ -518,11 +515,10 @@ static int kobil_tiocmget(struct usb_ser - } - - // allocate memory for transfer buffer -- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); -+ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (!transfer_buffer) { - return -ENOMEM; - } -- memset(transfer_buffer, 0, transfer_buffer_length); - - result = usb_control_msg( port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0 ), -@@ -564,11 +560,10 @@ static int kobil_tiocmset(struct usb_se - } - - // allocate memory for transfer buffer -- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); -+ transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); - if (! transfer_buffer) { - return -ENOMEM; - } -- memset(transfer_buffer, 0, transfer_buffer_length); - - if (set & TIOCM_RTS) - rts = 1; -@@ -655,11 +650,10 @@ static int kobil_ioctl(struct usb_seria - (struct termios __user *)arg)) - return -EFAULT; - -- settings = (unsigned char *) kmalloc(50, GFP_KERNEL); -+ settings = kzalloc(50, GFP_KERNEL); - if (! settings) { - return -ENOBUFS; - } -- memset(settings, 0, 50); - - switch (priv->internal_termios.c_cflag & CBAUD) { - case B1200: ---- gregkh-2.6.orig/drivers/usb/serial/mct_u232.c -+++ gregkh-2.6/drivers/usb/serial/mct_u232.c -@@ -348,10 +348,9 @@ static int mct_u232_startup (struct usb_ - struct mct_u232_private *priv; - struct usb_serial_port *port, *rport; - -- priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL); -+ priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; -- memset(priv, 0, sizeof(struct mct_u232_private)); - spin_lock_init(&priv->lock); - usb_set_serial_port_data(serial->port[0], priv); - ---- gregkh-2.6.orig/drivers/usb/serial/option.c -+++ gregkh-2.6/drivers/usb/serial/option.c -@@ -631,13 +631,12 @@ static int option_startup(struct usb_ser - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; -- portdata = kmalloc(sizeof(*portdata), GFP_KERNEL); -+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dbg("%s: kmalloc for option_port_private (%d) failed!.", - __FUNCTION__, i); - return (1); - } -- memset(portdata, 0, sizeof(struct option_port_private)); - - usb_set_serial_port_data(port, portdata); - ---- gregkh-2.6.orig/drivers/usb/serial/pl2303.c -+++ gregkh-2.6/drivers/usb/serial/pl2303.c -@@ -218,10 +218,9 @@ static int pl2303_startup (struct usb_se - dbg("device type: %d", type); - - for (i = 0; i < serial->num_ports; ++i) { -- priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); -+ priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); - if (!priv) - goto cleanup; -- memset (priv, 0x00, sizeof (struct pl2303_private)); - spin_lock_init(&priv->lock); - priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); - if (priv->buf == NULL) { -@@ -383,12 +382,11 @@ static void pl2303_set_termios (struct u - } - } - -- buf = kmalloc (7, GFP_KERNEL); -+ buf = kzalloc (7, GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__); - return; - } -- memset (buf, 0x00, 0x07); - - i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0), - GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, ---- gregkh-2.6.orig/drivers/usb/serial/ti_usb_3410_5052.c -+++ gregkh-2.6/drivers/usb/serial/ti_usb_3410_5052.c -@@ -416,12 +416,11 @@ static int ti_startup(struct usb_serial - dev->actconfig->desc.bConfigurationValue); - - /* create device structure */ -- tdev = kmalloc(sizeof(struct ti_device), GFP_KERNEL); -+ tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL); - if (tdev == NULL) { - dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset(tdev, 0, sizeof(struct ti_device)); - sema_init(&tdev->td_open_close_sem, 1); - tdev->td_serial = serial; - usb_set_serial_data(serial, tdev); ---- gregkh-2.6.orig/drivers/usb/serial/usb-serial.c -+++ gregkh-2.6/drivers/usb/serial/usb-serial.c -@@ -564,12 +564,11 @@ static struct usb_serial * create_serial - { - struct usb_serial *serial; - -- serial = kmalloc (sizeof (*serial), GFP_KERNEL); -+ serial = kzalloc(sizeof(*serial), GFP_KERNEL); - if (!serial) { - dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); - return NULL; - } -- memset (serial, 0, sizeof(*serial)); - serial->dev = usb_get_dev(dev); - serial->type = driver; - serial->interface = interface; -@@ -778,10 +777,9 @@ int usb_serial_probe(struct usb_interfac - serial->num_port_pointers = max_endpoints; - dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints); - for (i = 0; i < max_endpoints; ++i) { -- port = kmalloc(sizeof(struct usb_serial_port), GFP_KERNEL); -+ port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); - if (!port) - goto probe_error; -- memset(port, 0x00, sizeof(struct usb_serial_port)); - port->number = i + serial->minor; - port->serial = serial; - spin_lock_init(&port->lock); ---- gregkh-2.6.orig/drivers/usb/serial/visor.c -+++ gregkh-2.6/drivers/usb/serial/visor.c -@@ -763,10 +763,9 @@ static int generic_startup(struct usb_se - int i; - - for (i = 0; i < serial->num_ports; ++i) { -- priv = kmalloc (sizeof(*priv), GFP_KERNEL); -+ priv = kzalloc (sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -- memset (priv, 0x00, sizeof(*priv)); - spin_lock_init(&priv->lock); - usb_set_serial_port_data(serial->port[i], priv); - } ---- gregkh-2.6.orig/drivers/usb/storage/isd200.c -+++ gregkh-2.6/drivers/usb/storage/isd200.c -@@ -1382,7 +1382,7 @@ static int isd200_init_info(struct us_da - } else - US_DEBUGP("ERROR - kmalloc failure\n"); - -- return(retStatus); -+ return retStatus; - } - - /************************************************************************** diff --git a/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch b/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch deleted file mode 100644 index e5d034766505f..0000000000000 --- a/usb/usb-kzalloc-conversion-in-drivers-usb-gadget.patch +++ /dev/null @@ -1,186 +0,0 @@ -From david-b@pacbell.net Mon Feb 27 13:34:15 2006 -From: Eric Sesterhenn <snakebyte@gmx.de> -Subject: USB: kzalloc() conversion in drivers/usb/gadget -Date: Mon, 27 Feb 2006 13:34:10 -0800 -To: Greg KH <greg@kroah.com> -Cc: Eric Sesterhenn <snakebyte@gmx.de> -Content-Disposition: inline -Message-Id: <200602271334.10698.david-b@pacbell.net> - -this patch converts drivers/usb to kzalloc usage. -Compile tested with allyes config. - -I think there was a bug in drivers/usb/gadget/inode.c because -it used sizeof(*data) for the kmalloc() and sizeof(data) for -the memset(), since sizeof(data) just returns the size for a pointer. - -Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/dummy_hcd.c | 3 +-- - drivers/usb/gadget/goku_udc.c | 3 +-- - drivers/usb/gadget/inode.c | 6 ++---- - drivers/usb/gadget/lh7a40x_udc.c | 3 +-- - drivers/usb/gadget/net2280.c | 3 +-- - drivers/usb/gadget/omap_udc.c | 6 ++---- - drivers/usb/gadget/pxa2xx_udc.c | 3 +-- - drivers/usb/gadget/serial.c | 3 +-- - drivers/usb/gadget/zero.c | 3 +-- - 9 files changed, 11 insertions(+), 22 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/dummy_hcd.c -+++ gregkh-2.6/drivers/usb/gadget/dummy_hcd.c -@@ -478,10 +478,9 @@ dummy_alloc_request (struct usb_ep *_ep, - return NULL; - ep = usb_ep_to_dummy_ep (_ep); - -- req = kmalloc (sizeof *req, mem_flags); -+ req = kzalloc(sizeof(*req), mem_flags); - if (!req) - return NULL; -- memset (req, 0, sizeof *req); - INIT_LIST_HEAD (&req->queue); - return &req->req; - } ---- gregkh-2.6.orig/drivers/usb/gadget/goku_udc.c -+++ gregkh-2.6/drivers/usb/gadget/goku_udc.c -@@ -275,11 +275,10 @@ goku_alloc_request(struct usb_ep *_ep, g - - if (!_ep) - return NULL; -- req = kmalloc(sizeof *req, gfp_flags); -+ req = kzalloc(sizeof *req, gfp_flags); - if (!req) - return NULL; - -- memset(req, 0, sizeof *req); - req->req.dma = DMA_ADDR_INVALID; - INIT_LIST_HEAD(&req->queue); - return &req->req; ---- gregkh-2.6.orig/drivers/usb/gadget/inode.c -+++ gregkh-2.6/drivers/usb/gadget/inode.c -@@ -170,10 +170,9 @@ static struct dev_data *dev_new (void) - { - struct dev_data *dev; - -- dev = kmalloc (sizeof *dev, GFP_KERNEL); -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; -- memset (dev, 0, sizeof *dev); - dev->state = STATE_DEV_DISABLED; - atomic_set (&dev->count, 1); - spin_lock_init (&dev->lock); -@@ -1592,10 +1591,9 @@ static int activate_ep_files (struct dev - gadget_for_each_ep (ep, dev->gadget) { - struct ep_data *data; - -- data = kmalloc (sizeof *data, GFP_KERNEL); -+ data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - goto enomem; -- memset (data, 0, sizeof data); - data->state = STATE_EP_DISABLED; - init_MUTEX (&data->lock); - init_waitqueue_head (&data->wait); ---- gregkh-2.6.orig/drivers/usb/gadget/lh7a40x_udc.c -+++ gregkh-2.6/drivers/usb/gadget/lh7a40x_udc.c -@@ -1114,11 +1114,10 @@ static struct usb_request *lh7a40x_alloc - - DEBUG("%s, %p\n", __FUNCTION__, ep); - -- req = kmalloc(sizeof *req, gfp_flags); -+ req = kzalloc(sizeof(*req), gfp_flags); - if (!req) - return 0; - -- memset(req, 0, sizeof *req); - INIT_LIST_HEAD(&req->queue); - - return &req->req; ---- gregkh-2.6.orig/drivers/usb/gadget/net2280.c -+++ gregkh-2.6/drivers/usb/gadget/net2280.c -@@ -386,11 +386,10 @@ net2280_alloc_request (struct usb_ep *_e - return NULL; - ep = container_of (_ep, struct net2280_ep, ep); - -- req = kmalloc (sizeof *req, gfp_flags); -+ req = kzalloc(sizeof(*req), gfp_flags); - if (!req) - return NULL; - -- memset (req, 0, sizeof *req); - req->req.dma = DMA_ADDR_INVALID; - INIT_LIST_HEAD (&req->queue); - ---- gregkh-2.6.orig/drivers/usb/gadget/omap_udc.c -+++ gregkh-2.6/drivers/usb/gadget/omap_udc.c -@@ -273,9 +273,8 @@ omap_alloc_request(struct usb_ep *ep, gf - { - struct omap_req *req; - -- req = kmalloc(sizeof *req, gfp_flags); -+ req = kzalloc(sizeof(*req), gfp_flags); - if (req) { -- memset (req, 0, sizeof *req); - req->req.dma = DMA_ADDR_INVALID; - INIT_LIST_HEAD (&req->queue); - } -@@ -2586,11 +2585,10 @@ omap_udc_setup(struct platform_device *o - /* UDC_PULLUP_EN gates the chip clock */ - // OTG_SYSCON_1_REG |= DEV_IDLE_EN; - -- udc = kmalloc (sizeof *udc, SLAB_KERNEL); -+ udc = kzalloc(sizeof(*udc), SLAB_KERNEL); - if (!udc) - return -ENOMEM; - -- memset(udc, 0, sizeof *udc); - spin_lock_init (&udc->lock); - - udc->gadget.ops = &omap_gadget_ops; ---- gregkh-2.6.orig/drivers/usb/gadget/pxa2xx_udc.c -+++ gregkh-2.6/drivers/usb/gadget/pxa2xx_udc.c -@@ -335,11 +335,10 @@ pxa2xx_ep_alloc_request (struct usb_ep * - { - struct pxa2xx_request *req; - -- req = kmalloc (sizeof *req, gfp_flags); -+ req = kzalloc(sizeof(*req), gfp_flags); - if (!req) - return NULL; - -- memset (req, 0, sizeof *req); - INIT_LIST_HEAD (&req->queue); - return &req->req; - } ---- gregkh-2.6.orig/drivers/usb/gadget/serial.c -+++ gregkh-2.6/drivers/usb/gadget/serial.c -@@ -2178,10 +2178,9 @@ static int gs_alloc_ports(struct gs_dev - return -EIO; - - for (i=0; i<GS_NUM_PORTS; i++) { -- if ((port=(struct gs_port *)kmalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL) -+ if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL) - return -ENOMEM; - -- memset(port, 0, sizeof(struct gs_port)); - port->port_dev = dev; - port->port_num = i; - port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE); ---- gregkh-2.6.orig/drivers/usb/gadget/zero.c -+++ gregkh-2.6/drivers/usb/gadget/zero.c -@@ -1188,10 +1188,9 @@ autoconf_fail: - - - /* ok, we made sense of the hardware ... */ -- dev = kmalloc (sizeof *dev, SLAB_KERNEL); -+ dev = kzalloc(sizeof(*dev), SLAB_KERNEL); - if (!dev) - return -ENOMEM; -- memset (dev, 0, sizeof *dev); - spin_lock_init (&dev->lock); - dev->gadget = gadget; - set_gadget_data (gadget, dev); diff --git a/usb/usb-kzalloc-for-hid.patch b/usb/usb-kzalloc-for-hid.patch deleted file mode 100644 index 3e38e45f75821..0000000000000 --- a/usb/usb-kzalloc-for-hid.patch +++ /dev/null @@ -1,150 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:50:01 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Michael Haboustak <mike-@cinci.rr.com>, Greg KH <gregkh@suse.de>, Vojtech Pavlik <vojtech@suse.cz>, dtor_core@ameritech.net -Content-Disposition: inline -Message-Id: <200601062054.30226.oliver@neukum.org> -Subject: USB: kzalloc for hid -Date: Fri, 6 Jan 2006 20:54:29 +0100 - -this uses kzalloc in hid. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/input/hid-core.c | 18 +++++------------- - drivers/usb/input/hid-lgff.c | 6 ++---- - drivers/usb/input/hid-tmff.c | 3 +-- - drivers/usb/input/hiddev.c | 6 ++---- - 4 files changed, 10 insertions(+), 23 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/input/hid-core.c -+++ gregkh-2.6/drivers/usb/input/hid-core.c -@@ -66,9 +66,8 @@ static struct hid_report *hid_register_r - if (report_enum->report_id_hash[id]) - return report_enum->report_id_hash[id]; - -- if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL))) -+ if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) - return NULL; -- memset(report, 0, sizeof(struct hid_report)); - - if (id != 0) - report_enum->numbered = 1; -@@ -97,12 +96,9 @@ static struct hid_field *hid_register_fi - return NULL; - } - -- if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) -+ if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) - + values * sizeof(unsigned), GFP_KERNEL))) return NULL; - -- memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage) -- + values * sizeof(unsigned)); -- - field->index = report->maxfield++; - report->field[field->index] = field; - field->usage = (struct hid_usage *)(field + 1); -@@ -651,17 +647,14 @@ static struct hid_device *hid_parse_repo - hid_parser_reserved - }; - -- if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL))) -+ if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL))) - return NULL; -- memset(device, 0, sizeof(struct hid_device)); - -- if (!(device->collection = kmalloc(sizeof(struct hid_collection) * -+ if (!(device->collection = kzalloc(sizeof(struct hid_collection) * - HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) { - kfree(device); - return NULL; - } -- memset(device->collection, 0, sizeof(struct hid_collection) * -- HID_DEFAULT_NUM_COLLECTIONS); - device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; - - for (i = 0; i < HID_REPORT_TYPES; i++) -@@ -675,13 +668,12 @@ static struct hid_device *hid_parse_repo - memcpy(device->rdesc, start, size); - device->rsize = size; - -- if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) { -+ if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { - kfree(device->rdesc); - kfree(device->collection); - kfree(device); - return NULL; - } -- memset(parser, 0, sizeof(struct hid_parser)); - parser->device = device; - - end = start + size; ---- gregkh-2.6.orig/drivers/usb/input/hid-lgff.c -+++ gregkh-2.6/drivers/usb/input/hid-lgff.c -@@ -154,10 +154,9 @@ int hid_lgff_init(struct hid_device* hid - return -1; - } - -- private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); -+ private = kzalloc(sizeof(struct lgff_device), GFP_KERNEL); - if (!private) - return -1; -- memset(private, 0, sizeof(struct lgff_device)); - hid->ff_private = private; - - /* Input init */ -@@ -228,13 +227,12 @@ static struct hid_report* hid_lgff_dupli - } - *ret->field[0] = *report->field[0]; - -- ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL); -+ ret->field[0]->value = kzalloc(sizeof(s32[8]), GFP_KERNEL); - if (!ret->field[0]->value) { - kfree(ret->field[0]); - kfree(ret); - return NULL; - } -- memset(ret->field[0]->value, 0, sizeof(s32[8])); - - return ret; - } ---- gregkh-2.6.orig/drivers/usb/input/hid-tmff.c -+++ gregkh-2.6/drivers/usb/input/hid-tmff.c -@@ -113,11 +113,10 @@ int hid_tmff_init(struct hid_device *hid - struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct input_dev *input_dev = hidinput->input; - -- private = kmalloc(sizeof(struct tmff_device), GFP_KERNEL); -+ private = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); - if (!private) - return -ENOMEM; - -- memset(private, 0, sizeof(struct tmff_device)); - hid->ff_private = private; - - /* Find the report to use */ ---- gregkh-2.6.orig/drivers/usb/input/hiddev.c -+++ gregkh-2.6/drivers/usb/input/hiddev.c -@@ -257,9 +257,8 @@ static int hiddev_open(struct inode * in - if (i >= HIDDEV_MINORS || !hiddev_table[i]) - return -ENODEV; - -- if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL))) -+ if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) - return -ENOMEM; -- memset(list, 0, sizeof(struct hiddev_list)); - - list->hiddev = hiddev_table[i]; - list->next = hiddev_table[i]->list; -@@ -754,9 +753,8 @@ int hiddev_connect(struct hid_device *hi - if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) - return -1; - -- if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) -+ if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) - return -1; -- memset(hiddev, 0, sizeof(struct hiddev)); - - retval = usb_register_dev(hid->intf, &hiddev_class); - if (retval) { diff --git a/usb/usb-kzalloc-for-storage.patch b/usb/usb-kzalloc-for-storage.patch deleted file mode 100644 index e68e2afe52e2e..0000000000000 --- a/usb/usb-kzalloc-for-storage.patch +++ /dev/null @@ -1,112 +0,0 @@ -From oliver@neukum.org Sun Jan 8 03:34:01 2006 -From: Oliver Neukum <oliver@neukum.org> -To: mdharm-usb@one-eyed-alien.net, usb-storage@lists.one-eyed-alien.net, Greg KH <gregkh@suse.de> -Subject: USB: kzalloc for storage -Content-Disposition: inline -Date: Sun, 8 Jan 2006 12:33:45 +0100 -Message-Id: <200601081233.45552.oliver@neukum.org> - -another one for kzalloc. This covers the storage subdirectory. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/storage/datafab.c | 3 +-- - drivers/usb/storage/isd200.c | 8 +++----- - drivers/usb/storage/jumpshot.c | 3 +-- - drivers/usb/storage/sddr55.c | 3 +-- - drivers/usb/storage/shuttle_usbat.c | 3 +-- - 5 files changed, 7 insertions(+), 13 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/storage/datafab.c -+++ gregkh-2.6/drivers/usb/storage/datafab.c -@@ -512,13 +512,12 @@ int datafab_transport(struct scsi_cmnd * - }; - - if (!us->extra) { -- us->extra = kmalloc(sizeof(struct datafab_info), GFP_NOIO); -+ us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO); - if (!us->extra) { - US_DEBUGP("datafab_transport: Gah! " - "Can't allocate storage for Datafab info struct!\n"); - return USB_STOR_TRANSPORT_ERROR; - } -- memset(us->extra, 0, sizeof(struct datafab_info)); - us->extra_destructor = datafab_info_destructor; - ((struct datafab_info *)us->extra)->lun = -1; - } ---- gregkh-2.6.orig/drivers/usb/storage/isd200.c -+++ gregkh-2.6/drivers/usb/storage/isd200.c -@@ -1361,21 +1361,19 @@ static int isd200_init_info(struct us_da - struct isd200_info *info; - - info = (struct isd200_info *) -- kmalloc(sizeof(struct isd200_info), GFP_KERNEL); -+ kzalloc(sizeof(struct isd200_info), GFP_KERNEL); - if (!info) - retStatus = ISD200_ERROR; - else { -- memset(info, 0, sizeof(struct isd200_info)); - info->id = (struct hd_driveid *) -- kmalloc(sizeof(struct hd_driveid), GFP_KERNEL); -+ kzalloc(sizeof(struct hd_driveid), GFP_KERNEL); - info->RegsBuf = (unsigned char *) - kmalloc(sizeof(info->ATARegs), GFP_KERNEL); - if (!info->id || !info->RegsBuf) { - isd200_free_info_ptrs(info); - kfree(info); - retStatus = ISD200_ERROR; -- } else -- memset(info->id, 0, sizeof(struct hd_driveid)); -+ } - } - - if (retStatus == ISD200_GOOD) { ---- gregkh-2.6.orig/drivers/usb/storage/jumpshot.c -+++ gregkh-2.6/drivers/usb/storage/jumpshot.c -@@ -441,12 +441,11 @@ int jumpshot_transport(struct scsi_cmnd - }; - - if (!us->extra) { -- us->extra = kmalloc(sizeof(struct jumpshot_info), GFP_NOIO); -+ us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO); - if (!us->extra) { - US_DEBUGP("jumpshot_transport: Gah! Can't allocate storage for jumpshot info struct!\n"); - return USB_STOR_TRANSPORT_ERROR; - } -- memset(us->extra, 0, sizeof(struct jumpshot_info)); - us->extra_destructor = jumpshot_info_destructor; - } - ---- gregkh-2.6.orig/drivers/usb/storage/sddr55.c -+++ gregkh-2.6/drivers/usb/storage/sddr55.c -@@ -751,11 +751,10 @@ int sddr55_transport(struct scsi_cmnd *s - struct sddr55_card_info *info; - - if (!us->extra) { -- us->extra = kmalloc( -+ us->extra = kzalloc( - sizeof(struct sddr55_card_info), GFP_NOIO); - if (!us->extra) - return USB_STOR_TRANSPORT_ERROR; -- memset(us->extra, 0, sizeof(struct sddr55_card_info)); - us->extra_destructor = sddr55_card_info_destructor; - } - ---- gregkh-2.6.orig/drivers/usb/storage/shuttle_usbat.c -+++ gregkh-2.6/drivers/usb/storage/shuttle_usbat.c -@@ -1318,12 +1318,11 @@ int init_usbat(struct us_data *us) - unsigned char subcountL = USBAT_ATA_LBA_ME; - unsigned char *status = us->iobuf; - -- us->extra = kmalloc(sizeof(struct usbat_info), GFP_NOIO); -+ us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO); - if (!us->extra) { - US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n"); - return 1; - } -- memset(us->extra, 0, sizeof(struct usbat_info)); - info = (struct usbat_info *) (us->extra); - - /* Enable peripheral control signals */ diff --git a/usb/usb-kzalloc-in-cytherm.patch b/usb/usb-kzalloc-in-cytherm.patch deleted file mode 100644 index efadd4a6518c1..0000000000000 --- a/usb/usb-kzalloc-in-cytherm.patch +++ /dev/null @@ -1,34 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:28:33 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Erik Rigtorp <erkki@linux.nu> -Content-Disposition: inline -Message-Id: <200601062224.56945.oliver@neukum.org> -Subject: USB: kzalloc in cytherm -Date: Fri, 6 Jan 2006 22:24:56 +0100 - - -another one for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/cytherm.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/cytherm.c -+++ gregkh-2.6/drivers/usb/misc/cytherm.c -@@ -351,12 +351,11 @@ static int cytherm_probe(struct usb_inte - struct usb_cytherm *dev = NULL; - int retval = -ENOMEM; - -- dev = kmalloc (sizeof(struct usb_cytherm), GFP_KERNEL); -+ dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL); - if (dev == NULL) { - dev_err (&interface->dev, "Out of memory\n"); - goto error; - } -- memset (dev, 0x00, sizeof (*dev)); - - dev->udev = usb_get_dev(udev); - diff --git a/usb/usb-kzalloc-in-dabusb.patch b/usb/usb-kzalloc-in-dabusb.patch deleted file mode 100644 index c3480eb7aa171..0000000000000 --- a/usb/usb-kzalloc-in-dabusb.patch +++ /dev/null @@ -1,34 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:50:10 2006 -From: Oliver Neukum <oliver@neukum.org> -To: deti@fliegl.de -Content-Disposition: inline -Message-Id: <200601062101.47610.oliver@neukum.org> -Subject: USB: kzalloc in dabusb -Date: Fri, 6 Jan 2006 21:01:47 +0100 - -kzalloc in dabusb. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/media/dabusb.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/media/dabusb.c -+++ gregkh-2.6/drivers/usb/media/dabusb.c -@@ -217,12 +217,11 @@ static int dabusb_alloc_buffers (pdabusb - pipesize, packets, transfer_buffer_length); - - while (buffers < (s->total_buffer_size << 10)) { -- b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL); -+ b = (pbuff_t) kzalloc (sizeof (buff_t), GFP_KERNEL); - if (!b) { -- err("kmalloc(sizeof(buff_t))==NULL"); -+ err("kzalloc(sizeof(buff_t))==NULL"); - goto err; - } -- memset (b, 0, sizeof (buff_t)); - b->s = s; - b->purb = usb_alloc_urb(packets, GFP_KERNEL); - if (!b->purb) { diff --git a/usb/usb-kzalloc-in-idmouse.patch b/usb/usb-kzalloc-in-idmouse.patch deleted file mode 100644 index e76ea15893469..0000000000000 --- a/usb/usb-kzalloc-in-idmouse.patch +++ /dev/null @@ -1,32 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:39:07 2006 -From: Oliver Neukum <oliver@neukum.org> -To: echtler@fs.tum.de, aderesch@fs.tum.de -Content-Disposition: inline -Message-Id: <200601062236.27991.oliver@neukum.org> -Subject: USB: kzalloc in idmouse -Date: Fri, 6 Jan 2006 22:36:27 +0100 - - -another for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/idmouse.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/idmouse.c -+++ gregkh-2.6/drivers/usb/misc/idmouse.c -@@ -340,10 +340,9 @@ static int idmouse_probe(struct usb_inte - return -ENODEV; - - /* allocate memory for our device state and initialize it */ -- dev = kmalloc(sizeof(*dev), GFP_KERNEL); -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; -- memset(dev, 0x00, sizeof(*dev)); - - init_MUTEX(&dev->sem); - dev->udev = udev; diff --git a/usb/usb-kzalloc-in-ldusb.patch b/usb/usb-kzalloc-in-ldusb.patch deleted file mode 100644 index 334a4f2ef6985..0000000000000 --- a/usb/usb-kzalloc-in-ldusb.patch +++ /dev/null @@ -1,34 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:44:37 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Michael Hund <mhund@ld-didactic.de> -Content-Disposition: inline -Message-Id: <200601062240.02686.oliver@neukum.org> -Subject: USB: kzalloc in ldusb -Date: Fri, 6 Jan 2006 22:40:02 +0100 - - -another one for kzalloc - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/ldusb.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/ldusb.c -+++ gregkh-2.6/drivers/usb/misc/ldusb.c -@@ -626,12 +626,11 @@ static int ld_usb_probe(struct usb_inter - - /* allocate memory for our device state and intialize it */ - -- dev = kmalloc(sizeof(*dev), GFP_KERNEL); -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&intf->dev, "Out of memory\n"); - goto exit; - } -- memset(dev, 0x00, sizeof(*dev)); - init_MUTEX(&dev->sem); - dev->intf = intf; - init_waitqueue_head(&dev->read_wait); diff --git a/usb/usb-kzalloc-in-phidgetinterfacekit.patch b/usb/usb-kzalloc-in-phidgetinterfacekit.patch deleted file mode 100644 index 7b6c99c05ccf4..0000000000000 --- a/usb/usb-kzalloc-in-phidgetinterfacekit.patch +++ /dev/null @@ -1,68 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:44:40 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Sean Young <sean@mess.org> -Content-Disposition: inline -Message-Id: <200601062241.51664.oliver@neukum.org> -Subject: USB: kzalloc in PhidgetInterfaceKit -Date: Fri, 6 Jan 2006 22:41:51 +0100 - - -another for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/phidgetkit.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/phidgetkit.c -+++ gregkh-2.6/drivers/usb/misc/phidgetkit.c -@@ -88,7 +88,7 @@ static int change_outputs(struct phidget - int retval; - int n; - -- buffer = kmalloc(4, GFP_KERNEL); -+ buffer = kzalloc(4, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", - __FUNCTION__); -@@ -96,7 +96,6 @@ static int change_outputs(struct phidget - } - - kit->outputs[output_num] = enable; -- memset(buffer, 0, 4); - for (n=0; n<8; n++) { - if (kit->outputs[n]) { - buffer[0] |= 1 << n; -@@ -192,7 +191,7 @@ static ssize_t set_backlight(struct devi - unsigned char *buffer; - int retval = -ENOMEM; - -- buffer = kmalloc(8, GFP_KERNEL); -+ buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); - goto exit; -@@ -202,7 +201,6 @@ static ssize_t set_backlight(struct devi - retval = -EINVAL; - goto exit; - } -- memset(buffer, 0x00, 8); - if (enabled) - buffer[0] = 0x01; - buffer[7] = 0x11; -@@ -406,12 +404,11 @@ static int interfacekit_probe(struct usb - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - -- kit = kmalloc(sizeof(*kit), GFP_KERNEL); -+ kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (kit == NULL) { - dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset(kit, 0, sizeof(*kit)); - kit->ifkit = ifkit; - - kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma); diff --git a/usb/usb-kzalloc-in-phidgetservo.patch b/usb/usb-kzalloc-in-phidgetservo.patch deleted file mode 100644 index 35a312e1f07f5..0000000000000 --- a/usb/usb-kzalloc-in-phidgetservo.patch +++ /dev/null @@ -1,33 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:44:48 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Sean Young <sean@mess.org> -Content-Disposition: inline -Message-Id: <200601062243.33015.oliver@neukum.org> -Subject: USB: kzalloc in PhidgetServo -Date: Fri, 6 Jan 2006 22:43:32 +0100 - -another for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/phidgetservo.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/phidgetservo.c -+++ gregkh-2.6/drivers/usb/misc/phidgetservo.c -@@ -252,12 +252,11 @@ servo_probe(struct usb_interface *interf - struct usb_device *udev = interface_to_usbdev(interface); - struct phidget_servo *dev; - -- dev = kmalloc(sizeof (struct phidget_servo), GFP_KERNEL); -+ dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__); - return -ENOMEM; - } -- memset(dev, 0x00, sizeof (*dev)); - - dev->udev = usb_get_dev(udev); - dev->type = id->driver_info; diff --git a/usb/usb-kzalloc-in-sisusbvga.patch b/usb/usb-kzalloc-in-sisusbvga.patch deleted file mode 100644 index 395355e1b333f..0000000000000 --- a/usb/usb-kzalloc-in-sisusbvga.patch +++ /dev/null @@ -1,44 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 14:32:41 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Thomas Winischhofer <thomas@winischhofer.net> -Content-Disposition: inline -Message-Id: <200601062327.17654.oliver@neukum.org> -Subject: USB: kzalloc in sisusbvga -Date: Fri, 6 Jan 2006 23:27:17 +0100 - -this does two things: -- use kzalloc where appropriate -- correct error return codes in ioctl - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/sisusbvga/sisusb.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/sisusbvga/sisusb.c -+++ gregkh-2.6/drivers/usb/misc/sisusbvga/sisusb.c -@@ -3188,7 +3188,7 @@ sisusb_ioctl(struct inode *inode, struct - break; - - default: -- retval = -EINVAL; -+ retval = -ENOTTY; - break; - } - -@@ -3251,12 +3251,11 @@ static int sisusb_probe(struct usb_inter - dev->devnum); - - /* Allocate memory for our private */ -- if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) { -+ if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) { - printk(KERN_ERR - "sisusb: Failed to allocate memory for private data\n"); - return -ENOMEM; - } -- memset(sisusb, 0, sizeof(*sisusb)); - kref_init(&sisusb->kref); - - init_MUTEX(&(sisusb->lock)); diff --git a/usb/usb-kzalloc-in-usbled.patch b/usb/usb-kzalloc-in-usbled.patch deleted file mode 100644 index 8d15096d746b2..0000000000000 --- a/usb/usb-kzalloc-in-usbled.patch +++ /dev/null @@ -1,33 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 13:49:54 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Greg KH <gregkh@suse.de> -Content-Disposition: inline -Message-Id: <200601062244.52481.oliver@neukum.org> -Subject: USB: kzalloc in usbled -Date: Fri, 6 Jan 2006 22:44:52 +0100 - -another one for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/misc/usbled.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/misc/usbled.c -+++ gregkh-2.6/drivers/usb/misc/usbled.c -@@ -106,12 +106,11 @@ static int led_probe(struct usb_interfac - struct usb_led *dev = NULL; - int retval = -ENOMEM; - -- dev = kmalloc(sizeof(struct usb_led), GFP_KERNEL); -+ dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); - goto error; - } -- memset (dev, 0x00, sizeof (*dev)); - - dev->udev = usb_get_dev(udev); - diff --git a/usb/usb-kzalloc-in-usbvideo.patch b/usb/usb-kzalloc-in-usbvideo.patch deleted file mode 100644 index 5ee011ed54a46..0000000000000 --- a/usb/usb-kzalloc-in-usbvideo.patch +++ /dev/null @@ -1,35 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:52:07 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Greg KH <gregkh@suse.de> -Content-Disposition: inline -Message-Id: <200601062135.09101.oliver@neukum.org> -Subject: USB: kzalloc in usbvideo -Date: Fri, 6 Jan 2006 21:35:08 +0100 - -another for kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/media/usbvideo.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/media/usbvideo.c -+++ gregkh-2.6/drivers/usb/media/usbvideo.c -@@ -690,14 +690,13 @@ int usbvideo_register( - } - - base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo); -- cams = (struct usbvideo *) kmalloc(base_size, GFP_KERNEL); -+ cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL); - if (cams == NULL) { - err("Failed to allocate %d. bytes for usbvideo struct", base_size); - return -ENOMEM; - } - dbg("%s: Allocated $%p (%d. bytes) for %d. cameras", - __FUNCTION__, cams, base_size, num_cams); -- memset(cams, 0, base_size); - - /* Copy callbacks, apply defaults for those that are not set */ - memmove(&cams->cb, cbTbl, sizeof(cams->cb)); diff --git a/usb/usb-kzalloc-in-w9968cf.patch b/usb/usb-kzalloc-in-w9968cf.patch deleted file mode 100644 index 0b4e2370274db..0000000000000 --- a/usb/usb-kzalloc-in-w9968cf.patch +++ /dev/null @@ -1,73 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:51:54 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Luca Risolia <luca.risolia@studio.unibo.it>, Greg KH <gregkh@suse.de> -Content-Disposition: inline -Message-Id: <200601062128.41016.oliver@neukum.org> -Subject: USB: kzalloc in w9968cf -Date: Fri, 6 Jan 2006 21:28:40 +0100 - -another one for kzalloc. - - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/media/w9968cf.c | 13 ++++--------- - 1 file changed, 4 insertions(+), 9 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/media/w9968cf.c -+++ gregkh-2.6/drivers/usb/media/w9968cf.c -@@ -695,13 +695,12 @@ static int w9968cf_allocate_memory(struc - /* Allocate memory for the isochronous transfer buffers */ - for (i = 0; i < W9968CF_URBS; i++) { - if (!(cam->transfer_buffer[i] = -- kmalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { -+ kzalloc(W9968CF_ISO_PACKETS*p_size, GFP_KERNEL))) { - DBG(1, "Couldn't allocate memory for the isochronous " - "transfer buffers (%u bytes)", - p_size * W9968CF_ISO_PACKETS) - return -ENOMEM; - } -- memset(cam->transfer_buffer[i], 0, W9968CF_ISO_PACKETS*p_size); - } - - /* Allocate memory for the temporary frame buffer */ -@@ -3499,12 +3498,10 @@ w9968cf_usb_probe(struct usb_interface* - return -ENODEV; - - cam = (struct w9968cf_device*) -- kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL); -+ kzalloc(sizeof(struct w9968cf_device), GFP_KERNEL); - if (!cam) - return -ENOMEM; - -- memset(cam, 0, sizeof(*cam)); -- - init_MUTEX(&cam->dev_sem); - down(&cam->dev_sem); - -@@ -3532,21 +3529,19 @@ w9968cf_usb_probe(struct usb_interface* - - - /* Allocate 2 bytes of memory for camera control USB transfers */ -- if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) { -+ if (!(cam->control_buffer = kzalloc(2, GFP_KERNEL))) { - DBG(1,"Couldn't allocate memory for camera control transfers") - err = -ENOMEM; - goto fail; - } -- memset(cam->control_buffer, 0, 2); - - /* Allocate 8 bytes of memory for USB data transfers to the FSB */ -- if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) { -+ if (!(cam->data_buffer = kzalloc(8, GFP_KERNEL))) { - DBG(1, "Couldn't allocate memory for data " - "transfers to the FSB") - err = -ENOMEM; - goto fail; - } -- memset(cam->data_buffer, 0, 8); - - /* Register the V4L device */ - cam->v4ldev = video_device_alloc(); diff --git a/usb/usb-mdc800.c-to-kzalloc.patch b/usb/usb-mdc800.c-to-kzalloc.patch deleted file mode 100644 index 90afc0de6b16b..0000000000000 --- a/usb/usb-mdc800.c-to-kzalloc.patch +++ /dev/null @@ -1,35 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:49:49 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Henning Zabel <henning@uni-paderborn.de> -Content-Disposition: inline -Message-Id: <200601062045.11939.oliver@neukum.org> -Subject: USB: mdc800.c to kzalloc -Date: Fri, 6 Jan 2006 20:45:11 +0100 - - -one more conversion to kzalloc. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/image/mdc800.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/image/mdc800.c -+++ gregkh-2.6/drivers/usb/image/mdc800.c -@@ -978,13 +978,11 @@ static int __init usb_mdc800_init (void) - { - int retval = -ENODEV; - /* Allocate Memory */ -- mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL); -+ mdc800=kzalloc (sizeof (struct mdc800_data), GFP_KERNEL); - if (!mdc800) - goto cleanup_on_fail; - -- memset(mdc800, 0, sizeof(struct mdc800_data)); - mdc800->dev = NULL; -- mdc800->open=0; - mdc800->state=NOT_CONNECTED; - init_MUTEX (&mdc800->io_lock); - diff --git a/usb/usb-minor-gadget-rndis-tweak.patch b/usb/usb-minor-gadget-rndis-tweak.patch deleted file mode 100644 index e84a8f0194243..0000000000000 --- a/usb/usb-minor-gadget-rndis-tweak.patch +++ /dev/null @@ -1,30 +0,0 @@ -From david-b@pacbell.net Sun Jan 22 11:29:03 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: minor gadget/rndis tweak -Date: Sun, 22 Jan 2006 10:33:27 -0800 -Cc: Andrew Victor <andrew@sanpeople.com> -Message-Id: <200601221033.27776.david-b@pacbell.net> - -Resove a minor FIXME: don't change MTU while RNDIS link is active, -the other end won't expect such things... - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/gadget/ether.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/ether.c -+++ gregkh-2.6/drivers/usb/gadget/ether.c -@@ -1549,7 +1549,8 @@ static int eth_change_mtu (struct net_de - { - struct eth_dev *dev = netdev_priv(net); - -- // FIXME if rndis, don't change while link's live -+ if (dev->rndis) -+ return -EBUSY; - - if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN) - return -ERANGE; diff --git a/usb/usb-ohci-for-au1200.patch b/usb/usb-ohci-for-au1200.patch deleted file mode 100644 index c2f058ef71d61..0000000000000 --- a/usb/usb-ohci-for-au1200.patch +++ /dev/null @@ -1,241 +0,0 @@ -From david-b@pacbell.net Fri Jan 20 17:25:17 2006 -From: Jordan Crouse <jordan.crouse@amd.com> -To: Greg KH <greg@kroah.com> -Subject: USB: OHCI for AU1200 -Date: Fri, 20 Jan 2006 14:09:54 -0800 -Message-Id: <200601201409.54293.david-b@pacbell.net> - -ALCHEMY: Add OHCI support for AU1200 - -Updated by moving the OHCI support out of the EHCI patch. - -Signed-off-by: Jordan Crouse <jordan.crouse@amd.com> -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - arch/mips/au1000/common/platform.c | 2 - drivers/usb/host/ohci-au1xxx.c | 102 +++++++++++++++++++++++++++++++------ - 2 files changed, 88 insertions(+), 16 deletions(-) - ---- gregkh-2.6.orig/arch/mips/au1000/common/platform.c -+++ gregkh-2.6/arch/mips/au1000/common/platform.c -@@ -20,7 +20,7 @@ - static struct resource au1xxx_usb_ohci_resources[] = { - [0] = { - .start = USB_OHCI_BASE, -- .end = USB_OHCI_BASE + USB_OHCI_LEN, -+ .end = USB_OHCI_BASE + USB_OHCI_LEN - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { ---- gregkh-2.6.orig/drivers/usb/host/ohci-au1xxx.c -+++ gregkh-2.6/drivers/usb/host/ohci-au1xxx.c -@@ -23,6 +23,8 @@ - - #include <asm/mach-au1x00/au1000.h> - -+#ifndef CONFIG_SOC_AU1200 -+ - #define USBH_ENABLE_BE (1<<0) - #define USBH_ENABLE_C (1<<1) - #define USBH_ENABLE_E (1<<2) -@@ -37,21 +39,68 @@ - #error not byte order defined - #endif - -+#else /* Au1200 */ -+ -+#define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) -+#define USB_MCFG_PFEN (1<<31) -+#define USB_MCFG_RDCOMB (1<<30) -+#define USB_MCFG_SSDEN (1<<23) -+#define USB_MCFG_OHCCLKEN (1<<16) -+#define USB_MCFG_UCAM (1<<7) -+#define USB_MCFG_OBMEN (1<<1) -+#define USB_MCFG_OMEMEN (1<<0) -+ -+#define USBH_ENABLE_CE USB_MCFG_OHCCLKEN -+#ifdef CONFIG_DMA_COHERENT -+#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ -+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ -+ | USB_MCFG_SSDEN | USB_MCFG_UCAM \ -+ | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) -+#else -+#define USBH_ENABLE_INIT (USB_MCFG_OHCCLKEN \ -+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \ -+ | USB_MCFG_SSDEN \ -+ | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) -+#endif -+#define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) -+ -+#endif /* Au1200 */ -+ - extern int usb_disabled(void); - - /*-------------------------------------------------------------------------*/ - --static void au1xxx_start_hc(struct platform_device *dev) -+static void au1xxx_start_ohc(struct platform_device *dev) - { - printk(KERN_DEBUG __FILE__ - ": starting Au1xxx OHCI USB Controller\n"); - - /* enable host controller */ -+ -+#ifndef CONFIG_SOC_AU1200 -+ - au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); - udelay(1000); - au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); - udelay(1000); - -+#else /* Au1200 */ -+ -+ /* write HW defaults again in case Yamon cleared them */ -+ if (au_readl(USB_HOST_CONFIG) == 0) { -+ au_writel(0x00d02000, USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ } -+ au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+ udelay(1000); -+ -+#endif /* Au1200 */ -+ - /* wait for reset complete (read register twice; see au1500 errata) */ - while (au_readl(USB_HOST_CONFIG), - !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) -@@ -61,13 +110,25 @@ static void au1xxx_start_hc(struct platf - ": Clock to USB host has been enabled \n"); - } - --static void au1xxx_stop_hc(struct platform_device *dev) -+static void au1xxx_stop_ohc(struct platform_device *dev) - { - printk(KERN_DEBUG __FILE__ - ": stopping Au1xxx OHCI USB Controller\n"); - -+#ifndef CONFIG_SOC_AU1200 -+ - /* Disable clock */ - au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); -+ -+#else /* Au1200 */ -+ -+ /* Disable mem */ -+ au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ udelay(1000); -+ /* Disable clock */ -+ au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG); -+ au_readl(USB_HOST_CONFIG); -+#endif /* Au1200 */ - } - - -@@ -78,7 +139,7 @@ static void au1xxx_stop_hc(struct platfo - - - /** -- * usb_hcd_au1xxx_probe - initialize Au1xxx-based HCDs -+ * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs - * Context: !in_interrupt() - * - * Allocates basic resources for this USB host controller, and -@@ -86,14 +147,25 @@ static void au1xxx_stop_hc(struct platfo - * through the hotplug entry's driver_data. - * - */ --int usb_hcd_au1xxx_probe (const struct hc_driver *driver, -+static int usb_ohci_au1xxx_probe(const struct hc_driver *driver, - struct platform_device *dev) - { - int retval; - struct usb_hcd *hcd; - -- if(dev->resource[1].flags != IORESOURCE_IRQ) { -- pr_debug ("resource[1] is not IORESOURCE_IRQ"); -+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) -+ /* Au1200 AB USB does not support coherent memory */ -+ if (!(read_c0_prid() & 0xff)) { -+ pr_info("%s: this is chip revision AB !!\n", -+ dev->dev.name); -+ pr_info("%s: update your board or re-configure the kernel\n", -+ dev->dev.name); -+ return -ENODEV; -+ } -+#endif -+ -+ if (dev->resource[1].flags != IORESOURCE_IRQ) { -+ pr_debug("resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } - -@@ -104,26 +176,26 @@ int usb_hcd_au1xxx_probe (const struct h - hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { -- pr_debug("request_mem_region failed"); -+ pr_debug("request_mem_region failed\n"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { -- pr_debug("ioremap failed"); -+ pr_debug("ioremap failed\n"); - retval = -ENOMEM; - goto err2; - } - -- au1xxx_start_hc(dev); -+ au1xxx_start_ohc(dev); - ohci_hcd_init(hcd_to_ohci(hcd)); - -- retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); -+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT | SA_SHIRQ); - if (retval == 0) - return retval; - -- au1xxx_stop_hc(dev); -+ au1xxx_stop_ohc(dev); - iounmap(hcd->regs); - err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -@@ -146,10 +218,10 @@ int usb_hcd_au1xxx_probe (const struct h - * context, normally "rmmod", "apmd", or something similar. - * - */ --void usb_hcd_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev) -+static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev) - { - usb_remove_hcd(hcd); -- au1xxx_stop_hc(dev); -+ au1xxx_stop_ohc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -@@ -235,7 +307,7 @@ static int ohci_hcd_au1xxx_drv_probe(str - if (usb_disabled()) - return -ENODEV; - -- ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); -+ ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev); - return ret; - } - -@@ -243,7 +315,7 @@ static int ohci_hcd_au1xxx_drv_remove(st - { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - -- usb_hcd_au1xxx_remove(hcd, pdev); -+ usb_ohci_au1xxx_remove(hcd, pdev); - return 0; - } - /*TBD*/ diff --git a/usb/usb-ohci-uses-driver-model-wakeup-flags.patch b/usb/usb-ohci-uses-driver-model-wakeup-flags.patch deleted file mode 100644 index e9cbce5a0527f..0000000000000 --- a/usb/usb-ohci-uses-driver-model-wakeup-flags.patch +++ /dev/null @@ -1,228 +0,0 @@ -From david-b@pacbell.net Mon Jan 23 16:29:40 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: ohci uses driver model wakeup flags -Date: Mon, 23 Jan 2006 15:28:07 -0800 -Content-Disposition: inline -Message-Id: <200601231528.07476.david-b@pacbell.net> - -This makes OHCI use the driver model wakeup control bits for its root hub -(e.g. disable on amd756, because of chip erratum) and for the controller -itself. It no longer uses the hcd glue bits with those roles, and depends -on the previous patch making the root hub available earlier. - -Note that on most platforms (boot code properly setting the RWC bit) this -gives a partial workaround for the way PCI isn't currently flagging devices -that support PME# signals. (Because of odd PCI init sequencing on PPC.) -That's because many OHCI controllers support "legacy PCI PM" ... without -involving any PCI PM capability. - -USB wakeup from STR, if it works on your system, may still involve -tweaking things by hand in /proc/acpi/wakeup. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/ohci-hcd.c | 49 ++++++++++++++++++++++++-------------------- - drivers/usb/host/ohci-hub.c | 12 +++++----- - drivers/usb/host/ohci-pci.c | 15 +++++++++++-- - 3 files changed, 46 insertions(+), 30 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/host/ohci-hcd.c -+++ gregkh-2.6/drivers/usb/host/ohci-hcd.c -@@ -443,11 +443,16 @@ ohci_reboot (struct notifier_block *bloc - static int ohci_init (struct ohci_hcd *ohci) - { - int ret; -+ struct usb_hcd *hcd = ohci_to_hcd(ohci); - - disable (ohci); -- ohci->regs = ohci_to_hcd(ohci)->regs; -+ ohci->regs = hcd->regs; - ohci->next_statechange = jiffies; - -+ /* REVISIT this BIOS handshake is now moved into PCI "quirks", and -+ * was never needed for most non-PCI systems ... remove the code? -+ */ -+ - #ifndef IR_DISABLE - /* SMM owns the HC? not for long! */ - if (!no_handshake && ohci_readl (ohci, -@@ -478,8 +483,10 @@ static int ohci_init (struct ohci_hcd *o - - /* Disable HC interrupts */ - ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); -- // flush the writes -- (void) ohci_readl (ohci, &ohci->regs->control); -+ -+ /* flush the writes, and save key bits like RWC */ -+ if (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_RWC) -+ ohci->hc_control |= OHCI_CTRL_RWC; - - /* Read the number of ports unless overridden */ - if (ohci->num_ports == 0) -@@ -488,16 +495,19 @@ static int ohci_init (struct ohci_hcd *o - if (ohci->hcca) - return 0; - -- ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller, -+ ohci->hcca = dma_alloc_coherent (hcd->self.controller, - sizeof *ohci->hcca, &ohci->hcca_dma, 0); - if (!ohci->hcca) - return -ENOMEM; - - if ((ret = ohci_mem_init (ohci)) < 0) -- ohci_stop (ohci_to_hcd(ohci)); -+ ohci_stop (hcd); -+ else { -+ register_reboot_notifier (&ohci->reboot_notifier); -+ create_debug_files (ohci); -+ } - - return ret; -- - } - - /*-------------------------------------------------------------------------*/ -@@ -510,6 +520,7 @@ static int ohci_run (struct ohci_hcd *oh - { - u32 mask, temp; - int first = ohci->fminterval == 0; -+ struct usb_hcd *hcd = ohci_to_hcd(ohci); - - disable (ohci); - -@@ -525,18 +536,17 @@ static int ohci_run (struct ohci_hcd *oh - /* also: power/overcurrent flags in roothub.a */ - } - -- /* Reset USB nearly "by the book". RemoteWakeupConnected -- * saved if boot firmware (BIOS/SMM/...) told us it's connected -- * (for OHCI integrated on mainboard, it normally is) -+ /* Reset USB nearly "by the book". RemoteWakeupConnected was -+ * saved if boot firmware (BIOS/SMM/...) told us it's connected, -+ * or if bus glue did the same (e.g. for PCI add-in cards with -+ * PCI PM support). - */ -- ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); - ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), -- ohci->hc_control); -- -- if (ohci->hc_control & OHCI_CTRL_RWC -- && !(ohci->flags & OHCI_QUIRK_AMD756)) -- ohci_to_hcd(ohci)->can_wakeup = 1; -+ ohci_readl (ohci, &ohci->regs->control)); -+ if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 -+ && !device_may_wakeup(hcd->self.controller)) -+ device_init_wakeup(hcd->self.controller, 1); - - switch (ohci->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: -@@ -632,7 +642,7 @@ retry: - ohci->hc_control &= OHCI_CTRL_RWC; - ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); -- ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; -+ hcd->state = HC_STATE_RUNNING; - - /* wake on ConnectStatusChange, matching external hubs */ - ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); -@@ -667,15 +677,10 @@ retry: - - // POTPGT delay is bits 24-31, in 2 ms units. - mdelay ((temp >> 23) & 0x1fe); -- ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; -+ hcd->state = HC_STATE_RUNNING; - - ohci_dump (ohci, 1); - -- if (ohci_to_hcd(ohci)->self.root_hub == NULL) { -- register_reboot_notifier (&ohci->reboot_notifier); -- create_debug_files (ohci); -- } -- - return 0; - } - ---- gregkh-2.6.orig/drivers/usb/host/ohci-hub.c -+++ gregkh-2.6/drivers/usb/host/ohci-hub.c -@@ -107,7 +107,7 @@ static int ohci_bus_suspend (struct usb_ - &ohci->regs->intrstatus); - - /* maybe resume can wake root hub */ -- if (hcd->remote_wakeup) -+ if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev)) - ohci->hc_control |= OHCI_CTRL_RWE; - else - ohci->hc_control &= ~OHCI_CTRL_RWE; -@@ -246,9 +246,9 @@ static int ohci_bus_resume (struct usb_h - (void) ohci_readl (ohci, &ohci->regs->control); - msleep (3); - -- temp = OHCI_CONTROL_INIT | OHCI_USB_OPER; -- if (hcd->can_wakeup) -- temp |= OHCI_CTRL_RWC; -+ temp = ohci->hc_control; -+ temp &= OHCI_CTRL_RWC; -+ temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->hc_control = temp; - ohci_writel (ohci, temp, &ohci->regs->control); - (void) ohci_readl (ohci, &ohci->regs->control); -@@ -302,7 +302,7 @@ ohci_hub_status_data (struct usb_hcd *hc - { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int i, changed = 0, length = 1; -- int can_suspend = hcd->can_wakeup; -+ int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); - unsigned long flags; - - spin_lock_irqsave (&ohci->lock, flags); -@@ -354,7 +354,7 @@ ohci_hub_status_data (struct usb_hcd *hc - */ - if (!(status & RH_PS_CCS)) - continue; -- if ((status & RH_PS_PSS) && hcd->remote_wakeup) -+ if ((status & RH_PS_PSS) && can_suspend) - continue; - can_suspend = 0; - } ---- gregkh-2.6.orig/drivers/usb/host/ohci-pci.c -+++ gregkh-2.6/drivers/usb/host/ohci-pci.c -@@ -35,7 +35,10 @@ ohci_pci_start (struct usb_hcd *hcd) - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - -- if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { -+ /* REVISIT this whole block should move to reset(), which handles -+ * all the other one-time init. -+ */ -+ if (hcd->self.controller) { - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - - /* AMD 756, for most chips (early revs), corrupts register -@@ -45,7 +48,8 @@ ohci_pci_start (struct usb_hcd *hcd) - && pdev->device == 0x740c) { - ohci->flags = OHCI_QUIRK_AMD756; - ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); -- // also somewhat erratum 10 (suspend/resume issues) -+ /* also erratum 10 (suspend/resume issues) */ -+ device_init_wakeup(&hcd->self.root_hub->dev, 0); - } - - /* FIXME for some of the early AMD 760 southbridges, OHCI -@@ -88,6 +92,13 @@ ohci_pci_start (struct usb_hcd *hcd) - ohci_dbg (ohci, - "enabled Compaq ZFMicro chipset quirk\n"); - } -+ -+ /* RWC may not be set for add-in PCI cards, since boot -+ * firmware probably ignored them. This transfers PCI -+ * PM wakeup capabilities (once the PCI layer is fixed). -+ */ -+ if (device_may_wakeup(&pdev->dev)) -+ ohci->hc_control |= OHCI_CTRL_RWC; - } - - /* NOTE: there may have already been a first reset, to diff --git a/usb/usb-optimise-devio.c-usbdev_read-fix.patch b/usb/usb-optimise-devio.c-usbdev_read-fix.patch deleted file mode 100644 index 8a446cd0249f4..0000000000000 --- a/usb/usb-optimise-devio.c-usbdev_read-fix.patch +++ /dev/null @@ -1,43 +0,0 @@ -From akpm@osdl.org Wed Jan 18 23:55:40 2006 -Message-Id: <200601190755.k0J7tLRO027507@shell0.pdx.osdl.net> -From: Andrew Morton <akpm@osdl.org> -Subject: USB: optimise devio.c usbdev_read fix -To: greg@kroah.com -Cc: akpm@osdl.org, gregkh@suse.de, oliver@neukum.org, zaitcev@redhat.com -From: akpm@osdl.org -Date: Wed, 18 Jan 2006 23:55:07 -0800 - - -From: Andrew Morton <akpm@osdl.org> - -drivers/usb/core/devio.c: In function `usbdev_read': -drivers/usb/core/devio.c:140: error: invalid type argument of `->' -drivers/usb/core/devio.c:141: error: invalid type argument of `->' -drivers/usb/core/devio.c:142: error: invalid type argument of `->' -drivers/usb/core/devio.c:143: error: invalid type argument of `->' - -Cc: Oliver Neukum <oliver@neukum.org> -Cc: Pete Zaitcev <zaitcev@redhat.com> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/usb/core/devio.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/devio.c -+++ gregkh-2.6/drivers/usb/core/devio.c -@@ -137,10 +137,10 @@ static ssize_t usbdev_read(struct file * - struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */ - - memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); -- le16_to_cpus(&temp_desc->bcdUSB); -- le16_to_cpus(&temp_desc->idVendor); -- le16_to_cpus(&temp_desc->idProduct); -- le16_to_cpus(&temp_desc->bcdDevice); -+ le16_to_cpus(&temp_desc.bcdUSB); -+ le16_to_cpus(&temp_desc.idVendor); -+ le16_to_cpus(&temp_desc.idProduct); -+ le16_to_cpus(&temp_desc.bcdDevice); - - len = sizeof(struct usb_device_descriptor) - pos; - if (len > nbytes) diff --git a/usb/usb-optimise-devio.c-usbdev_read.patch b/usb/usb-optimise-devio.c-usbdev_read.patch deleted file mode 100644 index f7585a6bc75fa..0000000000000 --- a/usb/usb-optimise-devio.c-usbdev_read.patch +++ /dev/null @@ -1,56 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Fri Jan 6 12:51:44 2006 -From: Oliver Neukum <oliver@neukum.org> -To: Pete Zaitcev <zaitcev@redhat.com> -Subject: USB: optimise devio.c::usbdev_read -Cc: gregkh@suse.de -Content-Disposition: inline -Message-Id: <200601062124.25970.oliver@neukum.org> -Date: Fri, 6 Jan 2006 21:24:25 +0100 - -this is a small optimisation. It is ridiculous to do a kmalloc for -18 bytes. This puts it onto the stack. - -Signed-off-by: Oliver Neukum <oliver@neukum.name> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/devio.c | 21 ++++++++------------- - 1 file changed, 8 insertions(+), 13 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/devio.c -+++ gregkh-2.6/drivers/usb/core/devio.c -@@ -134,26 +134,21 @@ static ssize_t usbdev_read(struct file * - } - - if (pos < sizeof(struct usb_device_descriptor)) { -- struct usb_device_descriptor *desc = kmalloc(sizeof(*desc), GFP_KERNEL); -- if (!desc) { -- ret = -ENOMEM; -- goto err; -- } -- memcpy(desc, &dev->descriptor, sizeof(dev->descriptor)); -- le16_to_cpus(&desc->bcdUSB); -- le16_to_cpus(&desc->idVendor); -- le16_to_cpus(&desc->idProduct); -- le16_to_cpus(&desc->bcdDevice); -+ struct usb_device_descriptor temp_desc ; /* 18 bytes - fits on the stack */ -+ -+ memcpy(&temp_desc, &dev->descriptor, sizeof(dev->descriptor)); -+ le16_to_cpus(&temp_desc->bcdUSB); -+ le16_to_cpus(&temp_desc->idVendor); -+ le16_to_cpus(&temp_desc->idProduct); -+ le16_to_cpus(&temp_desc->bcdDevice); - - len = sizeof(struct usb_device_descriptor) - pos; - if (len > nbytes) - len = nbytes; -- if (copy_to_user(buf, ((char *)desc) + pos, len)) { -- kfree(desc); -+ if (copy_to_user(buf, ((char *)&temp_desc) + pos, len)) { - ret = -EFAULT; - goto err; - } -- kfree(desc); - - *ppos += len; - buf += len; diff --git a/usb/usb-pegasus-linksys-usbvpn1-support-cleanup.patch b/usb/usb-pegasus-linksys-usbvpn1-support-cleanup.patch deleted file mode 100644 index 1b44ddefdd396..0000000000000 --- a/usb/usb-pegasus-linksys-usbvpn1-support-cleanup.patch +++ /dev/null @@ -1,104 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Sat Jan 28 08:49:09 2006 -From: Malte Doersam <mdoersam@arcor.de> -Message-Id: <200601281748.33177.mdoersam@arcor.de> -Subject: USB: Pegasus: Linksys USBVPN1 support + cleanup -Date: Sat, 28 Jan 2006 17:48:33 +0100 - -This patch adds a second linksys vendor-id (077b) and the product id of the -pegasus based adapter USBVPN1 - -http://www1.linksys.com/Products/product.asp?prid=3D543&scid=3D30 - -Furthermore it replaces all LINKSYS_GPIO_RESET with DEFAULT_GPIO_RESET as both -are declared like this: -#define DEFAULT_GPIO_RESET 0x24 -#define LINKSYS_GPIO_RESET 0x24 - -This is misleading and confusing. -The check is now done via the VENDOR_ID in pegasus.c: -if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS - -Signed-off-by: Malte Doersam <mdoersam@arcor.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/usb/net/pegasus.c | 1 + - drivers/usb/net/pegasus.h | 26 ++++++++++++++------------ - 2 files changed, 15 insertions(+), 12 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/net/pegasus.c -+++ gregkh-2.6/drivers/usb/net/pegasus.c -@@ -524,6 +524,7 @@ static int enable_net_traffic(struct net - ret = set_registers(pegasus, EthCtrl0, 3, data); - - if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || -+ usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS2 || - usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { - u16 auxmode; - read_mii_word(pegasus, 0, 0x1b, &auxmode); ---- gregkh-2.6.orig/drivers/usb/net/pegasus.h -+++ gregkh-2.6/drivers/usb/net/pegasus.h -@@ -25,7 +25,6 @@ - #define PHY_READ 0x40 - #define PHY_WRITE 0x20 - #define DEFAULT_GPIO_RESET 0x24 --#define LINKSYS_GPIO_RESET 0x24 - #define DEFAULT_GPIO_SET 0x26 - - #define PEGASUS_PRESENT 0x00000001 -@@ -140,6 +139,7 @@ struct usb_eth_dev { - #define VENDOR_KINGSTON 0x0951 - #define VENDOR_LANEED 0x056e - #define VENDOR_LINKSYS 0x066b -+#define VENDOR_LINKSYS2 0x077b - #define VENDOR_MELCO 0x0411 - #define VENDOR_MICROSOFT 0x045e - #define VENDOR_MOBILITY 0x1342 -@@ -218,15 +218,15 @@ PEGASUS_DEV( "Corega FEter USB-TX", VEND - PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, - DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, -- LINKSYS_GPIO_RESET ) -+ DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002, -- LINKSYS_GPIO_RESET ) -+ DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102, -- LINKSYS_GPIO_RESET | PEGASUS_II ) -+ DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b, -- LINKSYS_GPIO_RESET | PEGASUS_II ) -+ DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c, -- LINKSYS_GPIO_RESET | PEGASUS_II ) -+ DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) - PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, -@@ -260,17 +260,19 @@ PEGASUS_DEV( "LANEED USB Ethernet LD-USB - PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c, - DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202, -- LINKSYS_GPIO_RESET ) -+ DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203, -- LINKSYS_GPIO_RESET ) -+ DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204, -- LINKSYS_GPIO_RESET | HAS_HOME_PNA ) -+ DEFAULT_GPIO_RESET | HAS_HOME_PNA ) - PEGASUS_DEV( "Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206, -- LINKSYS_GPIO_RESET | PEGASUS_II) -+ DEFAULT_GPIO_RESET | PEGASUS_II) -+PEGASUS_DEV( "Linksys USBVPN1", VENDOR_LINKSYS2, 0x08b4, -+ DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b, -- LINKSYS_GPIO_RESET | PEGASUS_II ) -+ DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c, -- LINKSYS_GPIO_RESET | PEGASUS_II ) -+ DEFAULT_GPIO_RESET | PEGASUS_II ) - PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001, - DEFAULT_GPIO_RESET ) - PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005, diff --git a/usb/usb-pl2303-and-tiocmiwait.patch b/usb/usb-pl2303-and-tiocmiwait.patch deleted file mode 100644 index 5319796e1a8e5..0000000000000 --- a/usb/usb-pl2303-and-tiocmiwait.patch +++ /dev/null @@ -1,39 +0,0 @@ -From jcb@inf.ed.ac.uk Wed Mar 1 15:31:40 2006 -Message-ID: <17413.30016.470872.240977@palau.inf.ed.ac.uk> -Date: Wed, 1 Mar 2006 10:19:44 +0000 -From: Julian Bradfield <jcb+luu@inf.ed.ac.uk> -cc: Greg KH <greg@kroah.com> -Subject: USB: PL2303 and TIOCMIWAIT - -A while ago, I posted about TIOCMIWAIT not working with the PL2303 -USB-serial adapter. - - -After a brief exchange with Greg, I tracked this to a missing wake-up -in the USB interrupt procedures. I got our systems staff to install -the enclosed very simple patch to our 2.6.12 kernels, and it all works -fine as expected. I guess this should also apply to the latest version -and go into the mainstream. - -Apologies for the long delay in posting the result. - -The routine being patched is pl2303_update_line_status - -Signed-off-by: Julian Bradfield <jcb+luu@inf.ed.ac.uk> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - - ---- - drivers/usb/serial/pl2303.c | 1 + - 1 file changed, 1 insertion(+) - ---- gregkh-2.6.orig/drivers/usb/serial/pl2303.c -+++ gregkh-2.6/drivers/usb/serial/pl2303.c -@@ -826,6 +826,7 @@ static void pl2303_update_line_status(st - spin_lock_irqsave(&priv->lock, flags); - priv->line_status = data[status_idx]; - spin_unlock_irqrestore(&priv->lock, flags); -+ wake_up_interruptible (&priv->delta_msr_wait); - - exit: - return; diff --git a/usb/usb-remove-linux_version_code-macro-usage.patch b/usb/usb-remove-linux_version_code-macro-usage.patch deleted file mode 100644 index 69cf4d0ed2bfa..0000000000000 --- a/usb/usb-remove-linux_version_code-macro-usage.patch +++ /dev/null @@ -1,82 +0,0 @@ -From penberg@cs.helsinki.fi Mon Jan 16 14:05:27 2006 -From: Pekka Enberg <penberg@cs.helsinki.fi> -Subject: USB: remove LINUX_VERSION_CODE macro usage -To: Greg KH <gregkh@suse.de> -Date: Thu, 12 Jan 2006 20:35:25 +0200 -Message-Id: <1137090925.9933.0.camel@localhost> - -From: Pekka Enberg <penberg@cs.helsinki.fi> - -This patch removes unnecessary LINUX_VERSION_CODE macro usage from -drivers/usb/. - -Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/usb/media/pwc/pwc-ctrl.c | 1 - - drivers/usb/media/pwc/pwc-if.c | 6 +----- - drivers/usb/misc/sisusbvga/sisusb.h | 8 -------- - 3 files changed, 1 insertion(+), 14 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/media/pwc/pwc-ctrl.c -+++ gregkh-2.6/drivers/usb/media/pwc/pwc-ctrl.c -@@ -41,7 +41,6 @@ - #include <asm/uaccess.h> - #endif - #include <asm/errno.h> --#include <linux/version.h> - - #include "pwc.h" - #include "pwc-ioctl.h" ---- gregkh-2.6.orig/drivers/usb/media/pwc/pwc-if.c -+++ gregkh-2.6/drivers/usb/media/pwc/pwc-if.c -@@ -62,7 +62,6 @@ - #include <linux/poll.h> - #include <linux/slab.h> - #include <linux/vmalloc.h> --#include <linux/version.h> - #include <asm/io.h> - - #include "pwc.h" -@@ -827,13 +826,10 @@ static int pwc_isoc_init(struct pwc_devi - /* Get the current alternate interface, adjust packet size */ - if (!udev->actconfig) - return -EFAULT; --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -- idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate]; --#else -+ - intf = usb_ifnum_to_if(udev, 0); - if (intf) - idesc = usb_altnum_to_altsetting(intf, pdev->valternate); --#endif - - if (!idesc) - return -EFAULT; ---- gregkh-2.6.orig/drivers/usb/misc/sisusbvga/sisusb.h -+++ gregkh-2.6/drivers/usb/misc/sisusbvga/sisusb.h -@@ -37,24 +37,16 @@ - #ifndef _SISUSB_H_ - #define _SISUSB_H_ - --#include <linux/version.h> - #ifdef CONFIG_COMPAT --#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) --#include <linux/ioctl32.h> --#define SISUSB_OLD_CONFIG_COMPAT --#else - #define SISUSB_NEW_CONFIG_COMPAT - #endif --#endif - - /* For older kernels, support for text consoles is by default - * off. To ensable text console support, change the following: - */ - #if 0 --#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) - #define CONFIG_USB_SISUSBVGA_CON - #endif --#endif - - /* Version Information */ - diff --git a/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch b/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch deleted file mode 100644 index 2f3e82d030d85..0000000000000 --- a/usb/usb-remove-obsolete_oss_usb_driver-drivers.patch +++ /dev/null @@ -1,6407 +0,0 @@ -From bunk@stusta.de Sat Feb 4 17:03:30 2006 -Date: Sun, 5 Feb 2006 00:03:28 +0100 -From: Adrian Bunk <bunk@stusta.de> -To: greg@kroah.com -Subject: USB: remove OBSOLETE_OSS_USB_DRIVER drivers -Message-ID: <20060204230328.GE4528@stusta.de> -Content-Disposition: inline - -This patch removes the obsolete USB_MIDI and USB_AUDIO drivers. - -Signed-off-by: Adrian Bunk <bunk@stusta.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/Makefile | 2 - drivers/usb/class/Kconfig | 47 - drivers/usb/class/Makefile | 2 - drivers/usb/class/audio.c | 3869 ------------------------------------------- - drivers/usb/class/audio.h | 110 - - drivers/usb/class/usb-midi.c | 2153 ----------------------- - drivers/usb/class/usb-midi.h | 164 - - 7 files changed, 6347 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/Makefile -+++ gregkh-2.6/drivers/usb/Makefile -@@ -17,8 +17,6 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ - obj-$(CONFIG_ETRAX_USB_HOST) += host/ - - obj-$(CONFIG_USB_ACM) += class/ --obj-$(CONFIG_USB_AUDIO) += class/ --obj-$(CONFIG_USB_MIDI) += class/ - obj-$(CONFIG_USB_PRINTER) += class/ - - obj-$(CONFIG_USB_STORAGE) += storage/ ---- gregkh-2.6.orig/drivers/usb/class/Kconfig -+++ gregkh-2.6/drivers/usb/class/Kconfig -@@ -4,53 +4,6 @@ - comment "USB Device Class drivers" - depends on USB - --config OBSOLETE_OSS_USB_DRIVER -- bool "Obsolete OSS USB drivers" -- depends on USB && SOUND -- help -- This option enables support for the obsolete USB Audio and Midi -- drivers that are scheduled for removal in the near future since -- there are ALSA drivers for the same hardware. -- -- Please contact Adrian Bunk <bunk@stusta.de> if you had to -- say Y here because of missing support in the ALSA drivers. -- -- If unsure, say N. -- --config USB_AUDIO -- tristate "USB Audio support" -- depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER -- help -- Say Y here if you want to connect USB audio equipment such as -- speakers to your computer's USB port. You only need this if you use -- the OSS sound driver; ALSA has its own option for usb audio support. -- -- To compile this driver as a module, choose M here: the -- module will be called audio. -- --config USB_MIDI -- tristate "USB MIDI support" -- depends on USB && SOUND && OBSOLETE_OSS_USB_DRIVER -- ---help--- -- Say Y here if you want to connect a USB MIDI device to your -- computer's USB port. You only need this if you use the OSS -- sound system; USB MIDI devices are supported by ALSA's USB -- audio driver. This driver is for devices that comply with -- 'Universal Serial Bus Device Class Definition for MIDI Device'. -- -- The following devices are known to work: -- * Steinberg USB2MIDI -- * Roland MPU64 -- * Roland PC-300 -- * Roland SC8850 -- * Roland UM-1 -- * Roland UM-2 -- * Roland UA-100 -- * Yamaha MU1000 -- -- To compile this driver as a module, choose M here: the -- module will be called usb-midi. -- - config USB_ACM - tristate "USB Modem (CDC ACM) support" - depends on USB ---- gregkh-2.6.orig/drivers/usb/class/Makefile -+++ gregkh-2.6/drivers/usb/class/Makefile -@@ -4,6 +4,4 @@ - # - - obj-$(CONFIG_USB_ACM) += cdc-acm.o --obj-$(CONFIG_USB_AUDIO) += audio.o --obj-$(CONFIG_USB_MIDI) += usb-midi.o - obj-$(CONFIG_USB_PRINTER) += usblp.o ---- gregkh-2.6.orig/drivers/usb/class/audio.c -+++ /dev/null -@@ -1,3869 +0,0 @@ --/*****************************************************************************/ -- --/* -- * audio.c -- USB Audio Class driver -- * -- * Copyright (C) 1999, 2000, 2001, 2003, 2004 -- * Alan Cox (alan@lxorguk.ukuu.org.uk) -- * Thomas Sailer (sailer@ife.ee.ethz.ch) -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * Debugging: -- * Use the 'lsusb' utility to dump the descriptors. -- * -- * 1999-09-07: Alan Cox -- * Parsing Audio descriptor patch -- * 1999-09-08: Thomas Sailer -- * Added OSS compatible data io functions; both parts of the -- * driver remain to be glued together -- * 1999-09-10: Thomas Sailer -- * Beautified the driver. Added sample format conversions. -- * Still not properly glued with the parsing code. -- * The parsing code seems to have its problems btw, -- * Since it parses all available configs but doesn't -- * store which iface/altsetting belongs to which config. -- * 1999-09-20: Thomas Sailer -- * Threw out Alan's parsing code and implemented my own one. -- * You cannot reasonnably linearly parse audio descriptors, -- * especially the AudioClass descriptors have to be considered -- * pointer lists. Mixer parsing untested, due to lack of device. -- * First stab at synch pipe implementation, the Dallas USB DAC -- * wants to use an Asynch out pipe. usb_audio_state now basically -- * only contains lists of mixer and wave devices. We can therefore -- * now have multiple mixer/wave devices per USB device. -- * 1999-10-28: Thomas Sailer -- * Converted to URB API. Fixed a taskstate/wakeup semantics mistake -- * that made the driver consume all available CPU cycles. -- * Now runs stable on UHCI-Acher/Fliegl/Sailer. -- * 1999-10-31: Thomas Sailer -- * Audio can now be unloaded if it is not in use by any mixer -- * or dsp client (formerly you had to disconnect the audio devices -- * from the USB port) -- * Finally, about three months after ordering, my "Maxxtro SPK222" -- * speakers arrived, isn't disdata a great mail order company 8-) -- * Parse class specific endpoint descriptor of the audiostreaming -- * interfaces and take the endpoint attributes from there. -- * Unbelievably, the Philips USB DAC has a sampling rate range -- * of over a decade, yet does not support the sampling rate control! -- * No wonder it sounds so bad, has very audible sampling rate -- * conversion distortion. Don't try to listen to it using -- * decent headphones! -- * "Let's make things better" -> but please Philips start with your -- * own stuff!!!! -- * 1999-11-02: Thomas Sailer -- * It takes the Philips boxes several seconds to acquire synchronisation -- * that means they won't play short sounds. Should probably maintain -- * the ISO datastream even if there's nothing to play. -- * Fix counting the total_bytes counter, RealPlayer G2 depends on it. -- * 1999-12-20: Thomas Sailer -- * Fix bad bug in conversion to per interface probing. -- * disconnect was called multiple times for the audio device, -- * leading to a premature freeing of the audio structures -- * 2000-05-13: Thomas Sailer -- * I don't remember who changed the find_format routine, -- * but the change was completely broken for the Dallas -- * chip. Anyway taking sampling rate into account in find_format -- * is bad and should not be done unless there are devices with -- * completely broken audio descriptors. Unless someone shows -- * me such a descriptor, I will not allow find_format to -- * take the sampling rate into account. -- * Also, the former find_format made: -- * - mpg123 play mono instead of stereo -- * - sox completely fail for wav's with sample rates < 44.1kHz -- * for the Dallas chip. -- * Also fix a rather long standing problem with applications that -- * use "small" writes producing no sound at all. -- * 2000-05-15: Thomas Sailer -- * My fears came true, the Philips camera indeed has pretty stupid -- * audio descriptors. -- * 2000-05-17: Thomas Sailer -- * Nemsoft spotted my stupid last minute change, thanks -- * 2000-05-19: Thomas Sailer -- * Fixed FEATURE_UNIT thinkos found thanks to the KC Technology -- * Xtend device. Basically the driver treated FEATURE_UNIT's sourced -- * by mono terminals as stereo. -- * 2000-05-20: Thomas Sailer -- * SELECTOR support (and thus selecting record channels from the mixer). -- * Somewhat peculiar due to OSS interface limitations. Only works -- * for channels where a "slider" is already in front of it (i.e. -- * a MIXER unit or a FEATURE unit with volume capability). -- * 2000-11-26: Thomas Sailer -- * Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for -- * its 8 bit modes, but expects signed data (and should therefore have used PCM). -- * 2001-03-10: Thomas Sailer -- * provide abs function, prevent picking up a bogus kernel macro -- * for abs. Bug report by Andrew Morton <andrewm@uow.edu.au> -- * 2001-06-16: Bryce Nesbitt <bryce@obviously.com> -- * Fix SNDCTL_DSP_STEREO API violation -- * 2003-04-08: Oliver Neukum (oliver@neukum.name): -- * Setting a configuration is done by usbcore and must not be overridden -- * 2004-02-27: Workaround for broken synch descriptors -- * 2004-03-07: Alan Stern <stern@rowland.harvard.edu> -- * Add usb_ifnum_to_if() and usb_altnum_to_altsetting() support. -- * Use the in-memory descriptors instead of reading them from the device. -- * -- */ -- --/* -- * Strategy: -- * -- * Alan Cox and Thomas Sailer are starting to dig at opposite ends and -- * are hoping to meet in the middle, just like tunnel diggers :) -- * Alan tackles the descriptor parsing, Thomas the actual data IO and the -- * OSS compatible interface. -- * -- * Data IO implementation issues -- * -- * A mmap'able ring buffer per direction is implemented, because -- * almost every OSS app expects it. It is however impractical to -- * transmit/receive USB data directly into and out of the ring buffer, -- * due to alignment and synchronisation issues. Instead, the ring buffer -- * feeds a constant time delay line that handles the USB issues. -- * -- * Now we first try to find an alternate setting that exactly matches -- * the sample format requested by the user. If we find one, we do not -- * need to perform any sample rate conversions. If there is no matching -- * altsetting, we choose the closest one and perform sample format -- * conversions. We never do sample rate conversion; these are too -- * expensive to be performed in the kernel. -- * -- * Current status: no known HCD-specific issues. -- * -- * Generally: Due to the brokenness of the Audio Class spec -- * it seems generally impossible to write a generic Audio Class driver, -- * so a reasonable driver should implement the features that are actually -- * used. -- * -- * Parsing implementation issues -- * -- * One cannot reasonably parse the AudioClass descriptors linearly. -- * Therefore the current implementation features routines to look -- * for a specific descriptor in the descriptor list. -- * -- * How does the parsing work? First, all interfaces are searched -- * for an AudioControl class interface. If found, the config descriptor -- * that belongs to the current configuration is searched and -- * the HEADER descriptor is found. It contains a list of -- * all AudioStreaming and MIDIStreaming devices. This list is then walked, -- * and all AudioStreaming interfaces are classified into input and output -- * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming -- * is currently not supported). The input & output list is then used -- * to group inputs and outputs together and issued pairwise to the -- * AudioStreaming class parser. Finally, all OUTPUT_TERMINAL descriptors -- * are walked and issued to the mixer construction routine. -- * -- * The AudioStreaming parser simply enumerates all altsettings belonging -- * to the specified interface. It looks for AS_GENERAL and FORMAT_TYPE -- * class specific descriptors to extract the sample format/sample rate -- * data. Only sample format types PCM and PCM8 are supported right now, and -- * only FORMAT_TYPE_I is handled. The isochronous data endpoint needs to -- * be the first endpoint of the interface, and the optional synchronisation -- * isochronous endpoint the second one. -- * -- * Mixer construction works as follows: The various TERMINAL and UNIT -- * descriptors span a tree from the root (OUTPUT_TERMINAL) through the -- * intermediate nodes (UNITs) to the leaves (INPUT_TERMINAL). We walk -- * that tree in a depth first manner. FEATURE_UNITs may contribute volume, -- * bass and treble sliders to the mixer, MIXER_UNITs volume sliders. -- * The terminal type encoded in the INPUT_TERMINALs feeds a heuristic -- * to determine "meaningful" OSS slider numbers, however we will see -- * how well this works in practice. Other features are not used at the -- * moment, they seem less often used. Also, it seems difficult at least -- * to construct recording source switches from SELECTOR_UNITs, but -- * since there are not many USB ADC's available, we leave that for later. -- */ -- --/*****************************************************************************/ -- --#include <linux/kernel.h> --#include <linux/slab.h> --#include <linux/string.h> --#include <linux/timer.h> --#include <linux/sched.h> --#include <linux/smp_lock.h> --#include <linux/module.h> --#include <linux/sound.h> --#include <linux/soundcard.h> --#include <linux/list.h> --#include <linux/vmalloc.h> --#include <linux/init.h> --#include <linux/poll.h> --#include <linux/bitops.h> --#include <asm/uaccess.h> --#include <asm/io.h> --#include <linux/usb.h> -- --#include "audio.h" -- --/* -- * Version Information -- */ --#define DRIVER_VERSION "v1.0.0" --#define DRIVER_AUTHOR "Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)" --#define DRIVER_DESC "USB Audio Class driver" -- --#define AUDIO_DEBUG 1 -- --#define SND_DEV_DSP16 5 -- --#define dprintk(x) -- --/* --------------------------------------------------------------------- */ -- --/* -- * Linked list of all audio devices... -- */ --static struct list_head audiodevs = LIST_HEAD_INIT(audiodevs); --static DECLARE_MUTEX(open_sem); -- --/* -- * wait queue for processes wanting to open an USB audio device -- */ --static DECLARE_WAIT_QUEUE_HEAD(open_wait); -- -- --#define MAXFORMATS MAX_ALT --#define DMABUFSHIFT 17 /* 128k worth of DMA buffer */ --#define NRSGBUF (1U<<(DMABUFSHIFT-PAGE_SHIFT)) -- --/* -- * This influences: -- * - Latency -- * - Interrupt rate -- * - Synchronisation behaviour -- * Don't touch this if you don't understand all of the above. -- */ --#define DESCFRAMES 5 --#define SYNCFRAMES DESCFRAMES -- --#define MIXFLG_STEREOIN 1 --#define MIXFLG_STEREOOUT 2 -- --struct mixerchannel { -- __u16 value; -- __u16 osschannel; /* number of the OSS channel */ -- __s16 minval, maxval; -- __u16 slctunitid; -- __u8 unitid; -- __u8 selector; -- __u8 chnum; -- __u8 flags; --}; -- --struct audioformat { -- unsigned int format; -- unsigned int sratelo; -- unsigned int sratehi; -- unsigned char altsetting; -- unsigned char attributes; --}; -- --struct dmabuf { -- /* buffer data format */ -- unsigned int format; -- unsigned int srate; -- /* physical buffer */ -- unsigned char *sgbuf[NRSGBUF]; -- unsigned bufsize; -- unsigned numfrag; -- unsigned fragshift; -- unsigned wrptr, rdptr; -- unsigned total_bytes; -- int count; -- unsigned error; /* over/underrun */ -- wait_queue_head_t wait; -- /* redundant, but makes calculations easier */ -- unsigned fragsize; -- unsigned dmasize; -- /* OSS stuff */ -- unsigned mapped:1; -- unsigned ready:1; -- unsigned ossfragshift; -- int ossmaxfrags; -- unsigned subdivision; --}; -- --struct usb_audio_state; -- --#define FLG_URB0RUNNING 1 --#define FLG_URB1RUNNING 2 --#define FLG_SYNC0RUNNING 4 --#define FLG_SYNC1RUNNING 8 --#define FLG_RUNNING 16 --#define FLG_CONNECTED 32 -- --struct my_data_urb { -- struct urb *urb; --}; -- --struct my_sync_urb { -- struct urb *urb; --}; -- -- --struct usb_audiodev { -- struct list_head list; -- struct usb_audio_state *state; -- -- /* soundcore stuff */ -- int dev_audio; -- -- /* wave stuff */ -- mode_t open_mode; -- spinlock_t lock; /* DMA buffer access spinlock */ -- -- struct usbin { -- int interface; /* Interface number, -1 means not used */ -- unsigned int format; /* USB data format */ -- unsigned int datapipe; /* the data input pipe */ -- unsigned int syncpipe; /* the synchronisation pipe - 0 for anything but adaptive IN mode */ -- unsigned int syncinterval; /* P for adaptive IN mode, 0 otherwise */ -- unsigned int freqn; /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */ -- unsigned int freqmax; /* maximum sampling rate, used for buffer management */ -- unsigned int phase; /* phase accumulator */ -- unsigned int flags; /* see FLG_ defines */ -- -- struct my_data_urb durb[2]; /* ISO descriptors for the data endpoint */ -- struct my_sync_urb surb[2]; /* ISO sync pipe descriptor if needed */ -- -- struct dmabuf dma; -- } usbin; -- -- struct usbout { -- int interface; /* Interface number, -1 means not used */ -- unsigned int format; /* USB data format */ -- unsigned int datapipe; /* the data input pipe */ -- unsigned int syncpipe; /* the synchronisation pipe - 0 for anything but asynchronous OUT mode */ -- unsigned int syncinterval; /* P for asynchronous OUT mode, 0 otherwise */ -- unsigned int freqn; /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */ -- unsigned int freqm; /* momentary sampling rate in USB format, i.e. fs/1000 in Q10.14 */ -- unsigned int freqmax; /* maximum sampling rate, used for buffer management */ -- unsigned int phase; /* phase accumulator */ -- unsigned int flags; /* see FLG_ defines */ -- -- struct my_data_urb durb[2]; /* ISO descriptors for the data endpoint */ -- struct my_sync_urb surb[2]; /* ISO sync pipe descriptor if needed */ -- -- struct dmabuf dma; -- } usbout; -- -- -- unsigned int numfmtin, numfmtout; -- struct audioformat fmtin[MAXFORMATS]; -- struct audioformat fmtout[MAXFORMATS]; --}; -- --struct usb_mixerdev { -- struct list_head list; -- struct usb_audio_state *state; -- -- /* soundcore stuff */ -- int dev_mixer; -- -- unsigned char iface; /* interface number of the AudioControl interface */ -- -- /* USB format descriptions */ -- unsigned int numch, modcnt; -- -- /* mixch is last and gets allocated dynamically */ -- struct mixerchannel ch[0]; --}; -- --struct usb_audio_state { -- struct list_head audiodev; -- -- /* USB device */ -- struct usb_device *usbdev; -- -- struct list_head audiolist; -- struct list_head mixerlist; -- -- unsigned count; /* usage counter; NOTE: the usb stack is also considered a user */ --}; -- --/* private audio format extensions */ --#define AFMT_STEREO 0x80000000 --#define AFMT_ISSTEREO(x) ((x) & AFMT_STEREO) --#define AFMT_IS16BIT(x) ((x) & (AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE)) --#define AFMT_ISUNSIGNED(x) ((x) & (AFMT_U8|AFMT_U16_LE|AFMT_U16_BE)) --#define AFMT_BYTESSHIFT(x) ((AFMT_ISSTEREO(x) ? 1 : 0) + (AFMT_IS16BIT(x) ? 1 : 0)) --#define AFMT_BYTES(x) (1<<AFMT_BYTESSHFIT(x)) -- --/* --------------------------------------------------------------------- */ -- --static inline unsigned ld2(unsigned int x) --{ -- unsigned r = 0; -- -- if (x >= 0x10000) { -- x >>= 16; -- r += 16; -- } -- if (x >= 0x100) { -- x >>= 8; -- r += 8; -- } -- if (x >= 0x10) { -- x >>= 4; -- r += 4; -- } -- if (x >= 4) { -- x >>= 2; -- r += 2; -- } -- if (x >= 2) -- r++; -- return r; --} -- --/* --------------------------------------------------------------------- */ -- --/* -- * OSS compatible ring buffer management. The ring buffer may be mmap'ed into -- * an application address space. -- * -- * I first used the rvmalloc stuff copied from bttv. Alan Cox did not like it, so -- * we now use an array of pointers to a single page each. This saves us the -- * kernel page table manipulations, but we have to do a page table alike mechanism -- * (though only one indirection) in software. -- */ -- --static void dmabuf_release(struct dmabuf *db) --{ -- unsigned int nr; -- void *p; -- -- for(nr = 0; nr < NRSGBUF; nr++) { -- if (!(p = db->sgbuf[nr])) -- continue; -- ClearPageReserved(virt_to_page(p)); -- free_page((unsigned long)p); -- db->sgbuf[nr] = NULL; -- } -- db->mapped = db->ready = 0; --} -- --static int dmabuf_init(struct dmabuf *db) --{ -- unsigned int nr, bytepersec, bufs; -- void *p; -- -- /* initialize some fields */ -- db->rdptr = db->wrptr = db->total_bytes = db->count = db->error = 0; -- /* calculate required buffer size */ -- bytepersec = db->srate << AFMT_BYTESSHIFT(db->format); -- bufs = 1U << DMABUFSHIFT; -- if (db->ossfragshift) { -- if ((1000 << db->ossfragshift) < bytepersec) -- db->fragshift = ld2(bytepersec/1000); -- else -- db->fragshift = db->ossfragshift; -- } else { -- db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1)); -- if (db->fragshift < 3) -- db->fragshift = 3; -- } -- db->numfrag = bufs >> db->fragshift; -- while (db->numfrag < 4 && db->fragshift > 3) { -- db->fragshift--; -- db->numfrag = bufs >> db->fragshift; -- } -- db->fragsize = 1 << db->fragshift; -- if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) -- db->numfrag = db->ossmaxfrags; -- db->dmasize = db->numfrag << db->fragshift; -- for(nr = 0; nr < NRSGBUF; nr++) { -- if (!db->sgbuf[nr]) { -- p = (void *)get_zeroed_page(GFP_KERNEL); -- if (!p) -- return -ENOMEM; -- db->sgbuf[nr] = p; -- SetPageReserved(virt_to_page(p)); -- } -- memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE); -- if ((nr << PAGE_SHIFT) >= db->dmasize) -- break; -- } -- db->bufsize = nr << PAGE_SHIFT; -- db->ready = 1; -- dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " -- "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x srate %d\n", -- bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize, -- db->numfrag, db->dmasize, db->bufsize, db->format, db->srate)); -- return 0; --} -- --static int dmabuf_mmap(struct vm_area_struct *vma, struct dmabuf *db, unsigned long start, unsigned long size, pgprot_t prot) --{ -- unsigned int nr; -- -- if (!db->ready || db->mapped || (start | size) & (PAGE_SIZE-1) || size > db->bufsize) -- return -EINVAL; -- size >>= PAGE_SHIFT; -- for(nr = 0; nr < size; nr++) -- if (!db->sgbuf[nr]) -- return -EINVAL; -- db->mapped = 1; -- for(nr = 0; nr < size; nr++) { -- unsigned long pfn; -- -- pfn = virt_to_phys(db->sgbuf[nr]) >> PAGE_SHIFT; -- if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, prot)) -- return -EAGAIN; -- start += PAGE_SIZE; -- } -- return 0; --} -- --static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size) --{ -- unsigned int pgrem, rem; -- -- db->total_bytes += size; -- for (;;) { -- if (size <= 0) -- return; -- pgrem = ((~db->wrptr) & (PAGE_SIZE-1)) + 1; -- if (pgrem > size) -- pgrem = size; -- rem = db->dmasize - db->wrptr; -- if (pgrem > rem) -- pgrem = rem; -- memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem); -- size -= pgrem; -- buffer += pgrem; -- db->wrptr += pgrem; -- if (db->wrptr >= db->dmasize) -- db->wrptr = 0; -- } --} -- --static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size) --{ -- unsigned int pgrem, rem; -- -- db->total_bytes += size; -- for (;;) { -- if (size <= 0) -- return; -- pgrem = ((~db->rdptr) & (PAGE_SIZE-1)) + 1; -- if (pgrem > size) -- pgrem = size; -- rem = db->dmasize - db->rdptr; -- if (pgrem > rem) -- pgrem = rem; -- memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem); -- size -= pgrem; -- buffer += pgrem; -- db->rdptr += pgrem; -- if (db->rdptr >= db->dmasize) -- db->rdptr = 0; -- } --} -- --static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void __user *buffer, unsigned int size) --{ -- unsigned int pgrem, rem; -- -- if (!db->ready || db->mapped) -- return -EINVAL; -- for (;;) { -- if (size <= 0) -- return 0; -- pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1; -- if (pgrem > size) -- pgrem = size; -- rem = db->dmasize - ptr; -- if (pgrem > rem) -- pgrem = rem; -- if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem)) -- return -EFAULT; -- size -= pgrem; -- buffer += pgrem; -- ptr += pgrem; -- if (ptr >= db->dmasize) -- ptr = 0; -- } --} -- --static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void __user *buffer, unsigned int size) --{ -- unsigned int pgrem, rem; -- -- if (!db->ready || db->mapped) -- return -EINVAL; -- for (;;) { -- if (size <= 0) -- return 0; -- pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1; -- if (pgrem > size) -- pgrem = size; -- rem = db->dmasize - ptr; -- if (pgrem > rem) -- pgrem = rem; -- if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem)) -- return -EFAULT; -- size -= pgrem; -- buffer += pgrem; -- ptr += pgrem; -- if (ptr >= db->dmasize) -- ptr = 0; -- } --} -- --/* --------------------------------------------------------------------- */ --/* -- * USB I/O code. We do sample format conversion if necessary -- */ -- --static void usbin_stop(struct usb_audiodev *as) --{ -- struct usbin *u = &as->usbin; -- unsigned long flags; -- unsigned int i, notkilled = 1; -- -- spin_lock_irqsave(&as->lock, flags); -- u->flags &= ~FLG_RUNNING; -- i = u->flags; -- spin_unlock_irqrestore(&as->lock, flags); -- while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { -- if (notkilled) -- schedule_timeout_interruptible(1); -- else -- schedule_timeout_uninterruptible(1); -- spin_lock_irqsave(&as->lock, flags); -- i = u->flags; -- spin_unlock_irqrestore(&as->lock, flags); -- if (notkilled && signal_pending(current)) { -- if (i & FLG_URB0RUNNING) -- usb_kill_urb(u->durb[0].urb); -- if (i & FLG_URB1RUNNING) -- usb_kill_urb(u->durb[1].urb); -- if (i & FLG_SYNC0RUNNING) -- usb_kill_urb(u->surb[0].urb); -- if (i & FLG_SYNC1RUNNING) -- usb_kill_urb(u->surb[1].urb); -- notkilled = 0; -- } -- } -- set_current_state(TASK_RUNNING); -- kfree(u->durb[0].urb->transfer_buffer); -- kfree(u->durb[1].urb->transfer_buffer); -- kfree(u->surb[0].urb->transfer_buffer); -- kfree(u->surb[1].urb->transfer_buffer); -- u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = -- u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; --} -- --static inline void usbin_release(struct usb_audiodev *as) --{ -- usbin_stop(as); --} -- --static void usbin_disc(struct usb_audiodev *as) --{ -- struct usbin *u = &as->usbin; -- -- unsigned long flags; -- -- spin_lock_irqsave(&as->lock, flags); -- u->flags &= ~(FLG_RUNNING | FLG_CONNECTED); -- spin_unlock_irqrestore(&as->lock, flags); -- usbin_stop(as); --} -- --static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt) --{ -- unsigned int cnt, i; -- __s16 *sp, *sp2, s; -- unsigned char *bp; -- -- cnt = scnt; -- if (AFMT_ISSTEREO(ifmt)) -- cnt <<= 1; -- sp = ((__s16 *)tmp) + cnt; -- switch (ifmt & ~AFMT_STEREO) { -- case AFMT_U8: -- for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { -- bp--; -- sp--; -- *sp = (*bp ^ 0x80) << 8; -- } -- break; -- -- case AFMT_S8: -- for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) { -- bp--; -- sp--; -- *sp = *bp << 8; -- } -- break; -- -- case AFMT_U16_LE: -- for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { -- bp -= 2; -- sp--; -- *sp = (bp[0] | (bp[1] << 8)) ^ 0x8000; -- } -- break; -- -- case AFMT_U16_BE: -- for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { -- bp -= 2; -- sp--; -- *sp = (bp[1] | (bp[0] << 8)) ^ 0x8000; -- } -- break; -- -- case AFMT_S16_LE: -- for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { -- bp -= 2; -- sp--; -- *sp = bp[0] | (bp[1] << 8); -- } -- break; -- -- case AFMT_S16_BE: -- for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) { -- bp -= 2; -- sp--; -- *sp = bp[1] | (bp[0] << 8); -- } -- break; -- } -- if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) { -- /* expand from mono to stereo */ -- for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) { -- sp--; -- sp2 -= 2; -- sp2[0] = sp2[1] = sp[0]; -- } -- } -- if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) { -- /* contract from stereo to mono */ -- for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2) -- sp[0] = (sp2[0] + sp2[1]) >> 1; -- } -- cnt = scnt; -- if (AFMT_ISSTEREO(ofmt)) -- cnt <<= 1; -- sp = ((__s16 *)tmp); -- bp = ((unsigned char *)obuf); -- switch (ofmt & ~AFMT_STEREO) { -- case AFMT_U8: -- for (i = 0; i < cnt; i++, sp++, bp++) -- *bp = (*sp >> 8) ^ 0x80; -- break; -- -- case AFMT_S8: -- for (i = 0; i < cnt; i++, sp++, bp++) -- *bp = *sp >> 8; -- break; -- -- case AFMT_U16_LE: -- for (i = 0; i < cnt; i++, sp++, bp += 2) { -- s = *sp; -- bp[0] = s; -- bp[1] = (s >> 8) ^ 0x80; -- } -- break; -- -- case AFMT_U16_BE: -- for (i = 0; i < cnt; i++, sp++, bp += 2) { -- s = *sp; -- bp[1] = s; -- bp[0] = (s >> 8) ^ 0x80; -- } -- break; -- -- case AFMT_S16_LE: -- for (i = 0; i < cnt; i++, sp++, bp += 2) { -- s = *sp; -- bp[0] = s; -- bp[1] = s >> 8; -- } -- break; -- -- case AFMT_S16_BE: -- for (i = 0; i < cnt; i++, sp++, bp += 2) { -- s = *sp; -- bp[1] = s; -- bp[0] = s >> 8; -- } -- break; -- } -- --} -- --static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples) --{ -- union { -- __s16 s[64]; -- unsigned char b[0]; -- } tmp; -- unsigned int scnt, maxs, ufmtsh, dfmtsh; -- -- ufmtsh = AFMT_BYTESSHIFT(u->format); -- dfmtsh = AFMT_BYTESSHIFT(u->dma.format); -- maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; -- while (samples > 0) { -- scnt = samples; -- if (scnt > maxs) -- scnt = maxs; -- conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt); -- dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh); -- buffer += scnt << ufmtsh; -- samples -= scnt; -- } --} -- --static int usbin_prepare_desc(struct usbin *u, struct urb *urb) --{ -- unsigned int i, maxsize, offs; -- -- maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); -- //printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format); -- for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) { -- urb->iso_frame_desc[i].length = maxsize; -- urb->iso_frame_desc[i].offset = offs; -- } -- urb->interval = 1; -- return 0; --} -- --/* -- * return value: 0 if descriptor should be restarted, -1 otherwise -- * convert sample format on the fly if necessary -- */ --static int usbin_retire_desc(struct usbin *u, struct urb *urb) --{ -- unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree; -- unsigned char *cp; -- -- ufmtsh = AFMT_BYTESSHIFT(u->format); -- dfmtsh = AFMT_BYTESSHIFT(u->dma.format); -- for (i = 0; i < DESCFRAMES; i++) { -- cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset; -- if (urb->iso_frame_desc[i].status) { -- dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); -- continue; -- } -- scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh; -- if (!scnt) -- continue; -- cnt = scnt << dfmtsh; -- if (!u->dma.mapped) { -- dmafree = u->dma.dmasize - u->dma.count; -- if (cnt > dmafree) { -- scnt = dmafree >> dfmtsh; -- cnt = scnt << dfmtsh; -- err++; -- } -- } -- u->dma.count += cnt; -- if (u->format == u->dma.format) { -- /* we do not need format conversion */ -- dprintk((KERN_DEBUG "usbaudio: no sample format conversion\n")); -- dmabuf_copyin(&u->dma, cp, cnt); -- } else { -- /* we need sampling format conversion */ -- dprintk((KERN_DEBUG "usbaudio: sample format conversion %x != %x\n", u->format, u->dma.format)); -- usbin_convert(u, cp, scnt); -- } -- } -- if (err) -- u->dma.error++; -- if (u->dma.count >= (signed)u->dma.fragsize) -- wake_up(&u->dma.wait); -- return err ? -1 : 0; --} -- --static void usbin_completed(struct urb *urb, struct pt_regs *regs) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)urb->context; -- struct usbin *u = &as->usbin; -- unsigned long flags; -- unsigned int mask; -- int suret = 0; -- --#if 0 -- printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); --#endif -- if (urb == u->durb[0].urb) -- mask = FLG_URB0RUNNING; -- else if (urb == u->durb[1].urb) -- mask = FLG_URB1RUNNING; -- else { -- mask = 0; -- printk(KERN_ERR "usbin_completed: panic: unknown URB\n"); -- } -- urb->dev = as->state->usbdev; -- spin_lock_irqsave(&as->lock, flags); -- if (!usbin_retire_desc(u, urb) && -- u->flags & FLG_RUNNING && -- !usbin_prepare_desc(u, urb) && -- (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { -- u->flags |= mask; -- } else { -- u->flags &= ~(mask | FLG_RUNNING); -- wake_up(&u->dma.wait); -- printk(KERN_DEBUG "usbin_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret); -- } -- spin_unlock_irqrestore(&as->lock, flags); --} -- --/* -- * we output sync data -- */ --static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb) --{ -- unsigned char *cp = urb->transfer_buffer; -- unsigned int i, offs; -- -- for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3, cp += 3) { -- urb->iso_frame_desc[i].length = 3; -- urb->iso_frame_desc[i].offset = offs; -- cp[0] = u->freqn; -- cp[1] = u->freqn >> 8; -- cp[2] = u->freqn >> 16; -- } -- urb->interval = 1; -- return 0; --} -- --/* -- * return value: 0 if descriptor should be restarted, -1 otherwise -- */ --static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb) --{ -- unsigned int i; -- -- for (i = 0; i < SYNCFRAMES; i++) -- if (urb->iso_frame_desc[0].status) -- dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); -- return 0; --} -- --static void usbin_sync_completed(struct urb *urb, struct pt_regs *regs) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)urb->context; -- struct usbin *u = &as->usbin; -- unsigned long flags; -- unsigned int mask; -- int suret = 0; -- --#if 0 -- printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); --#endif -- if (urb == u->surb[0].urb) -- mask = FLG_SYNC0RUNNING; -- else if (urb == u->surb[1].urb) -- mask = FLG_SYNC1RUNNING; -- else { -- mask = 0; -- printk(KERN_ERR "usbin_sync_completed: panic: unknown URB\n"); -- } -- urb->dev = as->state->usbdev; -- spin_lock_irqsave(&as->lock, flags); -- if (!usbin_sync_retire_desc(u, urb) && -- u->flags & FLG_RUNNING && -- !usbin_sync_prepare_desc(u, urb) && -- (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { -- u->flags |= mask; -- } else { -- u->flags &= ~(mask | FLG_RUNNING); -- wake_up(&u->dma.wait); -- dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); -- } -- spin_unlock_irqrestore(&as->lock, flags); --} -- --static int usbin_start(struct usb_audiodev *as) --{ -- struct usb_device *dev = as->state->usbdev; -- struct usbin *u = &as->usbin; -- struct urb *urb; -- unsigned long flags; -- unsigned int maxsze, bufsz; -- --#if 0 -- printk(KERN_DEBUG "usbin_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n", -- dev->devnum, u->format, u->dma.format, u->dma.srate); --#endif -- /* allocate USB storage if not already done */ -- spin_lock_irqsave(&as->lock, flags); -- if (!(u->flags & FLG_CONNECTED)) { -- spin_unlock_irqrestore(&as->lock, flags); -- return -EIO; -- } -- if (!(u->flags & FLG_RUNNING)) { -- spin_unlock_irqrestore(&as->lock, flags); -- u->freqn = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ -- u->freqmax = u->freqn + (u->freqn >> 2); -- u->phase = 0; -- maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); -- bufsz = DESCFRAMES * maxsze; -- kfree(u->durb[0].urb->transfer_buffer); -- u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); -- u->durb[0].urb->transfer_buffer_length = bufsz; -- kfree(u->durb[1].urb->transfer_buffer); -- u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); -- u->durb[1].urb->transfer_buffer_length = bufsz; -- if (u->syncpipe) { -- kfree(u->surb[0].urb->transfer_buffer); -- u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); -- u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; -- kfree(u->surb[1].urb->transfer_buffer); -- u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); -- u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; -- } -- if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || -- (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { -- printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); -- return 0; -- } -- spin_lock_irqsave(&as->lock, flags); -- } -- if (u->dma.count >= u->dma.dmasize && !u->dma.mapped) { -- spin_unlock_irqrestore(&as->lock, flags); -- return 0; -- } -- u->flags |= FLG_RUNNING; -- if (!(u->flags & FLG_URB0RUNNING)) { -- urb = u->durb[0].urb; -- urb->dev = dev; -- urb->pipe = u->datapipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = DESCFRAMES; -- urb->context = as; -- urb->complete = usbin_completed; -- if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) -- u->flags |= FLG_URB0RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { -- urb = u->durb[1].urb; -- urb->dev = dev; -- urb->pipe = u->datapipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = DESCFRAMES; -- urb->context = as; -- urb->complete = usbin_completed; -- if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) -- u->flags |= FLG_URB1RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->syncpipe) { -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { -- urb = u->surb[0].urb; -- urb->dev = dev; -- urb->pipe = u->syncpipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = SYNCFRAMES; -- urb->context = as; -- urb->complete = usbin_sync_completed; -- /* stride: u->syncinterval */ -- if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) -- u->flags |= FLG_SYNC0RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { -- urb = u->surb[1].urb; -- urb->dev = dev; -- urb->pipe = u->syncpipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = SYNCFRAMES; -- urb->context = as; -- urb->complete = usbin_sync_completed; -- /* stride: u->syncinterval */ -- if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL)) -- u->flags |= FLG_SYNC1RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- } -- spin_unlock_irqrestore(&as->lock, flags); -- return 0; --} -- --static void usbout_stop(struct usb_audiodev *as) --{ -- struct usbout *u = &as->usbout; -- unsigned long flags; -- unsigned int i, notkilled = 1; -- -- spin_lock_irqsave(&as->lock, flags); -- u->flags &= ~FLG_RUNNING; -- i = u->flags; -- spin_unlock_irqrestore(&as->lock, flags); -- while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) { -- if (notkilled) -- schedule_timeout_interruptible(1); -- else -- schedule_timeout_uninterruptible(1); -- spin_lock_irqsave(&as->lock, flags); -- i = u->flags; -- spin_unlock_irqrestore(&as->lock, flags); -- if (notkilled && signal_pending(current)) { -- if (i & FLG_URB0RUNNING) -- usb_kill_urb(u->durb[0].urb); -- if (i & FLG_URB1RUNNING) -- usb_kill_urb(u->durb[1].urb); -- if (i & FLG_SYNC0RUNNING) -- usb_kill_urb(u->surb[0].urb); -- if (i & FLG_SYNC1RUNNING) -- usb_kill_urb(u->surb[1].urb); -- notkilled = 0; -- } -- } -- set_current_state(TASK_RUNNING); -- kfree(u->durb[0].urb->transfer_buffer); -- kfree(u->durb[1].urb->transfer_buffer); -- kfree(u->surb[0].urb->transfer_buffer); -- kfree(u->surb[1].urb->transfer_buffer); -- u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = -- u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL; --} -- --static inline void usbout_release(struct usb_audiodev *as) --{ -- usbout_stop(as); --} -- --static void usbout_disc(struct usb_audiodev *as) --{ -- struct usbout *u = &as->usbout; -- unsigned long flags; -- -- spin_lock_irqsave(&as->lock, flags); -- u->flags &= ~(FLG_RUNNING | FLG_CONNECTED); -- spin_unlock_irqrestore(&as->lock, flags); -- usbout_stop(as); --} -- --static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples) --{ -- union { -- __s16 s[64]; -- unsigned char b[0]; -- } tmp; -- unsigned int scnt, maxs, ufmtsh, dfmtsh; -- -- ufmtsh = AFMT_BYTESSHIFT(u->format); -- dfmtsh = AFMT_BYTESSHIFT(u->dma.format); -- maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64; -- while (samples > 0) { -- scnt = samples; -- if (scnt > maxs) -- scnt = maxs; -- dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh); -- conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt); -- buffer += scnt << ufmtsh; -- samples -= scnt; -- } --} -- --static int usbout_prepare_desc(struct usbout *u, struct urb *urb) --{ -- unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs; -- unsigned char *cp = urb->transfer_buffer; -- -- ufmtsh = AFMT_BYTESSHIFT(u->format); -- dfmtsh = AFMT_BYTESSHIFT(u->dma.format); -- for (i = offs = 0; i < DESCFRAMES; i++) { -- urb->iso_frame_desc[i].offset = offs; -- u->phase = (u->phase & 0x3fff) + u->freqm; -- scnt = u->phase >> 14; -- if (!scnt) { -- urb->iso_frame_desc[i].length = 0; -- continue; -- } -- cnt = scnt << dfmtsh; -- if (!u->dma.mapped) { -- if (cnt > u->dma.count) { -- scnt = u->dma.count >> dfmtsh; -- cnt = scnt << dfmtsh; -- err++; -- } -- u->dma.count -= cnt; -- } else -- u->dma.count += cnt; -- if (u->format == u->dma.format) { -- /* we do not need format conversion */ -- dmabuf_copyout(&u->dma, cp, cnt); -- } else { -- /* we need sampling format conversion */ -- usbout_convert(u, cp, scnt); -- } -- cnt = scnt << ufmtsh; -- urb->iso_frame_desc[i].length = cnt; -- offs += cnt; -- cp += cnt; -- } -- urb->interval = 1; -- if (err) -- u->dma.error++; -- if (u->dma.mapped) { -- if (u->dma.count >= (signed)u->dma.fragsize) -- wake_up(&u->dma.wait); -- } else { -- if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize) -- wake_up(&u->dma.wait); -- } -- return err ? -1 : 0; --} -- --/* -- * return value: 0 if descriptor should be restarted, -1 otherwise -- */ --static int usbout_retire_desc(struct usbout *u, struct urb *urb) --{ -- unsigned int i; -- -- for (i = 0; i < DESCFRAMES; i++) { -- if (urb->iso_frame_desc[i].status) { -- dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); -- continue; -- } -- } -- return 0; --} -- --static void usbout_completed(struct urb *urb, struct pt_regs *regs) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)urb->context; -- struct usbout *u = &as->usbout; -- unsigned long flags; -- unsigned int mask; -- int suret = 0; -- --#if 0 -- printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); --#endif -- if (urb == u->durb[0].urb) -- mask = FLG_URB0RUNNING; -- else if (urb == u->durb[1].urb) -- mask = FLG_URB1RUNNING; -- else { -- mask = 0; -- printk(KERN_ERR "usbout_completed: panic: unknown URB\n"); -- } -- urb->dev = as->state->usbdev; -- spin_lock_irqsave(&as->lock, flags); -- if (!usbout_retire_desc(u, urb) && -- u->flags & FLG_RUNNING && -- !usbout_prepare_desc(u, urb) && -- (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { -- u->flags |= mask; -- } else { -- u->flags &= ~(mask | FLG_RUNNING); -- wake_up(&u->dma.wait); -- dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); -- } -- spin_unlock_irqrestore(&as->lock, flags); --} -- --static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb) --{ -- unsigned int i, offs; -- -- for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3) { -- urb->iso_frame_desc[i].length = 3; -- urb->iso_frame_desc[i].offset = offs; -- } -- urb->interval = 1; -- return 0; --} -- --/* -- * return value: 0 if descriptor should be restarted, -1 otherwise -- */ --static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb) --{ -- unsigned char *cp = urb->transfer_buffer; -- unsigned int f, i; -- -- for (i = 0; i < SYNCFRAMES; i++, cp += 3) { -- if (urb->iso_frame_desc[i].status) { -- dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); -- continue; -- } -- if (urb->iso_frame_desc[i].actual_length < 3) { -- dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length)); -- continue; -- } -- f = cp[0] | (cp[1] << 8) | (cp[2] << 16); -- if (abs(f - u->freqn) > (u->freqn >> 3) || f > u->freqmax) { -- printk(KERN_WARNING "usbout_sync_retire_desc: requested frequency %u (nominal %u) out of range!\n", f, u->freqn); -- continue; -- } -- u->freqm = f; -- } -- return 0; --} -- --static void usbout_sync_completed(struct urb *urb, struct pt_regs *regs) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)urb->context; -- struct usbout *u = &as->usbout; -- unsigned long flags; -- unsigned int mask; -- int suret = 0; -- --#if 0 -- printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags); --#endif -- if (urb == u->surb[0].urb) -- mask = FLG_SYNC0RUNNING; -- else if (urb == u->surb[1].urb) -- mask = FLG_SYNC1RUNNING; -- else { -- mask = 0; -- printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n"); -- } -- urb->dev = as->state->usbdev; -- spin_lock_irqsave(&as->lock, flags); -- if (!usbout_sync_retire_desc(u, urb) && -- u->flags & FLG_RUNNING && -- !usbout_sync_prepare_desc(u, urb) && -- (suret = usb_submit_urb(urb, GFP_ATOMIC)) == 0) { -- u->flags |= mask; -- } else { -- u->flags &= ~(mask | FLG_RUNNING); -- wake_up(&u->dma.wait); -- dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); -- } -- spin_unlock_irqrestore(&as->lock, flags); --} -- --static int usbout_start(struct usb_audiodev *as) --{ -- struct usb_device *dev = as->state->usbdev; -- struct usbout *u = &as->usbout; -- struct urb *urb; -- unsigned long flags; -- unsigned int maxsze, bufsz; -- --#if 0 -- printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n", -- dev->devnum, u->format, u->dma.format, u->dma.srate); --#endif -- /* allocate USB storage if not already done */ -- spin_lock_irqsave(&as->lock, flags); -- if (!(u->flags & FLG_CONNECTED)) { -- spin_unlock_irqrestore(&as->lock, flags); -- return -EIO; -- } -- if (!(u->flags & FLG_RUNNING)) { -- spin_unlock_irqrestore(&as->lock, flags); -- u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ -- u->freqmax = u->freqn + (u->freqn >> 2); -- u->phase = 0; -- maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); -- bufsz = DESCFRAMES * maxsze; -- kfree(u->durb[0].urb->transfer_buffer); -- u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); -- u->durb[0].urb->transfer_buffer_length = bufsz; -- kfree(u->durb[1].urb->transfer_buffer); -- u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL); -- u->durb[1].urb->transfer_buffer_length = bufsz; -- if (u->syncpipe) { -- kfree(u->surb[0].urb->transfer_buffer); -- u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); -- u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES; -- kfree(u->surb[1].urb->transfer_buffer); -- u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); -- u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES; -- } -- if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || -- (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) { -- printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); -- return 0; -- } -- spin_lock_irqsave(&as->lock, flags); -- } -- if (u->dma.count <= 0 && !u->dma.mapped) { -- spin_unlock_irqrestore(&as->lock, flags); -- return 0; -- } -- u->flags |= FLG_RUNNING; -- if (!(u->flags & FLG_URB0RUNNING)) { -- urb = u->durb[0].urb; -- urb->dev = dev; -- urb->pipe = u->datapipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = DESCFRAMES; -- urb->context = as; -- urb->complete = usbout_completed; -- if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) -- u->flags |= FLG_URB0RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { -- urb = u->durb[1].urb; -- urb->dev = dev; -- urb->pipe = u->datapipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = DESCFRAMES; -- urb->context = as; -- urb->complete = usbout_completed; -- if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) -- u->flags |= FLG_URB1RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->syncpipe) { -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { -- urb = u->surb[0].urb; -- urb->dev = dev; -- urb->pipe = u->syncpipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = SYNCFRAMES; -- urb->context = as; -- urb->complete = usbout_sync_completed; -- /* stride: u->syncinterval */ -- if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) -- u->flags |= FLG_SYNC0RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { -- urb = u->surb[1].urb; -- urb->dev = dev; -- urb->pipe = u->syncpipe; -- urb->transfer_flags = URB_ISO_ASAP; -- urb->number_of_packets = SYNCFRAMES; -- urb->context = as; -- urb->complete = usbout_sync_completed; -- /* stride: u->syncinterval */ -- if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_ATOMIC)) -- u->flags |= FLG_SYNC1RUNNING; -- else -- u->flags &= ~FLG_RUNNING; -- } -- } -- spin_unlock_irqrestore(&as->lock, flags); -- return 0; --} -- --/* --------------------------------------------------------------------- */ -- --static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate) --{ -- unsigned int g = 0; -- -- if (srate < afp->sratelo) -- g += afp->sratelo - srate; -- if (srate > afp->sratehi) -- g += srate - afp->sratehi; -- if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt)) -- g += 0x100000; -- if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt)) -- g += 0x400000; -- if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt)) -- g += 0x100000; -- if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt)) -- g += 0x400000; -- return g; --} -- --static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate) --{ -- unsigned int i, g, gb = ~0; -- int j = -1; /* default to failure */ -- -- /* find "best" format (according to format_goodness) */ -- for (i = 0; i < nr; i++) { -- g = format_goodness(&afp[i], fmt, srate); -- if (g >= gb) -- continue; -- j = i; -- gb = g; -- } -- return j; --} -- --static int set_format_in(struct usb_audiodev *as) --{ -- struct usb_device *dev = as->state->usbdev; -- struct usb_host_interface *alts; -- struct usb_interface *iface; -- struct usbin *u = &as->usbin; -- struct dmabuf *d = &u->dma; -- struct audioformat *fmt; -- unsigned int ep; -- unsigned char data[3]; -- int fmtnr, ret; -- -- iface = usb_ifnum_to_if(dev, u->interface); -- if (!iface) -- return 0; -- -- fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate); -- if (fmtnr < 0) { -- printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n"); -- return -1; -- } -- -- fmt = as->fmtin + fmtnr; -- alts = usb_altnum_to_altsetting(iface, fmt->altsetting); -- u->format = fmt->format; -- u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); -- u->syncpipe = u->syncinterval = 0; -- if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x08) { -- if (alts->desc.bNumEndpoints < 2 || -- alts->endpoint[1].desc.bmAttributes != 0x01 || -- alts->endpoint[1].desc.bSynchAddress != 0 || -- alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress & 0x7f)) { -- printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in " -- "but has invalid synch pipe; treating as asynchronous in\n", -- dev->devnum, u->interface, fmt->altsetting); -- } else { -- u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); -- u->syncinterval = alts->endpoint[1].desc.bRefresh; -- } -- } -- if (d->srate < fmt->sratelo) -- d->srate = fmt->sratelo; -- if (d->srate > fmt->sratehi) -- d->srate = fmt->sratehi; -- dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", -- u->interface, fmt->altsetting)); -- if (usb_set_interface(dev, alts->desc.bInterfaceNumber, fmt->altsetting) < 0) { -- printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", -- dev->devnum, u->interface, fmt->altsetting); -- return -1; -- } -- if (fmt->sratelo == fmt->sratehi) -- return 0; -- ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); -- /* if endpoint has pitch control, enable it */ -- if (fmt->attributes & 0x02) { -- data[0] = 1; -- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, -- PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", -- ret, dev->devnum, u->interface, ep, d->srate); -- return -1; -- } -- } -- /* if endpoint has sampling rate control, set it */ -- if (fmt->attributes & 0x01) { -- data[0] = d->srate; -- data[1] = d->srate >> 8; -- data[2] = d->srate >> 16; -- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, -- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n", -- ret, dev->devnum, u->interface, ep, d->srate); -- return -1; -- } -- if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, -- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n", -- ret, dev->devnum, u->interface, ep); -- return -1; -- } -- dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n", -- dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); -- d->srate = data[0] | (data[1] << 8) | (data[2] << 16); -- } -- dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); -- return 0; --} -- --static int set_format_out(struct usb_audiodev *as) --{ -- struct usb_device *dev = as->state->usbdev; -- struct usb_host_interface *alts; -- struct usb_interface *iface; -- struct usbout *u = &as->usbout; -- struct dmabuf *d = &u->dma; -- struct audioformat *fmt; -- unsigned int ep; -- unsigned char data[3]; -- int fmtnr, ret; -- -- iface = usb_ifnum_to_if(dev, u->interface); -- if (!iface) -- return 0; -- -- fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate); -- if (fmtnr < 0) { -- printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n"); -- return -1; -- } -- -- fmt = as->fmtout + fmtnr; -- u->format = fmt->format; -- alts = usb_altnum_to_altsetting(iface, fmt->altsetting); -- u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); -- u->syncpipe = u->syncinterval = 0; -- if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x04) { --#if 0 -- printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n" -- KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n" -- KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints, -- alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress, -- alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress); --#endif -- if (alts->desc.bNumEndpoints < 2 || -- alts->endpoint[1].desc.bmAttributes != 0x01 || -- alts->endpoint[1].desc.bSynchAddress != 0 || -- alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress | 0x80)) { -- printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out " -- "but has invalid synch pipe; treating as adaptive out\n", -- dev->devnum, u->interface, fmt->altsetting); -- } else { -- u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); -- u->syncinterval = alts->endpoint[1].desc.bRefresh; -- } -- } -- if (d->srate < fmt->sratelo) -- d->srate = fmt->sratelo; -- if (d->srate > fmt->sratehi) -- d->srate = fmt->sratehi; -- dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", -- u->interface, fmt->altsetting)); -- if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { -- printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", -- dev->devnum, u->interface, fmt->altsetting); -- return -1; -- } -- if (fmt->sratelo == fmt->sratehi) -- return 0; -- ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); -- /* if endpoint has pitch control, enable it */ -- if (fmt->attributes & 0x02) { -- data[0] = 1; -- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, -- PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", -- ret, dev->devnum, u->interface, ep, d->srate); -- return -1; -- } -- } -- /* if endpoint has sampling rate control, set it */ -- if (fmt->attributes & 0x01) { -- data[0] = d->srate; -- data[1] = d->srate >> 8; -- data[2] = d->srate >> 16; -- if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, -- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n", -- ret, dev->devnum, u->interface, ep, d->srate); -- return -1; -- } -- if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, -- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) { -- printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n", -- ret, dev->devnum, u->interface, ep); -- return -1; -- } -- dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n", -- dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); -- d->srate = data[0] | (data[1] << 8) | (data[2] << 16); -- } -- dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); -- return 0; --} -- --static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate) --{ -- int ret1 = 0, ret2 = 0; -- -- if (!(fmode & (FMODE_READ|FMODE_WRITE))) -- return -EINVAL; -- if (fmode & FMODE_READ) { -- usbin_stop(s); -- s->usbin.dma.ready = 0; -- if (fmt == AFMT_QUERY) -- fmt = s->usbin.dma.format; -- else -- s->usbin.dma.format = fmt; -- if (!srate) -- srate = s->usbin.dma.srate; -- else -- s->usbin.dma.srate = srate; -- } -- if (fmode & FMODE_WRITE) { -- usbout_stop(s); -- s->usbout.dma.ready = 0; -- if (fmt == AFMT_QUERY) -- fmt = s->usbout.dma.format; -- else -- s->usbout.dma.format = fmt; -- if (!srate) -- srate = s->usbout.dma.srate; -- else -- s->usbout.dma.srate = srate; -- } -- if (fmode & FMODE_READ) -- ret1 = set_format_in(s); -- if (fmode & FMODE_WRITE) -- ret2 = set_format_out(s); -- return ret1 ? ret1 : ret2; --} -- --/* --------------------------------------------------------------------- */ -- --static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value) --{ -- struct usb_device *dev = ms->state->usbdev; -- unsigned char data[2]; -- struct mixerchannel *ch; -- int v1, v2, v3; -- -- if (mixch >= ms->numch) -- return -1; -- ch = &ms->ch[mixch]; -- v3 = ch->maxval - ch->minval; -- v1 = value & 0xff; -- v2 = (value >> 8) & 0xff; -- if (v1 > 100) -- v1 = 100; -- if (v2 > 100) -- v2 = 100; -- if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) -- v2 = v1; -- ch->value = v1 | (v2 << 8); -- v1 = (v1 * v3) / 100 + ch->minval; -- v2 = (v2 * v3) / 100 + ch->minval; -- switch (ch->selector) { -- case 0: /* mixer unit request */ -- data[0] = v1; -- data[1] = v1 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) -- goto err; -- if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) -- return 0; -- data[0] = v2; -- data[1] = v2 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)), -- ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) -- goto err; -- return 0; -- -- /* various feature unit controls */ -- case VOLUME_CONTROL: -- data[0] = v1; -- data[1] = v1 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) -- goto err; -- if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) -- return 0; -- data[0] = v2; -- data[1] = v2 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, 1000) < 0) -- goto err; -- return 0; -- -- case BASS_CONTROL: -- case MID_CONTROL: -- case TREBLE_CONTROL: -- data[0] = v1 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, 1000) < 0) -- goto err; -- if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) -- return 0; -- data[0] = v2 >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, 1000) < 0) -- goto err; -- return 0; -- -- default: -- return -1; -- } -- return 0; -- -- err: -- printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", -- dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector); -- return -1; --} -- --static int get_rec_src(struct usb_mixerdev *ms) --{ -- struct usb_device *dev = ms->state->usbdev; -- unsigned int mask = 0, retmask = 0; -- unsigned int i, j; -- unsigned char buf; -- int err = 0; -- -- for (i = 0; i < ms->numch; i++) { -- if (!ms->ch[i].slctunitid || (mask & (1 << i))) -- continue; -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) { -- err = -EIO; -- printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", -- dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); -- continue; -- } -- for (j = i; j < ms->numch; j++) { -- if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) -- continue; -- mask |= 1 << j; -- if (buf == (ms->ch[j].slctunitid >> 8)) -- retmask |= 1 << ms->ch[j].osschannel; -- } -- } -- if (err) -- return -EIO; -- return retmask; --} -- --static int set_rec_src(struct usb_mixerdev *ms, int srcmask) --{ -- struct usb_device *dev = ms->state->usbdev; -- unsigned int mask = 0, smask, bmask; -- unsigned int i, j; -- unsigned char buf; -- int err = 0; -- -- for (i = 0; i < ms->numch; i++) { -- if (!ms->ch[i].slctunitid || (mask & (1 << i))) -- continue; -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) { -- err = -EIO; -- printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", -- dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff); -- continue; -- } -- /* first generate smask */ -- smask = bmask = 0; -- for (j = i; j < ms->numch; j++) { -- if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) -- continue; -- smask |= 1 << ms->ch[j].osschannel; -- if (buf == (ms->ch[j].slctunitid >> 8)) -- bmask |= 1 << ms->ch[j].osschannel; -- mask |= 1 << j; -- } -- /* check for multiple set sources */ -- j = hweight32(srcmask & smask); -- if (j == 0) -- continue; -- if (j > 1) -- srcmask &= ~bmask; -- for (j = i; j < ms->numch; j++) { -- if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff) -- continue; -- if (!(srcmask & (1 << ms->ch[j].osschannel))) -- continue; -- buf = ms->ch[j].slctunitid >> 8; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- 0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, 1000) < 0) { -- err = -EIO; -- printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", -- dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff); -- continue; -- } -- } -- } -- return err ? -EIO : 0; --} -- --/* --------------------------------------------------------------------- */ -- --/* -- * should be called with open_sem hold, so that no new processes -- * look at the audio device to be destroyed -- */ -- --static void release(struct usb_audio_state *s) --{ -- struct usb_audiodev *as; -- struct usb_mixerdev *ms; -- -- s->count--; -- if (s->count) { -- up(&open_sem); -- return; -- } -- up(&open_sem); -- wake_up(&open_wait); -- while (!list_empty(&s->audiolist)) { -- as = list_entry(s->audiolist.next, struct usb_audiodev, list); -- list_del(&as->list); -- usbin_release(as); -- usbout_release(as); -- dmabuf_release(&as->usbin.dma); -- dmabuf_release(&as->usbout.dma); -- usb_free_urb(as->usbin.durb[0].urb); -- usb_free_urb(as->usbin.durb[1].urb); -- usb_free_urb(as->usbin.surb[0].urb); -- usb_free_urb(as->usbin.surb[1].urb); -- usb_free_urb(as->usbout.durb[0].urb); -- usb_free_urb(as->usbout.durb[1].urb); -- usb_free_urb(as->usbout.surb[0].urb); -- usb_free_urb(as->usbout.surb[1].urb); -- kfree(as); -- } -- while (!list_empty(&s->mixerlist)) { -- ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list); -- list_del(&ms->list); -- kfree(ms); -- } -- kfree(s); --} -- --static inline int prog_dmabuf_in(struct usb_audiodev *as) --{ -- usbin_stop(as); -- return dmabuf_init(&as->usbin.dma); --} -- --static inline int prog_dmabuf_out(struct usb_audiodev *as) --{ -- usbout_stop(as); -- return dmabuf_init(&as->usbout.dma); --} -- --/* --------------------------------------------------------------------- */ -- --static int usb_audio_open_mixdev(struct inode *inode, struct file *file) --{ -- unsigned int minor = iminor(inode); -- struct usb_mixerdev *ms; -- struct usb_audio_state *s; -- -- down(&open_sem); -- list_for_each_entry(s, &audiodevs, audiodev) { -- list_for_each_entry(ms, &s->mixerlist, list) { -- if (ms->dev_mixer == minor) -- goto mixer_found; -- } -- } -- up(&open_sem); -- return -ENODEV; -- -- mixer_found: -- if (!s->usbdev) { -- up(&open_sem); -- return -EIO; -- } -- file->private_data = ms; -- s->count++; -- -- up(&open_sem); -- return nonseekable_open(inode, file); --} -- --static int usb_audio_release_mixdev(struct inode *inode, struct file *file) --{ -- struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; -- struct usb_audio_state *s; -- -- lock_kernel(); -- s = ms->state; -- down(&open_sem); -- release(s); -- unlock_kernel(); -- return 0; --} -- --static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) --{ -- struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data; -- int i, j, val; -- int __user *user_arg = (int __user *)arg; -- -- if (!ms->state->usbdev) -- return -ENODEV; -- -- if (cmd == SOUND_MIXER_INFO) { -- mixer_info info; -- -- memset(&info, 0, sizeof(info)); -- strncpy(info.id, "USB_AUDIO", sizeof(info.id)); -- strncpy(info.name, "USB Audio Class Driver", sizeof(info.name)); -- info.modify_counter = ms->modcnt; -- if (copy_to_user((void __user *)arg, &info, sizeof(info))) -- return -EFAULT; -- return 0; -- } -- if (cmd == SOUND_OLD_MIXER_INFO) { -- _old_mixer_info info; -- -- memset(&info, 0, sizeof(info)); -- strncpy(info.id, "USB_AUDIO", sizeof(info.id)); -- strncpy(info.name, "USB Audio Class Driver", sizeof(info.name)); -- if (copy_to_user((void __user *)arg, &info, sizeof(info))) -- return -EFAULT; -- return 0; -- } -- if (cmd == OSS_GETVERSION) -- return put_user(SOUND_VERSION, user_arg); -- if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) -- return -EINVAL; -- if (_IOC_DIR(cmd) == _IOC_READ) { -- switch (_IOC_NR(cmd)) { -- case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ -- val = get_rec_src(ms); -- if (val < 0) -- return val; -- return put_user(val, user_arg); -- -- case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */ -- for (val = i = 0; i < ms->numch; i++) -- val |= 1 << ms->ch[i].osschannel; -- return put_user(val, user_arg); -- -- case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */ -- for (val = i = 0; i < ms->numch; i++) -- if (ms->ch[i].slctunitid) -- val |= 1 << ms->ch[i].osschannel; -- return put_user(val, user_arg); -- -- case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */ -- for (val = i = 0; i < ms->numch; i++) -- if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) -- val |= 1 << ms->ch[i].osschannel; -- return put_user(val, user_arg); -- -- case SOUND_MIXER_CAPS: -- return put_user(SOUND_CAP_EXCL_INPUT, user_arg); -- -- default: -- i = _IOC_NR(cmd); -- if (i >= SOUND_MIXER_NRDEVICES) -- return -EINVAL; -- for (j = 0; j < ms->numch; j++) { -- if (ms->ch[j].osschannel == i) { -- return put_user(ms->ch[j].value, user_arg); -- } -- } -- return -EINVAL; -- } -- } -- if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) -- return -EINVAL; -- ms->modcnt++; -- switch (_IOC_NR(cmd)) { -- case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ -- if (get_user(val, user_arg)) -- return -EFAULT; -- return set_rec_src(ms, val); -- -- default: -- i = _IOC_NR(cmd); -- if (i >= SOUND_MIXER_NRDEVICES) -- return -EINVAL; -- for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++); -- if (j >= ms->numch) -- return -EINVAL; -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (wrmixer(ms, j, val)) -- return -EIO; -- return put_user(ms->ch[j].value, user_arg); -- } --} -- --static /*const*/ struct file_operations usb_mixer_fops = { -- .owner = THIS_MODULE, -- .llseek = no_llseek, -- .ioctl = usb_audio_ioctl_mixdev, -- .open = usb_audio_open_mixdev, -- .release = usb_audio_release_mixdev, --}; -- --/* --------------------------------------------------------------------- */ -- --static int drain_out(struct usb_audiodev *as, int nonblock) --{ -- DECLARE_WAITQUEUE(wait, current); -- unsigned long flags; -- int count, tmo; -- -- if (as->usbout.dma.mapped || !as->usbout.dma.ready) -- return 0; -- usbout_start(as); -- add_wait_queue(&as->usbout.dma.wait, &wait); -- for (;;) { -- __set_current_state(TASK_INTERRUPTIBLE); -- spin_lock_irqsave(&as->lock, flags); -- count = as->usbout.dma.count; -- spin_unlock_irqrestore(&as->lock, flags); -- if (count <= 0) -- break; -- if (signal_pending(current)) -- break; -- if (nonblock) { -- remove_wait_queue(&as->usbout.dma.wait, &wait); -- set_current_state(TASK_RUNNING); -- return -EBUSY; -- } -- tmo = 3 * HZ * count / as->usbout.dma.srate; -- tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format); -- if (!schedule_timeout(tmo + 1)) { -- printk(KERN_DEBUG "usbaudio: dma timed out??\n"); -- break; -- } -- } -- remove_wait_queue(&as->usbout.dma.wait, &wait); -- set_current_state(TASK_RUNNING); -- if (signal_pending(current)) -- return -ERESTARTSYS; -- return 0; --} -- --/* --------------------------------------------------------------------- */ -- --static ssize_t usb_audio_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- DECLARE_WAITQUEUE(wait, current); -- ssize_t ret = 0; -- unsigned long flags; -- unsigned int ptr; -- int cnt, err; -- -- if (as->usbin.dma.mapped) -- return -ENXIO; -- if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) -- return ret; -- if (!access_ok(VERIFY_WRITE, buffer, count)) -- return -EFAULT; -- add_wait_queue(&as->usbin.dma.wait, &wait); -- while (count > 0) { -- spin_lock_irqsave(&as->lock, flags); -- ptr = as->usbin.dma.rdptr; -- cnt = as->usbin.dma.count; -- /* set task state early to avoid wakeup races */ -- if (cnt <= 0) -- __set_current_state(TASK_INTERRUPTIBLE); -- spin_unlock_irqrestore(&as->lock, flags); -- if (cnt > count) -- cnt = count; -- if (cnt <= 0) { -- if (usbin_start(as)) { -- if (!ret) -- ret = -ENODEV; -- break; -- } -- if (file->f_flags & O_NONBLOCK) { -- if (!ret) -- ret = -EAGAIN; -- break; -- } -- schedule(); -- if (signal_pending(current)) { -- if (!ret) -- ret = -ERESTARTSYS; -- break; -- } -- continue; -- } -- if ((err = dmabuf_copyout_user(&as->usbin.dma, ptr, buffer, cnt))) { -- if (!ret) -- ret = err; -- break; -- } -- ptr += cnt; -- if (ptr >= as->usbin.dma.dmasize) -- ptr -= as->usbin.dma.dmasize; -- spin_lock_irqsave(&as->lock, flags); -- as->usbin.dma.rdptr = ptr; -- as->usbin.dma.count -= cnt; -- spin_unlock_irqrestore(&as->lock, flags); -- count -= cnt; -- buffer += cnt; -- ret += cnt; -- } -- __set_current_state(TASK_RUNNING); -- remove_wait_queue(&as->usbin.dma.wait, &wait); -- return ret; --} -- --static ssize_t usb_audio_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- DECLARE_WAITQUEUE(wait, current); -- ssize_t ret = 0; -- unsigned long flags; -- unsigned int ptr; -- unsigned int start_thr; -- int cnt, err; -- -- if (as->usbout.dma.mapped) -- return -ENXIO; -- if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) -- return ret; -- if (!access_ok(VERIFY_READ, buffer, count)) -- return -EFAULT; -- start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES)); -- add_wait_queue(&as->usbout.dma.wait, &wait); -- while (count > 0) { --#if 0 -- printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n", -- count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize, -- as->usbout.flags, current->state); --#endif -- spin_lock_irqsave(&as->lock, flags); -- if (as->usbout.dma.count < 0) { -- as->usbout.dma.count = 0; -- as->usbout.dma.rdptr = as->usbout.dma.wrptr; -- } -- ptr = as->usbout.dma.wrptr; -- cnt = as->usbout.dma.dmasize - as->usbout.dma.count; -- /* set task state early to avoid wakeup races */ -- if (cnt <= 0) -- __set_current_state(TASK_INTERRUPTIBLE); -- spin_unlock_irqrestore(&as->lock, flags); -- if (cnt > count) -- cnt = count; -- if (cnt <= 0) { -- if (usbout_start(as)) { -- if (!ret) -- ret = -ENODEV; -- break; -- } -- if (file->f_flags & O_NONBLOCK) { -- if (!ret) -- ret = -EAGAIN; -- break; -- } -- schedule(); -- if (signal_pending(current)) { -- if (!ret) -- ret = -ERESTARTSYS; -- break; -- } -- continue; -- } -- if ((err = dmabuf_copyin_user(&as->usbout.dma, ptr, buffer, cnt))) { -- if (!ret) -- ret = err; -- break; -- } -- ptr += cnt; -- if (ptr >= as->usbout.dma.dmasize) -- ptr -= as->usbout.dma.dmasize; -- spin_lock_irqsave(&as->lock, flags); -- as->usbout.dma.wrptr = ptr; -- as->usbout.dma.count += cnt; -- spin_unlock_irqrestore(&as->lock, flags); -- count -= cnt; -- buffer += cnt; -- ret += cnt; -- if (as->usbout.dma.count >= start_thr && usbout_start(as)) { -- if (!ret) -- ret = -ENODEV; -- break; -- } -- } -- __set_current_state(TASK_RUNNING); -- remove_wait_queue(&as->usbout.dma.wait, &wait); -- return ret; --} -- --/* Called without the kernel lock - fine */ --static unsigned int usb_audio_poll(struct file *file, struct poll_table_struct *wait) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- unsigned long flags; -- unsigned int mask = 0; -- -- if (file->f_mode & FMODE_WRITE) { -- if (!as->usbout.dma.ready) -- prog_dmabuf_out(as); -- poll_wait(file, &as->usbout.dma.wait, wait); -- } -- if (file->f_mode & FMODE_READ) { -- if (!as->usbin.dma.ready) -- prog_dmabuf_in(as); -- poll_wait(file, &as->usbin.dma.wait, wait); -- } -- spin_lock_irqsave(&as->lock, flags); -- if (file->f_mode & FMODE_READ) { -- if (as->usbin.dma.count >= (signed)as->usbin.dma.fragsize) -- mask |= POLLIN | POLLRDNORM; -- } -- if (file->f_mode & FMODE_WRITE) { -- if (as->usbout.dma.mapped) { -- if (as->usbout.dma.count >= (signed)as->usbout.dma.fragsize) -- mask |= POLLOUT | POLLWRNORM; -- } else { -- if ((signed)as->usbout.dma.dmasize >= as->usbout.dma.count + (signed)as->usbout.dma.fragsize) -- mask |= POLLOUT | POLLWRNORM; -- } -- } -- spin_unlock_irqrestore(&as->lock, flags); -- return mask; --} -- --static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- struct dmabuf *db; -- int ret = -EINVAL; -- -- lock_kernel(); -- if (vma->vm_flags & VM_WRITE) { -- if ((ret = prog_dmabuf_out(as)) != 0) -- goto out; -- db = &as->usbout.dma; -- } else if (vma->vm_flags & VM_READ) { -- if ((ret = prog_dmabuf_in(as)) != 0) -- goto out; -- db = &as->usbin.dma; -- } else -- goto out; -- -- ret = -EINVAL; -- if (vma->vm_pgoff != 0) -- goto out; -- -- ret = dmabuf_mmap(vma, db, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot); --out: -- unlock_kernel(); -- return ret; --} -- --static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- struct usb_audio_state *s = as->state; -- int __user *user_arg = (int __user *)arg; -- unsigned long flags; -- audio_buf_info abinfo; -- count_info cinfo; -- int val = 0; -- int val2, mapped, ret; -- -- if (!s->usbdev) -- return -EIO; -- mapped = ((file->f_mode & FMODE_WRITE) && as->usbout.dma.mapped) || -- ((file->f_mode & FMODE_READ) && as->usbin.dma.mapped); --#if 0 -- if (arg) -- get_user(val, (int *)arg); -- printk(KERN_DEBUG "usbaudio: usb_audio_ioctl cmd=%x arg=%lx *arg=%d\n", cmd, arg, val) --#endif -- switch (cmd) { -- case OSS_GETVERSION: -- return put_user(SOUND_VERSION, user_arg); -- -- case SNDCTL_DSP_SYNC: -- if (file->f_mode & FMODE_WRITE) -- return drain_out(as, 0/*file->f_flags & O_NONBLOCK*/); -- return 0; -- -- case SNDCTL_DSP_SETDUPLEX: -- return 0; -- -- case SNDCTL_DSP_GETCAPS: -- return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | -- DSP_CAP_MMAP | DSP_CAP_BATCH, user_arg); -- -- case SNDCTL_DSP_RESET: -- if (file->f_mode & FMODE_WRITE) { -- usbout_stop(as); -- as->usbout.dma.rdptr = as->usbout.dma.wrptr = as->usbout.dma.count = as->usbout.dma.total_bytes = 0; -- } -- if (file->f_mode & FMODE_READ) { -- usbin_stop(as); -- as->usbin.dma.rdptr = as->usbin.dma.wrptr = as->usbin.dma.count = as->usbin.dma.total_bytes = 0; -- } -- return 0; -- -- case SNDCTL_DSP_SPEED: -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (val >= 0) { -- if (val < 4000) -- val = 4000; -- if (val > 100000) -- val = 100000; -- if (set_format(as, file->f_mode, AFMT_QUERY, val)) -- return -EIO; -- } -- return put_user((file->f_mode & FMODE_READ) ? -- as->usbin.dma.srate : as->usbout.dma.srate, -- user_arg); -- -- case SNDCTL_DSP_STEREO: -- if (get_user(val, user_arg)) -- return -EFAULT; -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- if (val) -- val2 |= AFMT_STEREO; -- else -- val2 &= ~AFMT_STEREO; -- if (set_format(as, file->f_mode, val2, 0)) -- return -EIO; -- return 0; -- -- case SNDCTL_DSP_CHANNELS: -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (val != 0) { -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- if (val == 1) -- val2 &= ~AFMT_STEREO; -- else -- val2 |= AFMT_STEREO; -- if (set_format(as, file->f_mode, val2, 0)) -- return -EIO; -- } -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); -- -- case SNDCTL_DSP_GETFMTS: /* Returns a mask */ -- return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | -- AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, user_arg); -- -- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (val != AFMT_QUERY) { -- if (hweight32(val) != 1) -- return -EINVAL; -- if (!(val & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE | -- AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE))) -- return -EINVAL; -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- val |= val2 & AFMT_STEREO; -- if (set_format(as, file->f_mode, val, 0)) -- return -EIO; -- } -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- return put_user(val2 & ~AFMT_STEREO, user_arg); -- -- case SNDCTL_DSP_POST: -- return 0; -- -- case SNDCTL_DSP_GETTRIGGER: -- val = 0; -- if (file->f_mode & FMODE_READ && as->usbin.flags & FLG_RUNNING) -- val |= PCM_ENABLE_INPUT; -- if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) -- val |= PCM_ENABLE_OUTPUT; -- return put_user(val, user_arg); -- -- case SNDCTL_DSP_SETTRIGGER: -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (file->f_mode & FMODE_READ) { -- if (val & PCM_ENABLE_INPUT) { -- if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as))) -- return ret; -- if (usbin_start(as)) -- return -ENODEV; -- } else -- usbin_stop(as); -- } -- if (file->f_mode & FMODE_WRITE) { -- if (val & PCM_ENABLE_OUTPUT) { -- if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as))) -- return ret; -- if (usbout_start(as)) -- return -ENODEV; -- } else -- usbout_stop(as); -- } -- return 0; -- -- case SNDCTL_DSP_GETOSPACE: -- if (!(file->f_mode & FMODE_WRITE)) -- return -EINVAL; -- if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0) -- return val; -- spin_lock_irqsave(&as->lock, flags); -- abinfo.fragsize = as->usbout.dma.fragsize; -- abinfo.bytes = as->usbout.dma.dmasize - as->usbout.dma.count; -- abinfo.fragstotal = as->usbout.dma.numfrag; -- abinfo.fragments = abinfo.bytes >> as->usbout.dma.fragshift; -- spin_unlock_irqrestore(&as->lock, flags); -- return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -- -- case SNDCTL_DSP_GETISPACE: -- if (!(file->f_mode & FMODE_READ)) -- return -EINVAL; -- if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0) -- return val; -- spin_lock_irqsave(&as->lock, flags); -- abinfo.fragsize = as->usbin.dma.fragsize; -- abinfo.bytes = as->usbin.dma.count; -- abinfo.fragstotal = as->usbin.dma.numfrag; -- abinfo.fragments = abinfo.bytes >> as->usbin.dma.fragshift; -- spin_unlock_irqrestore(&as->lock, flags); -- return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; -- -- case SNDCTL_DSP_NONBLOCK: -- file->f_flags |= O_NONBLOCK; -- return 0; -- -- case SNDCTL_DSP_GETODELAY: -- if (!(file->f_mode & FMODE_WRITE)) -- return -EINVAL; -- spin_lock_irqsave(&as->lock, flags); -- val = as->usbout.dma.count; -- spin_unlock_irqrestore(&as->lock, flags); -- return put_user(val, user_arg); -- -- case SNDCTL_DSP_GETIPTR: -- if (!(file->f_mode & FMODE_READ)) -- return -EINVAL; -- spin_lock_irqsave(&as->lock, flags); -- cinfo.bytes = as->usbin.dma.total_bytes; -- cinfo.blocks = as->usbin.dma.count >> as->usbin.dma.fragshift; -- cinfo.ptr = as->usbin.dma.wrptr; -- if (as->usbin.dma.mapped) -- as->usbin.dma.count &= as->usbin.dma.fragsize-1; -- spin_unlock_irqrestore(&as->lock, flags); -- if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) -- return -EFAULT; -- return 0; -- -- case SNDCTL_DSP_GETOPTR: -- if (!(file->f_mode & FMODE_WRITE)) -- return -EINVAL; -- spin_lock_irqsave(&as->lock, flags); -- cinfo.bytes = as->usbout.dma.total_bytes; -- cinfo.blocks = as->usbout.dma.count >> as->usbout.dma.fragshift; -- cinfo.ptr = as->usbout.dma.rdptr; -- if (as->usbout.dma.mapped) -- as->usbout.dma.count &= as->usbout.dma.fragsize-1; -- spin_unlock_irqrestore(&as->lock, flags); -- if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo))) -- return -EFAULT; -- return 0; -- -- case SNDCTL_DSP_GETBLKSIZE: -- if (file->f_mode & FMODE_WRITE) { -- if ((val = prog_dmabuf_out(as))) -- return val; -- return put_user(as->usbout.dma.fragsize, user_arg); -- } -- if ((val = prog_dmabuf_in(as))) -- return val; -- return put_user(as->usbin.dma.fragsize, user_arg); -- -- case SNDCTL_DSP_SETFRAGMENT: -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (file->f_mode & FMODE_READ) { -- as->usbin.dma.ossfragshift = val & 0xffff; -- as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff; -- if (as->usbin.dma.ossfragshift < 4) -- as->usbin.dma.ossfragshift = 4; -- if (as->usbin.dma.ossfragshift > 15) -- as->usbin.dma.ossfragshift = 15; -- if (as->usbin.dma.ossmaxfrags < 4) -- as->usbin.dma.ossmaxfrags = 4; -- } -- if (file->f_mode & FMODE_WRITE) { -- as->usbout.dma.ossfragshift = val & 0xffff; -- as->usbout.dma.ossmaxfrags = (val >> 16) & 0xffff; -- if (as->usbout.dma.ossfragshift < 4) -- as->usbout.dma.ossfragshift = 4; -- if (as->usbout.dma.ossfragshift > 15) -- as->usbout.dma.ossfragshift = 15; -- if (as->usbout.dma.ossmaxfrags < 4) -- as->usbout.dma.ossmaxfrags = 4; -- } -- return 0; -- -- case SNDCTL_DSP_SUBDIVIDE: -- if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) || -- (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision)) -- return -EINVAL; -- if (get_user(val, user_arg)) -- return -EFAULT; -- if (val != 1 && val != 2 && val != 4) -- return -EINVAL; -- if (file->f_mode & FMODE_READ) -- as->usbin.dma.subdivision = val; -- if (file->f_mode & FMODE_WRITE) -- as->usbout.dma.subdivision = val; -- return 0; -- -- case SOUND_PCM_READ_RATE: -- return put_user((file->f_mode & FMODE_READ) ? -- as->usbin.dma.srate : as->usbout.dma.srate, -- user_arg); -- -- case SOUND_PCM_READ_CHANNELS: -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, user_arg); -- -- case SOUND_PCM_READ_BITS: -- val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format; -- return put_user(AFMT_IS16BIT(val2) ? 16 : 8, user_arg); -- -- case SOUND_PCM_WRITE_FILTER: -- case SNDCTL_DSP_SETSYNCRO: -- case SOUND_PCM_READ_FILTER: -- return -EINVAL; -- } -- dprintk((KERN_DEBUG "usbaudio: usb_audio_ioctl - no command found\n")); -- return -ENOIOCTLCMD; --} -- --static int usb_audio_open(struct inode *inode, struct file *file) --{ -- unsigned int minor = iminor(inode); -- DECLARE_WAITQUEUE(wait, current); -- struct usb_audiodev *as; -- struct usb_audio_state *s; -- -- for (;;) { -- down(&open_sem); -- list_for_each_entry(s, &audiodevs, audiodev) { -- list_for_each_entry(as, &s->audiolist, list) { -- if (!((as->dev_audio ^ minor) & ~0xf)) -- goto device_found; -- } -- } -- up(&open_sem); -- return -ENODEV; -- -- device_found: -- if (!s->usbdev) { -- up(&open_sem); -- return -EIO; -- } -- /* wait for device to become free */ -- if (!(as->open_mode & file->f_mode)) -- break; -- if (file->f_flags & O_NONBLOCK) { -- up(&open_sem); -- return -EBUSY; -- } -- __set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue(&open_wait, &wait); -- up(&open_sem); -- schedule(); -- __set_current_state(TASK_RUNNING); -- remove_wait_queue(&open_wait, &wait); -- if (signal_pending(current)) -- return -ERESTARTSYS; -- } -- if (file->f_mode & FMODE_READ) -- as->usbin.dma.ossfragshift = as->usbin.dma.ossmaxfrags = as->usbin.dma.subdivision = 0; -- if (file->f_mode & FMODE_WRITE) -- as->usbout.dma.ossfragshift = as->usbout.dma.ossmaxfrags = as->usbout.dma.subdivision = 0; -- if (set_format(as, file->f_mode, ((minor & 0xf) == SND_DEV_DSP16) ? AFMT_S16_LE : AFMT_U8 /* AFMT_ULAW */, 8000)) { -- up(&open_sem); -- return -EIO; -- } -- file->private_data = as; -- as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); -- s->count++; -- up(&open_sem); -- return nonseekable_open(inode, file); --} -- --static int usb_audio_release(struct inode *inode, struct file *file) --{ -- struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; -- struct usb_audio_state *s; -- struct usb_device *dev; -- -- lock_kernel(); -- s = as->state; -- dev = s->usbdev; -- if (file->f_mode & FMODE_WRITE) -- drain_out(as, file->f_flags & O_NONBLOCK); -- down(&open_sem); -- if (file->f_mode & FMODE_WRITE) { -- usbout_stop(as); -- if (dev && as->usbout.interface >= 0) -- usb_set_interface(dev, as->usbout.interface, 0); -- dmabuf_release(&as->usbout.dma); -- usbout_release(as); -- } -- if (file->f_mode & FMODE_READ) { -- usbin_stop(as); -- if (dev && as->usbin.interface >= 0) -- usb_set_interface(dev, as->usbin.interface, 0); -- dmabuf_release(&as->usbin.dma); -- usbin_release(as); -- } -- as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); -- release(s); -- wake_up(&open_wait); -- unlock_kernel(); -- return 0; --} -- --static /*const*/ struct file_operations usb_audio_fops = { -- .owner = THIS_MODULE, -- .llseek = no_llseek, -- .read = usb_audio_read, -- .write = usb_audio_write, -- .poll = usb_audio_poll, -- .ioctl = usb_audio_ioctl, -- .mmap = usb_audio_mmap, -- .open = usb_audio_open, -- .release = usb_audio_release, --}; -- --/* --------------------------------------------------------------------- */ -- --static int usb_audio_probe(struct usb_interface *iface, -- const struct usb_device_id *id); --static void usb_audio_disconnect(struct usb_interface *iface); -- --static struct usb_device_id usb_audio_ids [] = { -- { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), -- .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = 1}, -- { } /* Terminating entry */ --}; -- --MODULE_DEVICE_TABLE (usb, usb_audio_ids); -- --static struct usb_driver usb_audio_driver = { -- .name = "audio", -- .probe = usb_audio_probe, -- .disconnect = usb_audio_disconnect, -- .id_table = usb_audio_ids, --}; -- --static void *find_descriptor(void *descstart, unsigned int desclen, void *after, -- u8 dtype, int iface, int altsetting) --{ -- u8 *p, *end, *next; -- int ifc = -1, as = -1; -- -- p = descstart; -- end = p + desclen; -- for (; p < end;) { -- if (p[0] < 2) -- return NULL; -- next = p + p[0]; -- if (next > end) -- return NULL; -- if (p[1] == USB_DT_INTERFACE) { -- /* minimum length of interface descriptor */ -- if (p[0] < 9) -- return NULL; -- ifc = p[2]; -- as = p[3]; -- } -- if (p[1] == dtype && (!after || (void *)p > after) && -- (iface == -1 || iface == ifc) && (altsetting == -1 || altsetting == as)) { -- return p; -- } -- p = next; -- } -- return NULL; --} -- --static void *find_csinterface_descriptor(void *descstart, unsigned int desclen, void *after, u8 dsubtype, int iface, int altsetting) --{ -- unsigned char *p; -- -- p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, altsetting); -- while (p) { -- if (p[0] >= 3 && p[2] == dsubtype) -- return p; -- p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, altsetting); -- } -- return NULL; --} -- --static void *find_audiocontrol_unit(void *descstart, unsigned int desclen, void *after, u8 unit, int iface) --{ -- unsigned char *p; -- -- p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, -1); -- while (p) { -- if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit) -- return p; -- p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, -1); -- } -- return NULL; --} -- --static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, int asifin, int asifout) --{ -- struct usb_device *dev = s->usbdev; -- struct usb_audiodev *as; -- struct usb_host_interface *alts; -- struct usb_interface *iface; -- struct audioformat *fp; -- unsigned char *fmt, *csep; -- unsigned int i, j, k, format, idx; -- -- if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL))) -- return; -- memset(as, 0, sizeof(struct usb_audiodev)); -- init_waitqueue_head(&as->usbin.dma.wait); -- init_waitqueue_head(&as->usbout.dma.wait); -- spin_lock_init(&as->lock); -- as->usbin.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); -- as->usbin.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); -- as->usbin.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); -- as->usbin.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); -- as->usbout.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); -- as->usbout.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL); -- as->usbout.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); -- as->usbout.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL); -- if ((!as->usbin.durb[0].urb) || -- (!as->usbin.durb[1].urb) || -- (!as->usbin.surb[0].urb) || -- (!as->usbin.surb[1].urb) || -- (!as->usbout.durb[0].urb) || -- (!as->usbout.durb[1].urb) || -- (!as->usbout.surb[0].urb) || -- (!as->usbout.surb[1].urb)) { -- usb_free_urb(as->usbin.durb[0].urb); -- usb_free_urb(as->usbin.durb[1].urb); -- usb_free_urb(as->usbin.surb[0].urb); -- usb_free_urb(as->usbin.surb[1].urb); -- usb_free_urb(as->usbout.durb[0].urb); -- usb_free_urb(as->usbout.durb[1].urb); -- usb_free_urb(as->usbout.surb[0].urb); -- usb_free_urb(as->usbout.surb[1].urb); -- kfree(as); -- return; -- } -- as->state = s; -- as->usbin.interface = asifin; -- as->usbout.interface = asifout; -- /* search for input formats */ -- if (asifin >= 0) { -- as->usbin.flags = FLG_CONNECTED; -- iface = usb_ifnum_to_if(dev, asifin); -- for (idx = 0; idx < iface->num_altsetting; idx++) { -- alts = &iface->altsetting[idx]; -- i = alts->desc.bAlternateSetting; -- if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) -- continue; -- if (alts->desc.bNumEndpoints < 1) { -- if (i != 0) { /* altsetting 0 has no endpoints (Section B.3.4.1) */ -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", -- dev->devnum, asifin, i); -- } -- continue; -- } -- if ((alts->endpoint[0].desc.bmAttributes & 0x03) != 0x01 || -- !(alts->endpoint[0].desc.bEndpointAddress & 0x80)) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous in\n", -- dev->devnum, asifin, i); -- continue; -- } -- fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifin, i); -- if (!fmt) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", -- dev->devnum, asifin, i); -- continue; -- } -- if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", -- dev->devnum, asifin, i); -- continue; -- } -- format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); -- fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i); -- if (!fmt) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", -- dev->devnum, asifin, i); -- continue; -- } -- if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", -- dev->devnum, asifin, i); -- continue; -- } -- if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", -- dev->devnum, asifin, i, fmt[4], fmt[5]); -- continue; -- } -- csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifin, i); -- if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", -- dev->devnum, asifin, i); -- continue; -- } -- if (as->numfmtin >= MAXFORMATS) -- continue; -- fp = &as->fmtin[as->numfmtin++]; -- if (fmt[5] == 2) -- format &= (AFMT_U16_LE | AFMT_S16_LE); -- else -- format &= (AFMT_U8 | AFMT_S8); -- if (fmt[4] == 2) -- format |= AFMT_STEREO; -- fp->format = format; -- fp->altsetting = i; -- fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); -- printk(KERN_INFO "usbaudio: valid input sample rate %u\n", fp->sratelo); -- for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) { -- k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16); -- printk(KERN_INFO "usbaudio: valid input sample rate %u\n", k); -- if (k > fp->sratehi) -- fp->sratehi = k; -- if (k < fp->sratelo) -- fp->sratelo = k; -- } -- fp->attributes = csep[3]; -- printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", -- dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes); -- } -- } -- /* search for output formats */ -- if (asifout >= 0) { -- as->usbout.flags = FLG_CONNECTED; -- iface = usb_ifnum_to_if(dev, asifout); -- for (idx = 0; idx < iface->num_altsetting; idx++) { -- alts = &iface->altsetting[idx]; -- i = alts->desc.bAlternateSetting; -- if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) -- continue; -- if (alts->desc.bNumEndpoints < 1) { -- /* altsetting 0 should never have iso EPs */ -- if (i != 0) -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", -- dev->devnum, asifout, i); -- continue; -- } -- if ((alts->endpoint[0].desc.bmAttributes & 0x03) != 0x01 || -- (alts->endpoint[0].desc.bEndpointAddress & 0x80)) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous out\n", -- dev->devnum, asifout, i); -- continue; -- } -- /* See USB audio formats manual, section 2 */ -- fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifout, i); -- if (!fmt) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", -- dev->devnum, asifout, i); -- continue; -- } -- if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", -- dev->devnum, asifout, i); -- continue; -- } -- format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); -- /* Dallas DS4201 workaround */ -- if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && -- le16_to_cpu(dev->descriptor.idProduct) == 0x4201) -- format = (AFMT_S16_LE | AFMT_S8); -- fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i); -- if (!fmt) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", -- dev->devnum, asifout, i); -- continue; -- } -- if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", -- dev->devnum, asifout, i); -- continue; -- } -- if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", -- dev->devnum, asifout, i, fmt[4], fmt[5]); -- continue; -- } -- csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifout, i); -- if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { -- printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", -- dev->devnum, asifout, i); -- continue; -- } -- if (as->numfmtout >= MAXFORMATS) -- continue; -- fp = &as->fmtout[as->numfmtout++]; -- if (fmt[5] == 2) -- format &= (AFMT_U16_LE | AFMT_S16_LE); -- else -- format &= (AFMT_U8 | AFMT_S8); -- if (fmt[4] == 2) -- format |= AFMT_STEREO; -- fp->format = format; -- fp->altsetting = i; -- fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16); -- printk(KERN_INFO "usbaudio: valid output sample rate %u\n", fp->sratelo); -- for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) { -- k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16); -- printk(KERN_INFO "usbaudio: valid output sample rate %u\n", k); -- if (k > fp->sratehi) -- fp->sratehi = k; -- if (k < fp->sratelo) -- fp->sratelo = k; -- } -- fp->attributes = csep[3]; -- printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", -- dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes); -- } -- } -- if (as->numfmtin == 0 && as->numfmtout == 0) { -- usb_free_urb(as->usbin.durb[0].urb); -- usb_free_urb(as->usbin.durb[1].urb); -- usb_free_urb(as->usbin.surb[0].urb); -- usb_free_urb(as->usbin.surb[1].urb); -- usb_free_urb(as->usbout.durb[0].urb); -- usb_free_urb(as->usbout.durb[1].urb); -- usb_free_urb(as->usbout.surb[0].urb); -- usb_free_urb(as->usbout.surb[1].urb); -- kfree(as); -- return; -- } -- if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) { -- printk(KERN_ERR "usbaudio: cannot register dsp\n"); -- usb_free_urb(as->usbin.durb[0].urb); -- usb_free_urb(as->usbin.durb[1].urb); -- usb_free_urb(as->usbin.surb[0].urb); -- usb_free_urb(as->usbin.surb[1].urb); -- usb_free_urb(as->usbout.durb[0].urb); -- usb_free_urb(as->usbout.durb[1].urb); -- usb_free_urb(as->usbout.surb[0].urb); -- usb_free_urb(as->usbout.surb[1].urb); -- kfree(as); -- return; -- } -- printk(KERN_INFO "usbaudio: registered dsp 14,%d\n", as->dev_audio); -- /* everything successful */ -- list_add_tail(&as->list, &s->audiolist); --} -- --struct consmixstate { -- struct usb_audio_state *s; -- unsigned char *buffer; -- unsigned int buflen; -- unsigned int ctrlif; -- struct mixerchannel mixch[SOUND_MIXER_NRDEVICES]; -- unsigned int nrmixch; -- unsigned int mixchmask; -- unsigned long unitbitmap[32/sizeof(unsigned long)]; -- /* return values */ -- unsigned int nrchannels; -- unsigned int termtype; -- unsigned int chconfig; --}; -- --static struct mixerchannel *getmixchannel(struct consmixstate *state, unsigned int nr) --{ -- struct mixerchannel *c; -- -- if (nr >= SOUND_MIXER_NRDEVICES) { -- printk(KERN_ERR "usbaudio: invalid OSS mixer channel %u\n", nr); -- return NULL; -- } -- if (!(state->mixchmask & (1 << nr))) { -- printk(KERN_WARNING "usbaudio: OSS mixer channel %u already in use\n", nr); -- return NULL; -- } -- c = &state->mixch[state->nrmixch++]; -- c->osschannel = nr; -- state->mixchmask &= ~(1 << nr); -- return c; --} -- --static unsigned int getvolchannel(struct consmixstate *state) --{ -- unsigned int u; -- -- if ((state->termtype & 0xff00) == 0x0000 && (state->mixchmask & SOUND_MASK_VOLUME)) -- return SOUND_MIXER_VOLUME; -- if ((state->termtype & 0xff00) == 0x0100) { -- if (state->mixchmask & SOUND_MASK_PCM) -- return SOUND_MIXER_PCM; -- if (state->mixchmask & SOUND_MASK_ALTPCM) -- return SOUND_MIXER_ALTPCM; -- } -- if ((state->termtype & 0xff00) == 0x0200 && (state->mixchmask & SOUND_MASK_MIC)) -- return SOUND_MIXER_MIC; -- if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER)) -- return SOUND_MIXER_SPEAKER; -- if ((state->termtype & 0xff00) == 0x0500) { -- if (state->mixchmask & SOUND_MASK_PHONEIN) -- return SOUND_MIXER_PHONEIN; -- if (state->mixchmask & SOUND_MASK_PHONEOUT) -- return SOUND_MIXER_PHONEOUT; -- } -- if (state->termtype >= 0x710 && state->termtype <= 0x711 && (state->mixchmask & SOUND_MASK_RADIO)) -- return SOUND_MIXER_RADIO; -- if (state->termtype >= 0x709 && state->termtype <= 0x70f && (state->mixchmask & SOUND_MASK_VIDEO)) -- return SOUND_MIXER_VIDEO; -- u = ffs(state->mixchmask & (SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_LINE3 | -- SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 | SOUND_MASK_DIGITAL3)); -- return u-1; --} -- --static void prepmixch(struct consmixstate *state) --{ -- struct usb_device *dev = state->s->usbdev; -- struct mixerchannel *ch; -- unsigned char *buf; -- __s16 v1; -- unsigned int v2, v3; -- -- if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES) -- return; -- buf = kmalloc(sizeof(*buf) * 2, GFP_KERNEL); -- if (!buf) { -- printk(KERN_ERR "prepmixch: out of memory\n") ; -- return; -- } -- -- ch = &state->mixch[state->nrmixch-1]; -- switch (ch->selector) { -- case 0: /* mixer unit request */ -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- ch->minval = buf[0] | (buf[1] << 8); -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- ch->maxval = buf[0] | (buf[1] << 8); -- v2 = ch->maxval - ch->minval; -- if (!v2) -- v2 = 1; -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- v1 = buf[0] | (buf[1] << 8); -- v3 = v1 - ch->minval; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- ch->value = v3; -- if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)), -- state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- v1 = buf[0] | (buf[1] << 8); -- v3 = v1 - ch->minval; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- } -- ch->value |= v3 << 8; -- break; -- -- /* various feature unit controls */ -- case VOLUME_CONTROL: -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- ch->minval = buf[0] | (buf[1] << 8); -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- ch->maxval = buf[0] | (buf[1] << 8); -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- v1 = buf[0] | (buf[1] << 8); -- v2 = ch->maxval - ch->minval; -- v3 = v1 - ch->minval; -- if (!v2) -- v2 = 1; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- ch->value = v3; -- if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0) -- goto err; -- v1 = buf[0] | (buf[1] << 8); -- v3 = v1 - ch->minval; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- } -- ch->value |= v3 << 8; -- break; -- -- case BASS_CONTROL: -- case MID_CONTROL: -- case TREBLE_CONTROL: -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) -- goto err; -- ch->minval = buf[0] << 8; -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) -- goto err; -- ch->maxval = buf[0] << 8; -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) -- goto err; -- v1 = buf[0] << 8; -- v2 = ch->maxval - ch->minval; -- v3 = v1 - ch->minval; -- if (!v2) -- v2 = 1; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- ch->value = v3; -- if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) { -- if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -- (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0) -- goto err; -- v1 = buf[0] << 8; -- v3 = v1 - ch->minval; -- v3 = 100 * v3 / v2; -- if (v3 > 100) -- v3 = 100; -- } -- ch->value |= v3 << 8; -- break; -- -- default: -- goto err; -- } -- -- freebuf: -- kfree(buf); -- return; -- err: -- printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", -- dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector); -- if (state->nrmixch) -- state->nrmixch--; -- goto freebuf; --} -- -- --static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid); -- --static inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch) --{ -- unsigned int idx; -- -- idx = inidx*numoch; -- if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7)))) -- return 0; -- if (!(flg & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) -- return 1; -- idx = (inidx+!!(flg & MIXFLG_STEREOIN))*numoch+!!(flg & MIXFLG_STEREOOUT); -- if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7)))) -- return 0; -- return 1; --} -- --static void usb_audio_mixerunit(struct consmixstate *state, unsigned char *mixer) --{ -- unsigned int nroutch = mixer[5+mixer[4]]; -- unsigned int chidx[SOUND_MIXER_NRDEVICES+1]; -- unsigned int termt[SOUND_MIXER_NRDEVICES]; -- unsigned char flg = (nroutch >= 2) ? MIXFLG_STEREOOUT : 0; -- unsigned char *bmap = &mixer[9+mixer[4]]; -- unsigned int bmapsize; -- struct mixerchannel *ch; -- unsigned int i; -- -- if (!mixer[4]) { -- printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]); -- return; -- } -- if (mixer[4] > SOUND_MIXER_NRDEVICES) { -- printk(KERN_ERR "usbaudio: mixer unit %u: too many input pins\n", mixer[3]); -- return; -- } -- chidx[0] = 0; -- for (i = 0; i < mixer[4]; i++) { -- usb_audio_recurseunit(state, mixer[5+i]); -- chidx[i+1] = chidx[i] + state->nrchannels; -- termt[i] = state->termtype; -- } -- state->termtype = 0; -- state->chconfig = mixer[6+mixer[4]] | (mixer[7+mixer[4]] << 8); -- bmapsize = (nroutch * chidx[mixer[4]] + 7) >> 3; -- bmap += bmapsize - 1; -- if (mixer[0] < 10+mixer[4]+bmapsize) { -- printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]); -- return; -- } -- for (i = 0; i < mixer[4]; i++) { -- state->termtype = termt[i]; -- if (chidx[i+1]-chidx[i] >= 2) { -- flg |= MIXFLG_STEREOIN; -- if (checkmixbmap(bmap, flg, chidx[i], nroutch)) { -- ch = getmixchannel(state, getvolchannel(state)); -- if (ch) { -- ch->unitid = mixer[3]; -- ch->selector = 0; -- ch->chnum = chidx[i]+1; -- ch->flags = flg; -- prepmixch(state); -- } -- continue; -- } -- } -- flg &= ~MIXFLG_STEREOIN; -- if (checkmixbmap(bmap, flg, chidx[i], nroutch)) { -- ch = getmixchannel(state, getvolchannel(state)); -- if (ch) { -- ch->unitid = mixer[3]; -- ch->selector = 0; -- ch->chnum = chidx[i]+1; -- ch->flags = flg; -- prepmixch(state); -- } -- } -- } -- state->termtype = 0; --} -- --static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid) --{ -- unsigned int i; -- -- for (i = 0; i < state->nrmixch; i++) -- if (state->mixch[i].unitid == unitid) -- return &state->mixch[i]; -- return NULL; --} -- --static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector) --{ -- unsigned int chnum, i, mixch; -- struct mixerchannel *mch; -- -- if (!selector[4]) { -- printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]); -- return; -- } -- mixch = state->nrmixch; -- usb_audio_recurseunit(state, selector[5]); -- if (state->nrmixch != mixch) { -- mch = &state->mixch[state->nrmixch-1]; -- mch->slctunitid = selector[3] | (1 << 8); -- } else if ((mch = slctsrc_findunit(state, selector[5]))) { -- mch->slctunitid = selector[3] | (1 << 8); -- } else { -- printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]); -- } -- chnum = state->nrchannels; -- for (i = 1; i < selector[4]; i++) { -- mixch = state->nrmixch; -- usb_audio_recurseunit(state, selector[5+i]); -- if (chnum != state->nrchannels) { -- printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]); -- state->termtype = 0; -- state->chconfig = 0; -- state->nrchannels = 0; -- return; -- } -- if (state->nrmixch != mixch) { -- mch = &state->mixch[state->nrmixch-1]; -- mch->slctunitid = selector[3] | ((i + 1) << 8); -- } else if ((mch = slctsrc_findunit(state, selector[5+i]))) { -- mch->slctunitid = selector[3] | ((i + 1) << 8); -- } else { -- printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1); -- } -- } -- state->termtype = 0; -- state->chconfig = 0; --} -- --/* in the future we might try to handle 3D etc. effect units */ -- --static void usb_audio_processingunit(struct consmixstate *state, unsigned char *proc) --{ -- unsigned int i; -- -- for (i = 0; i < proc[6]; i++) -- usb_audio_recurseunit(state, proc[7+i]); -- state->nrchannels = proc[7+proc[6]]; -- state->termtype = 0; -- state->chconfig = proc[8+proc[6]] | (proc[9+proc[6]] << 8); --} -- -- --/* See Audio Class Spec, section 4.3.2.5 */ --static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr) --{ -- struct mixerchannel *ch; -- unsigned short chftr, mchftr; --#if 0 -- struct usb_device *dev = state->s->usbdev; -- unsigned char data[1]; --#endif -- unsigned char nr_logical_channels, i; -- -- usb_audio_recurseunit(state, ftr[4]); -- -- if (ftr[5] == 0 ) { -- printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]); -- return; -- } -- -- if (state->nrchannels == 0) { -- printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]); -- return; -- } -- if (state->nrchannels > 2) -- printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]); -- -- nr_logical_channels=(ftr[0]-7)/ftr[5]-1; -- -- if (nr_logical_channels != state->nrchannels) { -- printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels); -- -- if (state->nrchannels == 1 && nr_logical_channels==0) { -- printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n"); -- } else if (state->nrchannels == 1 && nr_logical_channels==2) { -- printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n"); -- state->nrchannels=nr_logical_channels; -- } else { -- printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n"); -- } -- } -- -- /* There is always a master channel */ -- mchftr = ftr[6]; -- /* Binary AND over logical channels if they exist */ -- if (nr_logical_channels) { -- chftr = ftr[6+ftr[5]]; -- for (i = 2; i <= nr_logical_channels; i++) -- chftr &= ftr[6+i*ftr[5]]; -- } else { -- chftr = 0; -- } -- -- /* volume control */ -- if (chftr & 2) { -- ch = getmixchannel(state, getvolchannel(state)); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = VOLUME_CONTROL; -- ch->chnum = 1; -- ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; -- prepmixch(state); -- } -- } else if (mchftr & 2) { -- ch = getmixchannel(state, getvolchannel(state)); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = VOLUME_CONTROL; -- ch->chnum = 0; -- ch->flags = 0; -- prepmixch(state); -- } -- } -- /* bass control */ -- if (chftr & 4) { -- ch = getmixchannel(state, SOUND_MIXER_BASS); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = BASS_CONTROL; -- ch->chnum = 1; -- ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; -- prepmixch(state); -- } -- } else if (mchftr & 4) { -- ch = getmixchannel(state, SOUND_MIXER_BASS); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = BASS_CONTROL; -- ch->chnum = 0; -- ch->flags = 0; -- prepmixch(state); -- } -- } -- /* treble control */ -- if (chftr & 16) { -- ch = getmixchannel(state, SOUND_MIXER_TREBLE); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = TREBLE_CONTROL; -- ch->chnum = 1; -- ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0; -- prepmixch(state); -- } -- } else if (mchftr & 16) { -- ch = getmixchannel(state, SOUND_MIXER_TREBLE); -- if (ch) { -- ch->unitid = ftr[3]; -- ch->selector = TREBLE_CONTROL; -- ch->chnum = 0; -- ch->flags = 0; -- prepmixch(state); -- } -- } --#if 0 -- /* if there are mute controls, unmute them */ -- /* does not seem to be necessary, and the Dallas chip does not seem to support the "all" channel (255) */ -- if ((chftr & 1) || (mchftr & 1)) { -- printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif); -- data[0] = 0; -- if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, 1000) < 0) -- printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif); -- } --#endif --} -- --static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid) --{ -- unsigned char *p1; -- unsigned int i, j; -- -- if (test_and_set_bit(unitid, state->unitbitmap)) { -- printk(KERN_INFO "usbaudio: mixer path revisits unit %d\n", unitid); -- return; -- } -- p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif); -- if (!p1) { -- printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid); -- return; -- } -- state->nrchannels = 0; -- state->termtype = 0; -- state->chconfig = 0; -- switch (p1[2]) { -- case INPUT_TERMINAL: -- if (p1[0] < 12) { -- printk(KERN_ERR "usbaudio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid); -- return; -- } -- state->nrchannels = p1[7]; -- state->termtype = p1[4] | (p1[5] << 8); -- state->chconfig = p1[8] | (p1[9] << 8); -- return; -- -- case MIXER_UNIT: -- if (p1[0] < 10 || p1[0] < 10+p1[4]) { -- printk(KERN_ERR "usbaudio: unit %u: invalid MIXER_UNIT descriptor\n", unitid); -- return; -- } -- usb_audio_mixerunit(state, p1); -- return; -- -- case SELECTOR_UNIT: -- if (p1[0] < 6 || p1[0] < 6+p1[4]) { -- printk(KERN_ERR "usbaudio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid); -- return; -- } -- usb_audio_selectorunit(state, p1); -- return; -- -- case FEATURE_UNIT: /* See USB Audio Class Spec 4.3.2.5 */ -- if (p1[0] < 7 || p1[0] < 7+p1[5]) { -- printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); -- return; -- } -- usb_audio_featureunit(state, p1); -- return; -- -- case PROCESSING_UNIT: -- if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) { -- printk(KERN_ERR "usbaudio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid); -- return; -- } -- usb_audio_processingunit(state, p1); -- return; -- -- case EXTENSION_UNIT: -- if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) { -- printk(KERN_ERR "usbaudio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid); -- return; -- } -- for (j = i = 0; i < p1[6]; i++) { -- usb_audio_recurseunit(state, p1[7+i]); -- if (!i) -- j = state->termtype; -- else if (j != state->termtype) -- j = 0; -- } -- state->nrchannels = p1[7+p1[6]]; -- state->chconfig = p1[8+p1[6]] | (p1[9+p1[6]] << 8); -- state->termtype = j; -- return; -- -- default: -- printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); -- return; -- } --} -- --static void usb_audio_constructmixer(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif, unsigned char *oterm) --{ -- struct usb_mixerdev *ms; -- struct consmixstate state; -- -- memset(&state, 0, sizeof(state)); -- state.s = s; -- state.nrmixch = 0; -- state.mixchmask = ~0; -- state.buffer = buffer; -- state.buflen = buflen; -- state.ctrlif = ctrlif; -- set_bit(oterm[3], state.unitbitmap); /* mark terminal ID as visited */ -- printk(KERN_DEBUG "usbaudio: constructing mixer for Terminal %u type 0x%04x\n", -- oterm[3], oterm[4] | (oterm[5] << 8)); -- usb_audio_recurseunit(&state, oterm[7]); -- if (!state.nrmixch) { -- printk(KERN_INFO "usbaudio: no mixer controls found for Terminal %u\n", oterm[3]); -- return; -- } -- if (!(ms = kmalloc(sizeof(struct usb_mixerdev)+state.nrmixch*sizeof(struct mixerchannel), GFP_KERNEL))) -- return; -- memset(ms, 0, sizeof(struct usb_mixerdev)); -- memcpy(&ms->ch, &state.mixch, state.nrmixch*sizeof(struct mixerchannel)); -- ms->state = s; -- ms->iface = ctrlif; -- ms->numch = state.nrmixch; -- if ((ms->dev_mixer = register_sound_mixer(&usb_mixer_fops, -1)) < 0) { -- printk(KERN_ERR "usbaudio: cannot register mixer\n"); -- kfree(ms); -- return; -- } -- printk(KERN_INFO "usbaudio: registered mixer 14,%d\n", ms->dev_mixer); -- list_add_tail(&ms->list, &s->mixerlist); --} -- --/* arbitrary limit, we won't check more interfaces than this */ --#define USB_MAXINTERFACES 32 -- --static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif) --{ -- struct usb_audio_state *s; -- struct usb_interface *iface; -- struct usb_host_interface *alt; -- unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES]; -- unsigned char *p1; -- unsigned int i, j, k, numifin = 0, numifout = 0; -- -- if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL))) -- return NULL; -- memset(s, 0, sizeof(struct usb_audio_state)); -- INIT_LIST_HEAD(&s->audiolist); -- INIT_LIST_HEAD(&s->mixerlist); -- s->usbdev = dev; -- s->count = 1; -- -- /* find audiocontrol interface */ -- if (!(p1 = find_csinterface_descriptor(buffer, buflen, NULL, HEADER, ctrlif, -1))) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u no HEADER found\n", -- dev->devnum, ctrlif); -- goto ret; -- } -- if (p1[0] < 8 + p1[7]) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u HEADER error\n", -- dev->devnum, ctrlif); -- goto ret; -- } -- if (!p1[7]) -- printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n", -- dev->devnum, ctrlif); -- for (i = 0; i < p1[7]; i++) { -- j = p1[8+i]; -- iface = usb_ifnum_to_if(dev, j); -- if (!iface) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (iface->num_altsetting == 1) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif); -- continue; -- } -- alt = usb_altnum_to_altsetting(iface, 0); -- if (!alt) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 0\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (alt->desc.bInterfaceClass != USB_CLASS_AUDIO) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (alt->desc.bInterfaceSubClass == 3) { -- printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (alt->desc.bInterfaceSubClass != 2) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (alt->desc.bNumEndpoints > 0) { -- /* Check all endpoints; should they all have a bandwidth of 0 ? */ -- for (k = 0; k < alt->desc.bNumEndpoints; k++) { -- if (le16_to_cpu(alt->endpoint[k].desc.wMaxPacketSize) > 0) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k); -- break; -- } -- } -- if (k < alt->desc.bNumEndpoints) -- continue; -- } -- -- alt = usb_altnum_to_altsetting(iface, 1); -- if (!alt) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 1\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- if (alt->desc.bNumEndpoints < 1) { -- printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n", -- dev->devnum, ctrlif, j); -- continue; -- } -- /* note: this requires the data endpoint to be ep0 and the optional sync -- ep to be ep1, which seems to be the case */ -- if (alt->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) { -- if (numifin < USB_MAXINTERFACES) { -- ifin[numifin++] = j; -- usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); -- } -- } else { -- if (numifout < USB_MAXINTERFACES) { -- ifout[numifout++] = j; -- usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); -- } -- } -- } -- printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n", -- dev->devnum, ctrlif, numifin, numifout); -- for (i = 0; i < numifin && i < numifout; i++) -- usb_audio_parsestreaming(s, buffer, buflen, ifin[i], ifout[i]); -- for (j = i; j < numifin; j++) -- usb_audio_parsestreaming(s, buffer, buflen, ifin[i], -1); -- for (j = i; j < numifout; j++) -- usb_audio_parsestreaming(s, buffer, buflen, -1, ifout[i]); -- /* now walk through all OUTPUT_TERMINAL descriptors to search for mixers */ -- p1 = find_csinterface_descriptor(buffer, buflen, NULL, OUTPUT_TERMINAL, ctrlif, -1); -- while (p1) { -- if (p1[0] >= 9) -- usb_audio_constructmixer(s, buffer, buflen, ctrlif, p1); -- p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, ctrlif, -1); -- } -- --ret: -- if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) { -- kfree(s); -- return NULL; -- } -- /* everything successful */ -- down(&open_sem); -- list_add_tail(&s->audiodev, &audiodevs); -- up(&open_sem); -- printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s); -- return s; --} -- --/* we only care for the currently active configuration */ -- --static int usb_audio_probe(struct usb_interface *intf, -- const struct usb_device_id *id) --{ -- struct usb_device *dev = interface_to_usbdev (intf); -- struct usb_audio_state *s; -- unsigned char *buffer; -- unsigned int buflen; -- --#if 0 -- printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum, -- config->interface[ifnum].altsetting[0].desc.bInterfaceClass, -- config->interface[ifnum].altsetting[0].desc.bInterfaceSubClass); --#endif -- -- /* -- * audiocontrol interface found -- * find which configuration number is active -- */ -- buffer = dev->rawdescriptors[dev->actconfig - dev->config]; -- buflen = le16_to_cpu(dev->actconfig->desc.wTotalLength); -- s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber); -- if (s) { -- usb_set_intfdata (intf, s); -- return 0; -- } -- return -ENODEV; --} -- -- --/* a revoke facility would make things simpler */ -- --static void usb_audio_disconnect(struct usb_interface *intf) --{ -- struct usb_audio_state *s = usb_get_intfdata (intf); -- struct usb_audiodev *as; -- struct usb_mixerdev *ms; -- -- if (!s) -- return; -- -- /* we get called with -1 for every audiostreaming interface registered */ -- if (s == (struct usb_audio_state *)-1) { -- dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with -1\n")); -- return; -- } -- if (!s->usbdev) { -- dprintk((KERN_DEBUG "usbaudio: error, usb_audio_disconnect already called for %p!\n", s)); -- return; -- } -- down(&open_sem); -- list_del_init(&s->audiodev); -- s->usbdev = NULL; -- usb_set_intfdata (intf, NULL); -- -- /* deregister all audio and mixer devices, so no new processes can open this device */ -- list_for_each_entry(as, &s->audiolist, list) { -- usbin_disc(as); -- usbout_disc(as); -- wake_up(&as->usbin.dma.wait); -- wake_up(&as->usbout.dma.wait); -- if (as->dev_audio >= 0) { -- unregister_sound_dsp(as->dev_audio); -- printk(KERN_INFO "usbaudio: unregister dsp 14,%d\n", as->dev_audio); -- } -- as->dev_audio = -1; -- } -- list_for_each_entry(ms, &s->mixerlist, list) { -- if (ms->dev_mixer >= 0) { -- unregister_sound_mixer(ms->dev_mixer); -- printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer); -- } -- ms->dev_mixer = -1; -- } -- release(s); -- wake_up(&open_wait); --} -- --static int __init usb_audio_init(void) --{ -- int result = usb_register(&usb_audio_driver); -- if (result == 0) -- info(DRIVER_VERSION ":" DRIVER_DESC); -- return result; --} -- -- --static void __exit usb_audio_cleanup(void) --{ -- usb_deregister(&usb_audio_driver); --} -- --module_init(usb_audio_init); --module_exit(usb_audio_cleanup); -- --MODULE_AUTHOR( DRIVER_AUTHOR ); --MODULE_DESCRIPTION( DRIVER_DESC ); --MODULE_LICENSE("GPL"); -- ---- gregkh-2.6.orig/drivers/usb/class/audio.h -+++ /dev/null -@@ -1,110 +0,0 @@ --#define CS_AUDIO_UNDEFINED 0x20 --#define CS_AUDIO_DEVICE 0x21 --#define CS_AUDIO_CONFIGURATION 0x22 --#define CS_AUDIO_STRING 0x23 --#define CS_AUDIO_INTERFACE 0x24 --#define CS_AUDIO_ENDPOINT 0x25 -- --#define HEADER 0x01 --#define INPUT_TERMINAL 0x02 --#define OUTPUT_TERMINAL 0x03 --#define MIXER_UNIT 0x04 --#define SELECTOR_UNIT 0x05 --#define FEATURE_UNIT 0x06 --#define PROCESSING_UNIT 0x07 --#define EXTENSION_UNIT 0x08 -- --#define AS_GENERAL 0x01 --#define FORMAT_TYPE 0x02 --#define FORMAT_SPECIFIC 0x03 -- --#define EP_GENERAL 0x01 -- --#define MAX_CHAN 9 --#define MAX_FREQ 16 --#define MAX_IFACE 8 --#define MAX_FORMAT 8 --#define MAX_ALT 32 /* Sorry, we need quite a few for the Philips webcams */ -- --struct usb_audio_terminal --{ -- u8 flags; -- u8 assoc; -- u16 type; /* Mic etc */ -- u8 channels; -- u8 source; -- u16 chancfg; --}; -- --struct usb_audio_format --{ -- u8 type; -- u8 channels; -- u8 num_freq; -- u8 sfz; -- u8 bits; -- u16 freq[MAX_FREQ]; --}; -- --struct usb_audio_interface --{ -- u8 terminal; -- u8 delay; -- u16 num_formats; -- u16 format_type; -- u8 flags; -- u8 idleconf; /* Idle config */ --#define AU_IFACE_FOUND 1 -- struct usb_audio_format format[MAX_FORMAT]; --}; -- --struct usb_audio_device --{ -- struct list_head list; -- u8 mixer; -- u8 selector; -- void *irq_handle; -- u8 num_channels; -- u8 num_dsp_iface; -- u8 channel_map[MAX_CHAN]; -- struct usb_audio_terminal terminal[MAX_CHAN]; -- struct usb_audio_interface interface[MAX_IFACE][MAX_ALT]; --}; -- -- -- --/* Audio Class specific Request Codes */ -- --#define SET_CUR 0x01 --#define GET_CUR 0x81 --#define SET_MIN 0x02 --#define GET_MIN 0x82 --#define SET_MAX 0x03 --#define GET_MAX 0x83 --#define SET_RES 0x04 --#define GET_RES 0x84 --#define SET_MEM 0x05 --#define GET_MEM 0x85 --#define GET_STAT 0xff -- --/* Terminal Control Selectors */ -- --#define COPY_PROTECT_CONTROL 0x01 -- --/* Feature Unit Control Selectors */ -- --#define MUTE_CONTROL 0x01 --#define VOLUME_CONTROL 0x02 --#define BASS_CONTROL 0x03 --#define MID_CONTROL 0x04 --#define TREBLE_CONTROL 0x05 --#define GRAPHIC_EQUALIZER_CONTROL 0x06 --#define AUTOMATIC_GAIN_CONTROL 0x07 --#define DELAY_CONTROL 0x08 --#define BASS_BOOST_CONTROL 0x09 --#define LOUDNESS_CONTROL 0x0a -- --/* Endpoint Control Selectors */ -- --#define SAMPLING_FREQ_CONTROL 0x01 --#define PITCH_CONTROL 0x02 ---- gregkh-2.6.orig/drivers/usb/class/usb-midi.c -+++ /dev/null -@@ -1,2153 +0,0 @@ --/* -- usb-midi.c -- USB-MIDI driver -- -- Copyright (C) 2001 -- NAGANO Daisuke <breeze.nagano@nifty.ne.jp> -- -- 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, or (at your option) -- any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- -- This driver is based on: -- - 'Universal Serial Bus Device Class Definition for MIDI Device' -- - linux/drivers/sound/es1371.c, linux/drivers/usb/audio.c -- - alsa/lowlevel/pci/cs64xx.c -- - umidi.c for NetBSD -- */ -- --/* ------------------------------------------------------------------------- */ -- -- --#include <linux/module.h> --#include <linux/kernel.h> --#include <linux/sched.h> --#include <linux/list.h> --#include <linux/slab.h> --#include <linux/usb.h> --#include <linux/poll.h> --#include <linux/sound.h> --#include <linux/init.h> --#include <asm/semaphore.h> -- --#include "usb-midi.h" -- --/* ------------------------------------------------------------------------- */ -- --/* More verbose on syslog */ --#undef MIDI_DEBUG -- --#define MIDI_IN_BUFSIZ 1024 -- --#define HAVE_SUPPORT_USB_MIDI_CLASS -- --#undef HAVE_SUPPORT_ALSA -- --/* ------------------------------------------------------------------------- */ -- --static int singlebyte = 0; --module_param(singlebyte, int, 0); --MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet"); -- --static int maxdevices = 4; --module_param(maxdevices, int, 0); --MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device"); -- --static int uvendor = -1; --module_param(uvendor, int, 0); --MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface"); -- --static int uproduct = -1; --module_param(uproduct, int, 0); --MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface"); -- --static int uinterface = -1; --module_param(uinterface, int, 0); --MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface"); -- --static int ualt = -1; --module_param(ualt, int, 0); --MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface"); -- --static int umin = -1; --module_param(umin, int, 0); --MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface"); -- --static int umout = -1; --module_param(umout, int, 0); --MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface"); -- --static int ucable = -1; --module_param(ucable, int, 0); --MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface"); -- --/** Note -- the usb_string() returns only Latin-1 characters. -- * (unicode chars <= 255). To support Japanese, a unicode16LE-to-EUC or -- * unicode16LE-to-JIS routine is needed to wrap around usb_get_string(). -- **/ --static unsigned short ulangid = 0x0409; /** 0x0411 for Japanese **/ --module_param(ulangid, ushort, 0); --MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices"); -- --MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>"); --MODULE_DESCRIPTION("USB-MIDI driver"); --MODULE_LICENSE("GPL"); -- --/* ------------------------------------------------------------------------- */ -- --/** MIDIStreaming Class-Specific Interface Descriptor Subtypes **/ -- --#define MS_DESCRIPTOR_UNDEFINED 0 --#define MS_HEADER 1 --#define MIDI_IN_JACK 2 --#define MIDI_OUT_JACK 3 --/* Spec reads: ELEMENT */ --#define ELEMENT_DESCRIPTOR 4 -- --#define MS_HEADER_LENGTH 7 -- --/** MIDIStreaming Class-Specific Endpoint Descriptor Subtypes **/ -- --#define DESCRIPTOR_UNDEFINED 0 --/* Spec reads: MS_GENERAL */ --#define MS_GENERAL_ENDPOINT 1 -- --/** MIDIStreaming MIDI IN and OUT Jack Types **/ -- --#define JACK_TYPE_UNDEFINED 0 --/* Spec reads: EMBEDDED */ --#define EMBEDDED_JACK 1 --/* Spec reads: EXTERNAL */ --#define EXTERNAL_JACK 2 -- -- --/* structure summary -- -- usb_midi_state usb_device -- | | -- *| *| per ep -- in_ep out_ep -- | | -- *| *| per cable -- min mout -- | | (cable to device pairing magic) -- | | -- usb_midi_dev dev_id (major,minor) == file->private_data -- --*/ -- --/* usb_midi_state: corresponds to a USB-MIDI module */ --struct usb_midi_state { -- struct list_head mididev; -- -- struct usb_device *usbdev; -- -- struct list_head midiDevList; -- struct list_head inEndpointList; -- struct list_head outEndpointList; -- -- spinlock_t lock; -- -- unsigned int count; /* usage counter */ --}; -- --/* midi_out_endpoint: corresponds to an output endpoint */ --struct midi_out_endpoint { -- struct list_head list; -- -- struct usb_device *usbdev; -- int endpoint; -- spinlock_t lock; -- wait_queue_head_t wait; -- -- unsigned char *buf; -- int bufWrPtr; -- int bufSize; -- -- struct urb *urb; --}; -- --/* midi_in_endpoint: corresponds to an input endpoint */ --struct midi_in_endpoint { -- struct list_head list; -- -- struct usb_device *usbdev; -- int endpoint; -- spinlock_t lock; -- wait_queue_head_t wait; -- -- struct usb_mididev *cables[16]; // cables open for read -- int readers; // number of cables open for read -- -- struct urb *urb; -- unsigned char *recvBuf; -- int recvBufSize; -- int urbSubmitted; //FIXME: == readers > 0 --}; -- --/* usb_mididev: corresponds to a logical device */ --struct usb_mididev { -- struct list_head list; -- -- struct usb_midi_state *midi; -- int dev_midi; -- mode_t open_mode; -- -- struct { -- struct midi_in_endpoint *ep; -- int cableId; -- --// as we are pushing data from usb_bulk_read to usb_midi_read, --// we need a larger, cyclic buffer here. -- unsigned char buf[MIDI_IN_BUFSIZ]; -- int bufRdPtr; -- int bufWrPtr; -- int bufRemains; -- } min; -- -- struct { -- struct midi_out_endpoint *ep; -- int cableId; -- -- unsigned char buf[3]; -- int bufPtr; -- int bufRemains; -- -- int isInExclusive; -- unsigned char lastEvent; -- } mout; -- -- int singlebyte; --}; -- --/** Map the high nybble of MIDI voice messages to number of Message bytes. -- * High nyble ranges from 0x8 to 0xe -- */ -- --static int remains_80e0[] = { -- 3, /** 0x8X Note Off **/ -- 3, /** 0x9X Note On **/ -- 3, /** 0xAX Poly-key pressure **/ -- 3, /** 0xBX Control Change **/ -- 2, /** 0xCX Program Change **/ -- 2, /** 0xDX Channel pressure **/ -- 3 /** 0xEX PitchBend Change **/ --}; -- --/** Map the messages to a number of Message bytes. -- * -- **/ --static int remains_f0f6[] = { -- 0, /** 0xF0 **/ -- 2, /** 0XF1 **/ -- 3, /** 0XF2 **/ -- 2, /** 0XF3 **/ -- 2, /** 0XF4 (Undefined by MIDI Spec, and subject to change) **/ -- 2, /** 0XF5 (Undefined by MIDI Spec, and subject to change) **/ -- 1 /** 0XF6 **/ --}; -- --/** Map the messages to a CIN (Code Index Number). -- * -- **/ --static int cin_f0ff[] = { -- 4, /** 0xF0 System Exclusive Message Start (special cases may be 6 or 7) */ -- 2, /** 0xF1 **/ -- 3, /** 0xF2 **/ -- 2, /** 0xF3 **/ -- 2, /** 0xF4 **/ -- 2, /** 0xF5 **/ -- 5, /** 0xF6 **/ -- 5, /** 0xF7 End of System Exclusive Message (May be 6 or 7) **/ -- 5, /** 0xF8 **/ -- 5, /** 0xF9 **/ -- 5, /** 0xFA **/ -- 5, /** 0xFB **/ -- 5, /** 0xFC **/ -- 5, /** 0xFD **/ -- 5, /** 0xFE **/ -- 5 /** 0xFF **/ --}; -- --/** Map MIDIStreaming Event packet Code Index Number (low nybble of byte 0) -- * to the number of bytes of valid MIDI data. -- * -- * CIN of 0 and 1 are NOT USED in MIDIStreaming 1.0. -- * -- **/ --static int cin_to_len[] = { -- 0, 0, 2, 3, -- 3, 1, 2, 3, -- 3, 3, 3, 3, -- 2, 2, 3, 1 --}; -- -- --/* ------------------------------------------------------------------------- */ -- --static struct list_head mididevs = LIST_HEAD_INIT(mididevs); -- --static DECLARE_MUTEX(open_sem); --static DECLARE_WAIT_QUEUE_HEAD(open_wait); -- -- --/* ------------------------------------------------------------------------- */ -- --static void usb_write_callback(struct urb *urb, struct pt_regs *regs) --{ -- struct midi_out_endpoint *ep = (struct midi_out_endpoint *)urb->context; -- -- if ( waitqueue_active( &ep->wait ) ) -- wake_up_interruptible( &ep->wait ); --} -- -- --static int usb_write( struct midi_out_endpoint *ep, unsigned char *buf, int len ) --{ -- struct usb_device *d; -- int pipe; -- int ret = 0; -- int status; -- int maxretry = 50; -- -- DECLARE_WAITQUEUE(wait,current); -- init_waitqueue_head(&ep->wait); -- -- d = ep->usbdev; -- pipe = usb_sndbulkpipe(d, ep->endpoint); -- usb_fill_bulk_urb( ep->urb, d, pipe, (unsigned char*)buf, len, -- usb_write_callback, ep ); -- -- status = usb_submit_urb(ep->urb, GFP_KERNEL); -- -- if (status) { -- printk(KERN_ERR "usbmidi: Cannot submit urb (%d)\n",status); -- ret = -EIO; -- goto error; -- } -- -- add_wait_queue( &ep->wait, &wait ); -- set_current_state( TASK_INTERRUPTIBLE ); -- -- while( ep->urb->status == -EINPROGRESS ) { -- if ( maxretry-- < 0 ) { -- printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n"); -- ret = -ETIME; -- break; -- } -- interruptible_sleep_on_timeout( &ep->wait, 10 ); -- } -- set_current_state( TASK_RUNNING ); -- remove_wait_queue( &ep->wait, &wait ); -- --error: -- return ret; --} -- -- --/** Copy data from URB to In endpoint buf. -- * Discard if CIN == 0 or CIN = 1. -- * -- * -- **/ -- --static void usb_bulk_read(struct urb *urb, struct pt_regs *regs) --{ -- struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context); -- unsigned char *data = urb->transfer_buffer; -- int i, j, wake; -- -- if ( !ep->urbSubmitted ) { -- return; -- } -- -- if ( (urb->status == 0) && (urb->actual_length > 0) ) { -- wake = 0; -- spin_lock( &ep->lock ); -- -- for(j = 0; j < urb->actual_length; j += 4) { -- int cin = (data[j]>>0)&0xf; -- int cab = (data[j]>>4)&0xf; -- struct usb_mididev *cable = ep->cables[cab]; -- if ( cable ) { -- int len = cin_to_len[cin]; /** length of MIDI data **/ -- for (i = 0; i < len; i++) { -- cable->min.buf[cable->min.bufWrPtr] = data[1+i+j]; -- cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ; -- if (cable->min.bufRemains < MIDI_IN_BUFSIZ) -- cable->min.bufRemains += 1; -- else /** need to drop data **/ -- cable->min.bufRdPtr += (cable->min.bufRdPtr+1)%MIDI_IN_BUFSIZ; -- wake = 1; -- } -- } -- } -- -- spin_unlock ( &ep->lock ); -- if ( wake ) { -- wake_up( &ep->wait ); -- } -- } -- -- /* urb->dev must be reinitialized on 2.4.x kernels */ -- urb->dev = ep->usbdev; -- -- urb->actual_length = 0; -- usb_submit_urb(urb, GFP_ATOMIC); --} -- -- -- --/* ------------------------------------------------------------------------- */ -- --/* This routine must be called with spin_lock */ -- --/** Wrapper around usb_write(). -- * This routine must be called with spin_lock held on ep. -- * Called by midiWrite(), putOneMidiEvent(), and usb_midi_write(); -- **/ --static int flush_midi_buffer( struct midi_out_endpoint *ep ) --{ -- int ret=0; -- -- if ( ep->bufWrPtr > 0 ) { -- ret = usb_write( ep, ep->buf, ep->bufWrPtr ); -- ep->bufWrPtr = 0; -- } -- -- return ret; --} -- -- --/* ------------------------------------------------------------------------- */ -- -- --/** Given a MIDI Event, determine size of data to be attached to -- * USB-MIDI packet. -- * Returns 1, 2 or 3. -- * Called by midiWrite(); -- * Uses remains_80e0 and remains_f0f6; -- **/ --static int get_remains(int event) --{ -- int ret; -- -- if ( event < 0x80 ) { -- ret = 1; -- } else if ( event < 0xf0 ) { -- ret = remains_80e0[((event-0x80)>>4)&0x0f]; -- } else if ( event < 0xf7 ) { -- ret = remains_f0f6[event-0xf0]; -- } else { -- ret = 1; -- } -- -- return ret; --} -- --/** Given the output MIDI data in the output buffer, computes a reasonable -- * CIN. -- * Called by putOneMidiEvent(). -- **/ --static int get_CIN( struct usb_mididev *m ) --{ -- int cin; -- -- if ( m->mout.buf[0] == 0xf7 ) { -- cin = 5; -- } -- else if ( m->mout.buf[1] == 0xf7 ) { -- cin = 6; -- } -- else if ( m->mout.buf[2] == 0xf7 ) { -- cin = 7; -- } -- else { -- if ( m->mout.isInExclusive == 1 ) { -- cin = 4; -- } else if ( m->mout.buf[0] < 0x80 ) { -- /** One byte that we know nothing about. **/ -- cin = 0xF; -- } else if ( m->mout.buf[0] < 0xf0 ) { -- /** MIDI Voice messages 0x8X to 0xEX map to cin 0x8 to 0xE. **/ -- cin = (m->mout.buf[0]>>4)&0x0f; -- } -- else { -- /** Special lookup table exists for real-time events. **/ -- cin = cin_f0ff[m->mout.buf[0]-0xf0]; -- } -- } -- -- return cin; --} -- -- --/* ------------------------------------------------------------------------- */ -- -- -- --/** Move data to USB endpoint buffer. -- * -- **/ --static int put_one_midi_event(struct usb_mididev *m) --{ -- int cin; -- unsigned long flags; -- struct midi_out_endpoint *ep = m->mout.ep; -- int ret=0; -- -- cin = get_CIN( m ); -- if ( cin > 0x0f || cin < 0 ) { -- return -EINVAL; -- } -- -- spin_lock_irqsave( &ep->lock, flags ); -- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | cin; -- ep->buf[ep->bufWrPtr++] = m->mout.buf[0]; -- ep->buf[ep->bufWrPtr++] = m->mout.buf[1]; -- ep->buf[ep->bufWrPtr++] = m->mout.buf[2]; -- if ( ep->bufWrPtr >= ep->bufSize ) { -- ret = flush_midi_buffer( ep ); -- } -- spin_unlock_irqrestore( &ep->lock, flags); -- -- m->mout.buf[0] = m->mout.buf[1] = m->mout.buf[2] = 0; -- m->mout.bufPtr = 0; -- -- return ret; --} -- --/** Write the MIDI message v on the midi device. -- * Called by usb_midi_write(); -- * Responsible for packaging a MIDI data stream into USB-MIDI packets. -- **/ -- --static int midi_write( struct usb_mididev *m, int v ) --{ -- unsigned long flags; -- struct midi_out_endpoint *ep = m->mout.ep; -- int ret=0; -- unsigned char c = (unsigned char)v; -- unsigned char sysrt_buf[4]; -- -- if ( m->singlebyte != 0 ) { -- /** Simple code to handle the single-byte USB-MIDI protocol. */ -- spin_lock_irqsave( &ep->lock, flags ); -- if ( ep->bufWrPtr+4 > ep->bufSize ) { -- ret = flush_midi_buffer( ep ); -- if ( !ret ) { -- spin_unlock_irqrestore( &ep->lock, flags ); -- return ret; -- } -- } -- ep->buf[ep->bufWrPtr++] = (m->mout.cableId<<4) | 0x0f; /* single byte */ -- ep->buf[ep->bufWrPtr++] = c; -- ep->buf[ep->bufWrPtr++] = 0; -- ep->buf[ep->bufWrPtr++] = 0; -- if ( ep->bufWrPtr >= ep->bufSize ) { -- ret = flush_midi_buffer( ep ); -- } -- spin_unlock_irqrestore( &ep->lock, flags ); -- -- return ret; -- } -- /** Normal USB-MIDI protocol begins here. */ -- -- if ( c > 0xf7 ) { /* system: Realtime messages */ -- /** Realtime messages are written IMMEDIATELY. */ -- sysrt_buf[0] = (m->mout.cableId<<4) | 0x0f; -- sysrt_buf[1] = c; -- sysrt_buf[2] = 0; -- sysrt_buf[3] = 0; -- spin_lock_irqsave( &ep->lock, flags ); -- ret = usb_write( ep, sysrt_buf, 4 ); -- spin_unlock_irqrestore( &ep->lock, flags ); -- /* m->mout.lastEvent = 0; */ -- -- return ret; -- } -- -- if ( c >= 0x80 ) { -- if ( c < 0xf0 ) { -- m->mout.lastEvent = c; -- m->mout.isInExclusive = 0; -- m->mout.bufRemains = get_remains(c); -- } else if ( c == 0xf0 ) { -- /* m->mout.lastEvent = 0; */ -- m->mout.isInExclusive = 1; -- m->mout.bufRemains = get_remains(c); -- } else if ( c == 0xf7 && m->mout.isInExclusive == 1 ) { -- /* m->mout.lastEvent = 0; */ -- m->mout.isInExclusive = 0; -- m->mout.bufRemains = 1; -- } else if ( c > 0xf0 ) { -- /* m->mout.lastEvent = 0; */ -- m->mout.isInExclusive = 0; -- m->mout.bufRemains = get_remains(c); -- } -- -- } else if ( m->mout.bufRemains == 0 && m->mout.isInExclusive == 0 ) { -- if ( m->mout.lastEvent == 0 ) { -- return 0; /* discard, waiting for the first event */ -- } -- /** track status **/ -- m->mout.buf[0] = m->mout.lastEvent; -- m->mout.bufPtr = 1; -- m->mout.bufRemains = get_remains(m->mout.lastEvent)-1; -- } -- -- m->mout.buf[m->mout.bufPtr++] = c; -- m->mout.bufRemains--; -- if ( m->mout.bufRemains == 0 || m->mout.bufPtr >= 3) { -- ret = put_one_midi_event(m); -- } -- -- return ret; --} -- -- --/* ------------------------------------------------------------------------- */ -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic contract: Used to change the current read/write position in a file. -- * On success, the non-negative position is reported. -- * On failure, the negative of an error code is reported. -- * -- * Because a MIDIStream is not a file, all seek operations are doomed to fail. -- * -- **/ --static loff_t usb_midi_llseek(struct file *file, loff_t offset, int origin) --{ -- /** Tell user you cannot seek on a PIPE-like device. **/ -- return -ESPIPE; --} -- -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic contract: Block until count bytes have been read or an error occurs. -- * -- **/ -- --static ssize_t usb_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) --{ -- struct usb_mididev *m = (struct usb_mididev *)file->private_data; -- struct midi_in_endpoint *ep = m->min.ep; -- ssize_t ret; -- DECLARE_WAITQUEUE(wait, current); -- -- if ( !access_ok(VERIFY_READ, buffer, count) ) { -- return -EFAULT; -- } -- if ( count == 0 ) { -- return 0; -- } -- -- add_wait_queue( &ep->wait, &wait ); -- ret = 0; -- while( count > 0 ) { -- int cnt; -- int d = (int)count; -- -- cnt = m->min.bufRemains; -- if ( cnt > d ) { -- cnt = d; -- } -- -- if ( cnt <= 0 ) { -- if ( file->f_flags & O_NONBLOCK ) { -- if (!ret) -- ret = -EAGAIN; -- break; -- } -- __set_current_state(TASK_INTERRUPTIBLE); -- schedule(); -- if (signal_pending(current)) { -- if(!ret) -- ret=-ERESTARTSYS; -- break; -- } -- continue; -- } -- -- { -- int i; -- unsigned long flags; /* used to synchronize access to the endpoint */ -- spin_lock_irqsave( &ep->lock, flags ); -- for (i = 0; i < cnt; i++) { -- if ( copy_to_user( buffer+i, m->min.buf+m->min.bufRdPtr, 1 ) ) { -- if ( !ret ) -- ret = -EFAULT; -- break; -- } -- m->min.bufRdPtr = (m->min.bufRdPtr+1)%MIDI_IN_BUFSIZ; -- m->min.bufRemains -= 1; -- } -- spin_unlock_irqrestore( &ep->lock, flags ); -- } -- -- count-=cnt; -- buffer+=cnt; -- ret+=cnt; -- -- break; -- } -- -- remove_wait_queue( &ep->wait, &wait ); -- set_current_state(TASK_RUNNING); -- -- return ret; --} -- -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic Contract: Take MIDI data byte-by-byte and pass it to -- * writeMidi() which packages MIDI data into USB-MIDI stream. -- * Then flushMidiData() is called to ensure all bytes have been written -- * in a timely fashion. -- * -- **/ -- --static ssize_t usb_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) --{ -- struct usb_mididev *m = (struct usb_mididev *)file->private_data; -- ssize_t ret; -- unsigned long int flags; -- -- if ( !access_ok(VERIFY_READ, buffer, count) ) { -- return -EFAULT; -- } -- if ( count == 0 ) { -- return 0; -- } -- -- ret = 0; -- while( count > 0 ) { -- unsigned char c; -- -- if (copy_from_user((unsigned char *)&c, buffer, 1)) { -- if ( ret == 0 ) -- ret = -EFAULT; -- break; -- } -- if( midi_write(m, (int)c) ) { -- if ( ret == 0 ) -- ret = -EFAULT; -- break; -- } -- count--; -- buffer++; -- ret++; -- } -- -- spin_lock_irqsave( &m->mout.ep->lock, flags ); -- if ( flush_midi_buffer(m->mout.ep) < 0 ) { -- ret = -EFAULT; -- } -- spin_unlock_irqrestore( &m->mout.ep->lock, flags ); -- -- return ret; --} -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic contract: Wait (spin) until ready to read or write on the file. -- * -- **/ --static unsigned int usb_midi_poll(struct file *file, struct poll_table_struct *wait) --{ -- struct usb_mididev *m = (struct usb_mididev *)file->private_data; -- struct midi_in_endpoint *iep = m->min.ep; -- struct midi_out_endpoint *oep = m->mout.ep; -- unsigned long flags; -- unsigned int mask = 0; -- -- if ( file->f_mode & FMODE_READ ) { -- poll_wait( file, &iep->wait, wait ); -- spin_lock_irqsave( &iep->lock, flags ); -- if ( m->min.bufRemains > 0 ) -- mask |= POLLIN | POLLRDNORM; -- spin_unlock_irqrestore( &iep->lock, flags ); -- } -- -- if ( file->f_mode & FMODE_WRITE ) { -- poll_wait( file, &oep->wait, wait ); -- spin_lock_irqsave( &oep->lock, flags ); -- if ( oep->bufWrPtr < oep->bufSize ) -- mask |= POLLOUT | POLLWRNORM; -- spin_unlock_irqrestore( &oep->lock, flags ); -- } -- -- return mask; --} -- -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic contract: This is always the first operation performed on the -- * device node. If no method is defined, the open succeeds without any -- * notification given to the module. -- * -- **/ -- --static int usb_midi_open(struct inode *inode, struct file *file) --{ -- int minor = iminor(inode); -- DECLARE_WAITQUEUE(wait, current); -- struct usb_midi_state *s; -- struct usb_mididev *m; -- unsigned long flags; -- int succeed = 0; -- --#if 0 -- printk(KERN_INFO "usb-midi: Open minor= %d.\n", minor); --#endif -- -- for(;;) { -- down(&open_sem); -- list_for_each_entry(s, &mididevs, mididev) { -- list_for_each_entry(m, &s->midiDevList, list) { -- if ( !((m->dev_midi ^ minor) & ~0xf) ) -- goto device_found; -- } -- } -- up(&open_sem); -- return -ENODEV; -- -- device_found: -- if ( !s->usbdev ) { -- up(&open_sem); -- return -EIO; -- } -- if ( !(m->open_mode & file->f_mode) ) { -- break; -- } -- if ( file->f_flags & O_NONBLOCK ) { -- up(&open_sem); -- return -EBUSY; -- } -- __set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue( &open_wait, &wait ); -- up(&open_sem); -- schedule(); -- remove_wait_queue( &open_wait, &wait ); -- if ( signal_pending(current) ) { -- return -ERESTARTSYS; -- } -- } -- -- file->private_data = m; -- spin_lock_irqsave( &s->lock, flags ); -- -- if ( !(m->open_mode & (FMODE_READ | FMODE_WRITE)) ) { -- //FIXME: intented semantics unclear here -- m->min.bufRdPtr = 0; -- m->min.bufWrPtr = 0; -- m->min.bufRemains = 0; -- spin_lock_init(&m->min.ep->lock); -- -- m->mout.bufPtr = 0; -- m->mout.bufRemains = 0; -- m->mout.isInExclusive = 0; -- m->mout.lastEvent = 0; -- spin_lock_init(&m->mout.ep->lock); -- } -- -- if ( (file->f_mode & FMODE_READ) && m->min.ep != NULL ) { -- unsigned long int flagsep; -- spin_lock_irqsave( &m->min.ep->lock, flagsep ); -- m->min.ep->cables[m->min.cableId] = m; -- m->min.ep->readers += 1; -- m->min.bufRdPtr = 0; -- m->min.bufWrPtr = 0; -- m->min.bufRemains = 0; -- spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); -- -- if ( !(m->min.ep->urbSubmitted)) { -- -- /* urb->dev must be reinitialized on 2.4.x kernels */ -- m->min.ep->urb->dev = m->min.ep->usbdev; -- -- if ( usb_submit_urb(m->min.ep->urb, GFP_ATOMIC) ) { -- printk(KERN_ERR "usbmidi: Cannot submit urb for MIDI-IN\n"); -- } -- m->min.ep->urbSubmitted = 1; -- } -- m->open_mode |= FMODE_READ; -- succeed = 1; -- } -- -- if ( (file->f_mode & FMODE_WRITE) && m->mout.ep != NULL ) { -- m->mout.bufPtr = 0; -- m->mout.bufRemains = 0; -- m->mout.isInExclusive = 0; -- m->mout.lastEvent = 0; -- m->open_mode |= FMODE_WRITE; -- succeed = 1; -- } -- -- spin_unlock_irqrestore( &s->lock, flags ); -- -- s->count++; -- up(&open_sem); -- -- /** Changed to prevent extra increments to USE_COUNT. **/ -- if (!succeed) { -- return -EBUSY; -- } -- --#if 0 -- printk(KERN_INFO "usb-midi: Open Succeeded. minor= %d.\n", minor); --#endif -- -- return nonseekable_open(inode, file); /** Success. **/ --} -- -- --/** Basic operation on /dev/midiXX as registered through struct file_operations. -- * -- * Basic contract: Close an opened file and deallocate anything we allocated. -- * Like open(), this can be missing. If open set file->private_data, -- * release() must clear it. -- * -- **/ -- --static int usb_midi_release(struct inode *inode, struct file *file) --{ -- struct usb_mididev *m = (struct usb_mididev *)file->private_data; -- struct usb_midi_state *s = (struct usb_midi_state *)m->midi; -- --#if 0 -- printk(KERN_INFO "usb-midi: Close.\n"); --#endif -- -- down(&open_sem); -- -- if ( m->open_mode & FMODE_WRITE ) { -- m->open_mode &= ~FMODE_WRITE; -- usb_kill_urb( m->mout.ep->urb ); -- } -- -- if ( m->open_mode & FMODE_READ ) { -- unsigned long int flagsep; -- spin_lock_irqsave( &m->min.ep->lock, flagsep ); -- m->min.ep->cables[m->min.cableId] = NULL; // discard cable -- m->min.ep->readers -= 1; -- m->open_mode &= ~FMODE_READ; -- if ( m->min.ep->readers == 0 && -- m->min.ep->urbSubmitted ) { -- m->min.ep->urbSubmitted = 0; -- usb_kill_urb(m->min.ep->urb); -- } -- spin_unlock_irqrestore( &m->min.ep->lock, flagsep ); -- } -- -- s->count--; -- -- up(&open_sem); -- wake_up(&open_wait); -- -- file->private_data = NULL; -- return 0; --} -- --static struct file_operations usb_midi_fops = { -- .owner = THIS_MODULE, -- .llseek = usb_midi_llseek, -- .read = usb_midi_read, -- .write = usb_midi_write, -- .poll = usb_midi_poll, -- .open = usb_midi_open, -- .release = usb_midi_release, --}; -- --/* ------------------------------------------------------------------------- */ -- --/** Returns filled midi_in_endpoint structure or null on failure. -- * -- * Parameters: -- * d - a usb_device -- * endPoint - An usb endpoint in the range 0 to 15. -- * Called by allocUsbMidiDev(); -- * -- **/ -- --static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, int endPoint ) --{ -- struct midi_in_endpoint *ep; -- int bufSize; -- int pipe; -- -- endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */ -- -- pipe = usb_rcvbulkpipe( d, endPoint ); -- bufSize = usb_maxpacket( d, pipe, 0 ); -- /* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */ -- -- ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL); -- if ( !ep ) { -- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint\n"); -- return NULL; -- } -- memset( ep, 0, sizeof(struct midi_in_endpoint) ); --// this sets cables[] and readers to 0, too. --// for (i=0; i<16; i++) ep->cables[i] = 0; // discard cable --// ep->readers = 0; -- -- ep->endpoint = endPoint; -- -- ep->recvBuf = (unsigned char *)kmalloc(sizeof(unsigned char)*(bufSize), GFP_KERNEL); -- if ( !ep->recvBuf ) { -- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint buffer\n"); -- kfree(ep); -- return NULL; -- } -- -- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */ -- if ( !ep->urb ) { -- printk(KERN_ERR "usbmidi: no memory for midi in-endpoint urb\n"); -- kfree(ep->recvBuf); -- kfree(ep); -- return NULL; -- } -- usb_fill_bulk_urb( ep->urb, d, -- usb_rcvbulkpipe(d, endPoint), -- (unsigned char *)ep->recvBuf, bufSize, -- usb_bulk_read, ep ); -- -- /* ep->bufRdPtr = 0; */ -- /* ep->bufWrPtr = 0; */ -- /* ep->bufRemains = 0; */ -- /* ep->urbSubmitted = 0; */ -- ep->recvBufSize = bufSize; -- -- init_waitqueue_head(&ep->wait); -- -- return ep; --} -- --static int remove_midi_in_endpoint( struct midi_in_endpoint *min ) --{ -- usb_kill_urb( min->urb ); -- usb_free_urb( min->urb ); -- kfree( min->recvBuf ); -- kfree( min ); -- -- return 0; --} -- --/** Returns filled midi_out_endpoint structure or null on failure. -- * -- * Parameters: -- * d - a usb_device -- * endPoint - An usb endpoint in the range 0 to 15. -- * Called by allocUsbMidiDev(); -- * -- **/ --static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d, int endPoint ) --{ -- struct midi_out_endpoint *ep = NULL; -- int pipe; -- int bufSize; -- -- endPoint &= 0x0f; -- pipe = usb_sndbulkpipe( d, endPoint ); -- bufSize = usb_maxpacket( d, pipe, 1 ); -- -- ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL); -- if ( !ep ) { -- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint\n"); -- return NULL; -- } -- memset( ep, 0, sizeof(struct midi_out_endpoint) ); -- -- ep->endpoint = endPoint; -- ep->buf = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL); -- if ( !ep->buf ) { -- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint buffer\n"); -- kfree(ep); -- return NULL; -- } -- -- ep->urb = usb_alloc_urb(0, GFP_KERNEL); /* no ISO */ -- if ( !ep->urb ) { -- printk(KERN_ERR "usbmidi: no memory for midi out-endpoint urb\n"); -- kfree(ep->buf); -- kfree(ep); -- return NULL; -- } -- -- ep->bufSize = bufSize; -- /* ep->bufWrPtr = 0; */ -- -- init_waitqueue_head(&ep->wait); -- -- return ep; --} -- -- --static int remove_midi_out_endpoint( struct midi_out_endpoint *mout ) --{ -- usb_kill_urb( mout->urb ); -- usb_free_urb( mout->urb ); -- kfree( mout->buf ); -- kfree( mout ); -- -- return 0; --} -- -- --/** Returns a filled usb_mididev structure, registered as a Linux MIDI device. -- * -- * Returns null if memory is not available or the device cannot be registered. -- * Called by allocUsbMidiDev(); -- * -- **/ --static struct usb_mididev *allocMidiDev( -- struct usb_midi_state *s, -- struct midi_in_endpoint *min, -- struct midi_out_endpoint *mout, -- int inCableId, -- int outCableId ) --{ -- struct usb_mididev *m; -- -- m = (struct usb_mididev *)kmalloc(sizeof(struct usb_mididev), GFP_KERNEL); -- if (!m) { -- printk(KERN_ERR "usbmidi: no memory for midi device\n"); -- return NULL; -- } -- -- memset(m, 0, sizeof(struct usb_mididev)); -- -- if ((m->dev_midi = register_sound_midi(&usb_midi_fops, -1)) < 0) { -- printk(KERN_ERR "usbmidi: cannot register midi device\n"); -- kfree(m); -- return NULL; -- } -- -- m->midi = s; -- /* m->open_mode = 0; */ -- -- if ( min ) { -- m->min.ep = min; -- m->min.ep->usbdev = s->usbdev; -- m->min.cableId = inCableId; -- } -- /* m->min.bufPtr = 0; */ -- /* m->min.bufRemains = 0; */ -- -- if ( mout ) { -- m->mout.ep = mout; -- m->mout.ep->usbdev = s->usbdev; -- m->mout.cableId = outCableId; -- } -- /* m->mout.bufPtr = 0; */ -- /* m->mout.bufRemains = 0; */ -- /* m->mout.isInExclusive = 0; */ -- /* m->mout.lastEvent = 0; */ -- -- m->singlebyte = singlebyte; -- -- return m; --} -- -- --static void release_midi_device( struct usb_midi_state *s ) --{ -- struct usb_mididev *m; -- struct midi_in_endpoint *min; -- struct midi_out_endpoint *mout; -- -- if ( s->count > 0 ) { -- up(&open_sem); -- return; -- } -- up( &open_sem ); -- wake_up( &open_wait ); -- -- while(!list_empty(&s->inEndpointList)) { -- min = list_entry(s->inEndpointList.next, struct midi_in_endpoint, list); -- list_del(&min->list); -- remove_midi_in_endpoint(min); -- } -- -- while(!list_empty(&s->outEndpointList)) { -- mout = list_entry(s->outEndpointList.next, struct midi_out_endpoint, list); -- list_del(&mout->list); -- remove_midi_out_endpoint(mout); -- } -- -- while(!list_empty(&s->midiDevList)) { -- m = list_entry(s->midiDevList.next, struct usb_mididev, list); -- list_del(&m->list); -- kfree(m); -- } -- -- kfree(s); -- -- return; --} -- -- --/* ------------------------------------------------------------------------- */ -- --/** Utility routine to find a descriptor in a dump of many descriptors. -- * Returns start of descriptor or NULL if not found. -- * descStart pointer to list of interfaces. -- * descLength length (in bytes) of dump -- * after (ignored if NULL) this routine returns only descriptors after "after" -- * dtype (mandatory) The descriptor type. -- * iface (ignored if -1) returns descriptor at/following given interface -- * altSetting (ignored if -1) returns descriptor at/following given altSetting -- * -- * -- * Called by parseDescriptor(), find_csinterface_descriptor(); -- * -- */ --static void *find_descriptor( void *descStart, unsigned int descLength, void *after, unsigned char dtype, int iface, int altSetting ) --{ -- unsigned char *p, *end, *next; -- int interfaceNumber = -1, altSet = -1; -- -- p = descStart; -- end = p + descLength; -- for( ; p < end; ) { -- if ( p[0] < 2 ) -- return NULL; -- next = p + p[0]; -- if ( next > end ) -- return NULL; -- if ( p[1] == USB_DT_INTERFACE ) { -- if ( p[0] < USB_DT_INTERFACE_SIZE ) -- return NULL; -- interfaceNumber = p[2]; -- altSet = p[3]; -- } -- if ( p[1] == dtype && -- ( !after || ( p > (unsigned char *)after) ) && -- ( ( iface == -1) || (iface == interfaceNumber) ) && -- ( (altSetting == -1) || (altSetting == altSet) )) { -- return p; -- } -- p = next; -- } -- return NULL; --} -- --/** Utility to find a class-specific interface descriptor. -- * dsubtype is a descriptor subtype -- * Called by parseDescriptor(); -- **/ --static void *find_csinterface_descriptor(void *descStart, unsigned int descLength, void *after, u8 dsubtype, int iface, int altSetting) --{ -- unsigned char *p; -- -- p = find_descriptor( descStart, descLength, after, USB_DT_CS_INTERFACE, iface, altSetting ); -- while ( p ) { -- if ( p[0] >= 3 && p[2] == dsubtype ) -- return p; -- p = find_descriptor( descStart, descLength, p, USB_DT_CS_INTERFACE, -- iface, altSetting ); -- } -- return NULL; --} -- -- --/** The magic of making a new usb_midi_device from config happens here. -- * -- * The caller is responsible for free-ing this return value (if not NULL). -- * -- **/ --static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned char *buffer, int bufSize, unsigned int ifnum , unsigned int altSetting, int quirks) --{ -- struct usb_midi_device *u; -- unsigned char *p1; -- unsigned char *p2; -- unsigned char *next; -- int iep, oep; -- int length; -- unsigned long longBits; -- int pins, nbytes, offset, shift, jack; --#ifdef HAVE_JACK_STRINGS -- /** Jacks can have associated names. **/ -- unsigned char jack2string[256]; --#endif -- -- u = NULL; -- /* find audiocontrol interface */ -- p1 = find_csinterface_descriptor( buffer, bufSize, NULL, -- MS_HEADER, ifnum, altSetting); -- -- if ( !p1 ) { -- goto error_end; -- } -- -- if ( p1[0] < MS_HEADER_LENGTH ) { -- goto error_end; -- } -- -- /* Assume success. Since the device corresponds to USB-MIDI spec, we assume -- that the rest of the USB 2.0 spec is obeyed. */ -- -- u = (struct usb_midi_device *)kmalloc( sizeof(struct usb_midi_device), GFP_KERNEL ); -- if ( !u ) { -- return NULL; -- } -- u->deviceName = NULL; -- u->idVendor = le16_to_cpu(d->descriptor.idVendor); -- u->idProduct = le16_to_cpu(d->descriptor.idProduct); -- u->interface = ifnum; -- u->altSetting = altSetting; -- u->in[0].endpoint = -1; -- u->in[0].cableId = -1; -- u->out[0].endpoint = -1; -- u->out[0].cableId = -1; -- -- -- printk(KERN_INFO "usb-midi: Found MIDIStreaming device corresponding to Release %d.%02d of spec.\n", -- (p1[4] >> 4) * 10 + (p1[4] & 0x0f ), -- (p1[3] >> 4) * 10 + (p1[3] & 0x0f ) -- ); -- -- length = p1[5] | (p1[6] << 8); -- --#ifdef HAVE_JACK_STRINGS -- memset(jack2string, 0, sizeof(unsigned char) * 256); --#endif -- -- length -= p1[0]; -- for (p2 = p1 + p1[0]; length > 0; p2 = next) { -- next = p2 + p2[0]; -- length -= p2[0]; -- -- if (p2[0] < 2 ) -- break; -- if (p2[1] != USB_DT_CS_INTERFACE) -- break; -- if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) { -- jack = p2[4]; --#ifdef HAVE_JACK_STRINGS -- jack2string[jack] = p2[5]; --#endif -- printk(KERN_INFO "usb-midi: Found IN Jack 0x%02x %s\n", -- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" ); -- } else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) { -- pins = p2[5]; -- if ( p2[0] < (6 + 2 * pins) ) -- continue; -- jack = p2[4]; --#ifdef HAVE_JACK_STRINGS -- jack2string[jack] = p2[5 + 2 * pins]; --#endif -- printk(KERN_INFO "usb-midi: Found OUT Jack 0x%02x %s, %d pins\n", -- jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins ); -- } else if ( p2[2] == ELEMENT_DESCRIPTOR && p2[0] >= 10) { -- pins = p2[4]; -- if ( p2[0] < (9 + 2 * pins ) ) -- continue; -- nbytes = p2[8 + 2 * pins ]; -- if ( p2[0] < (10 + 2 * pins + nbytes) ) -- continue; -- longBits = 0L; -- for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) { -- longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift; -- } -- jack = p2[3]; --#ifdef HAVE_JACK_STRINGS -- jack2string[jack] = p2[9 + 2 * pins + nbytes]; --#endif -- printk(KERN_INFO "usb-midi: Found ELEMENT 0x%02x, %d/%d pins in/out, bits: 0x%016lx\n", -- jack, pins, (int)(p2[5 + 2 * pins]), (long)longBits ); -- } else { -- } -- } -- -- iep=0; -- oep=0; -- -- if (quirks==0) { -- /* MIDISTREAM */ -- p2 = NULL; -- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT, -- ifnum, altSetting ); p1; p1 = next ) { -- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT, -- ifnum, altSetting ); -- p2 = find_descriptor(buffer, bufSize, p1, USB_DT_CS_ENDPOINT, -- ifnum, altSetting ); -- -- if ( p2 && next && ( p2 > next ) ) -- p2 = NULL; -- -- if ( p1[0] < 9 || !p2 || p2[0] < 4 ) -- continue; -- -- if ( (p1[2] & 0x80) == 0x80 ) { -- if ( iep < 15 ) { -- pins = p2[3]; /* not pins -- actually "cables" */ -- if ( pins > 16 ) -- pins = 16; -- u->in[iep].endpoint = p1[2]; -- u->in[iep].cableId = ( 1 << pins ) - 1; -- if ( u->in[iep].cableId ) -- iep ++; -- if ( iep < 15 ) { -- u->in[iep].endpoint = -1; -- u->in[iep].cableId = -1; -- } -- } -- } else { -- if ( oep < 15 ) { -- pins = p2[3]; /* not pins -- actually "cables" */ -- if ( pins > 16 ) -- pins = 16; -- u->out[oep].endpoint = p1[2]; -- u->out[oep].cableId = ( 1 << pins ) - 1; -- if ( u->out[oep].cableId ) -- oep ++; -- if ( oep < 15 ) { -- u->out[oep].endpoint = -1; -- u->out[oep].cableId = -1; -- } -- } -- } -- -- } -- } else if (quirks==1) { -- /* YAMAHA quirks */ -- for (p1 = find_descriptor(buffer, bufSize, NULL, USB_DT_ENDPOINT, -- ifnum, altSetting ); p1; p1 = next ) { -- next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT, -- ifnum, altSetting ); -- -- if ( p1[0] < 7 ) -- continue; -- -- if ( (p1[2] & 0x80) == 0x80 ) { -- if ( iep < 15 ) { -- pins = iep+1; -- if ( pins > 16 ) -- pins = 16; -- u->in[iep].endpoint = p1[2]; -- u->in[iep].cableId = ( 1 << pins ) - 1; -- if ( u->in[iep].cableId ) -- iep ++; -- if ( iep < 15 ) { -- u->in[iep].endpoint = -1; -- u->in[iep].cableId = -1; -- } -- } -- } else { -- if ( oep < 15 ) { -- pins = oep+1; -- u->out[oep].endpoint = p1[2]; -- u->out[oep].cableId = ( 1 << pins ) - 1; -- if ( u->out[oep].cableId ) -- oep ++; -- if ( oep < 15 ) { -- u->out[oep].endpoint = -1; -- u->out[oep].cableId = -1; -- } -- } -- } -- -- } -- } -- -- if ( !iep && ! oep ) { -- goto error_end; -- } -- -- return u; -- --error_end: -- kfree(u); -- return NULL; --} -- --/* ------------------------------------------------------------------------- */ -- --/** Returns number between 0 and 16. -- * -- **/ --static int on_bits( unsigned short v ) --{ -- int i; -- int ret=0; -- -- for ( i=0 ; i<16 ; i++ ) { -- if ( v & (1<<i) ) -- ret++; -- } -- -- return ret; --} -- -- --/** USB-device will be interrogated for altSetting. -- * -- * Returns negative on error. -- * Called by allocUsbMidiDev(); -- * -- **/ -- --static int get_alt_setting( struct usb_device *d, int ifnum ) --{ -- int alts, alt=0; -- struct usb_interface *iface; -- struct usb_host_interface *interface; -- struct usb_endpoint_descriptor *ep; -- int epin, epout; -- int i; -- -- iface = usb_ifnum_to_if( d, ifnum ); -- alts = iface->num_altsetting; -- -- for ( alt=0 ; alt<alts ; alt++ ) { -- interface = &iface->altsetting[alt]; -- epin = -1; -- epout = -1; -- -- for ( i=0 ; i<interface->desc.bNumEndpoints ; i++ ) { -- ep = &interface->endpoint[i].desc; -- if ( (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ) { -- continue; -- } -- if ( (ep->bEndpointAddress & USB_DIR_IN) && epin < 0 ) { -- epin = i; -- } else if ( epout < 0 ) { -- epout = i; -- } -- if ( epin >= 0 && epout >= 0 ) { -- return interface->desc.bAlternateSetting; -- } -- } -- } -- -- return -ENODEV; --} -- -- --/* ------------------------------------------------------------------------- */ -- -- --/** Returns 0 if successful in allocating and registering internal structures. -- * Returns negative on failure. -- * Calls allocMidiDev which additionally registers /dev/midiXX devices. -- * Writes messages on success to indicate which /dev/midiXX is which physical -- * endpoint. -- * -- **/ --static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s, struct usb_midi_device *u ) --{ -- struct usb_mididev **mdevs=NULL; -- struct midi_in_endpoint *mins[15], *min; -- struct midi_out_endpoint *mouts[15], *mout; -- int inDevs=0, outDevs=0; -- int inEndpoints=0, outEndpoints=0; -- int inEndpoint, outEndpoint; -- int inCableId, outCableId; -- int i; -- int devices = 0; -- int alt = 0; -- -- /* Obtain altSetting or die.. */ -- alt = u->altSetting; -- if ( alt < 0 ) { -- alt = get_alt_setting( d, u->interface ); -- } -- if ( alt < 0 ) -- return -ENXIO; -- -- /* Configure interface */ -- if ( usb_set_interface( d, u->interface, alt ) < 0 ) { -- return -ENXIO; -- } -- -- for ( i = 0 ; i < 15 ; i++ ) { -- mins[i] = NULL; -- mouts[i] = NULL; -- } -- -- /* Begin Allocation */ -- while( inEndpoints < 15 -- && inDevs < maxdevices -- && u->in[inEndpoints].cableId >= 0 ) { -- inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId); -- mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint ); -- if ( mins[inEndpoints] == NULL ) -- goto error_end; -- inEndpoints++; -- } -- -- while( outEndpoints < 15 -- && outDevs < maxdevices -- && u->out[outEndpoints].cableId >= 0 ) { -- outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId); -- mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint ); -- if ( mouts[outEndpoints] == NULL ) -- goto error_end; -- outEndpoints++; -- } -- -- devices = inDevs > outDevs ? inDevs : outDevs; -- devices = maxdevices > devices ? devices : maxdevices; -- -- /* obtain space for device name (iProduct) if not known. */ -- if ( ! u->deviceName ) { -- mdevs = (struct usb_mididev **) -- kmalloc(sizeof(struct usb_mididevs *)*devices -- + sizeof(char) * 256, GFP_KERNEL); -- } else { -- mdevs = (struct usb_mididev **) -- kmalloc(sizeof(struct usb_mididevs *)*devices, GFP_KERNEL); -- } -- -- if ( !mdevs ) { -- /* devices = 0; */ -- /* mdevs = NULL; */ -- goto error_end; -- } -- for ( i=0 ; i<devices ; i++ ) { -- mdevs[i] = NULL; -- } -- -- /* obtain device name (iProduct) if not known. */ -- if ( ! u->deviceName ) { -- u->deviceName = (char *) (mdevs + devices); -- if ( ! d->have_langid && d->descriptor.iProduct) { -- alt = usb_get_string(d, 0, 0, u->deviceName, 250); -- if (alt < 0) { -- printk(KERN_INFO "error getting string descriptor 0 (error=%d)\n", alt); -- } else if (u->deviceName[0] < 4) { -- printk(KERN_INFO "string descriptor 0 too short (length = %d)\n", alt); -- } else { -- printk(KERN_INFO "string descriptor 0 found (length = %d)\n", alt); -- for(; alt >= 4; alt -= 2) { -- i = u->deviceName[alt-2] | (u->deviceName[alt-1]<< 8); -- printk(KERN_INFO "usb-midi: langid(%d) 0x%04x\n", -- (alt-4) >> 1, i); -- if ( ( ( i ^ ulangid ) & 0xff ) == 0 ) { -- d->have_langid = 1; -- d->string_langid = i; -- printk(KERN_INFO "usb-midi: langid(match) 0x%04x\n", i); -- if ( i == ulangid ) -- break; -- } -- } -- } -- } -- u->deviceName[0] = (char) 0; -- if (d->descriptor.iProduct) { -- printk(KERN_INFO "usb-midi: fetchString(%d)\n", d->descriptor.iProduct); -- alt = usb_string(d, d->descriptor.iProduct, u->deviceName, 255); -- if( alt < 0 ) { -- u->deviceName[0] = (char) 0; -- } -- printk(KERN_INFO "usb-midi: fetchString = %d\n", alt); -- } -- /* Failsafe */ -- if ( !u->deviceName[0] ) { -- if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_ROLAND ) { -- strcpy(u->deviceName, "Unknown Roland"); -- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_STEINBERG ) { -- strcpy(u->deviceName, "Unknown Steinberg"); -- } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_YAMAHA ) { -- strcpy(u->deviceName, "Unknown Yamaha"); -- } else { -- strcpy(u->deviceName, "Unknown"); -- } -- } -- } -- -- inEndpoint = 0; inCableId = -1; -- outEndpoint = 0; outCableId = -1; -- -- for ( i=0 ; i<devices ; i++ ) { -- for ( inCableId ++ ; -- inEndpoint <15 -- && mins[inEndpoint] -- && !(u->in[inEndpoint].cableId & (1<<inCableId)) ; -- inCableId++ ) { -- if ( inCableId >= 16 ) { -- inEndpoint ++; -- inCableId = 0; -- } -- } -- min = mins[inEndpoint]; -- for ( outCableId ++ ; -- outEndpoint <15 -- && mouts[outEndpoint] -- && !(u->out[outEndpoint].cableId & (1<<outCableId)) ; -- outCableId++ ) { -- if ( outCableId >= 16 ) { -- outEndpoint ++; -- outCableId = 0; -- } -- } -- mout = mouts[outEndpoint]; -- -- mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId ); -- if ( mdevs[i] == NULL ) -- goto error_end; -- -- } -- -- /* Success! */ -- for ( i=0 ; i<devices ; i++ ) { -- list_add_tail( &mdevs[i]->list, &s->midiDevList ); -- } -- for ( i=0 ; i<inEndpoints ; i++ ) { -- list_add_tail( &mins[i]->list, &s->inEndpointList ); -- } -- for ( i=0 ; i<outEndpoints ; i++ ) { -- list_add_tail( &mouts[i]->list, &s->outEndpointList ); -- } -- -- printk(KERN_INFO "usbmidi: found [ %s ] (0x%04x:0x%04x), attached:\n", u->deviceName, u->idVendor, u->idProduct ); -- for ( i=0 ; i<devices ; i++ ) { -- int dm = (mdevs[i]->dev_midi-2)>>4; -- if ( mdevs[i]->mout.ep != NULL && mdevs[i]->min.ep != NULL ) { -- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%2d) out (ep:%02x cid:%2d bufsiz:%2d)\n", -- dm, -- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize, -- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize); -- } else if ( mdevs[i]->min.ep != NULL ) { -- printk(KERN_INFO "usbmidi: /dev/midi%02d: in (ep:%02x cid:%2d bufsiz:%02d)\n", -- dm, -- mdevs[i]->min.ep->endpoint|USB_DIR_IN, mdevs[i]->min.cableId, mdevs[i]->min.ep->recvBufSize); -- } else if ( mdevs[i]->mout.ep != NULL ) { -- printk(KERN_INFO "usbmidi: /dev/midi%02d: out (ep:%02x cid:%2d bufsiz:%02d)\n", -- dm, -- mdevs[i]->mout.ep->endpoint, mdevs[i]->mout.cableId, mdevs[i]->mout.ep->bufSize); -- } -- } -- -- kfree(mdevs); -- return 0; -- -- error_end: -- if ( mdevs != NULL ) { -- for ( i=0 ; i<devices ; i++ ) { -- if ( mdevs[i] != NULL ) { -- unregister_sound_midi( mdevs[i]->dev_midi ); -- kfree(mdevs[i]); -- } -- } -- kfree(mdevs); -- } -- -- for ( i=0 ; i<15 ; i++ ) { -- if ( mins[i] != NULL ) { -- remove_midi_in_endpoint( mins[i] ); -- } -- if ( mouts[i] != NULL ) { -- remove_midi_out_endpoint( mouts[i] ); -- } -- } -- -- return -ENOMEM; --} -- --/* ------------------------------------------------------------------------- */ -- --/** Attempt to scan YAMAHA's device descriptor and detect correct values of -- * them. -- * Return 0 on succes, negative on failure. -- * Called by usb_midi_probe(); -- **/ -- --static int detect_yamaha_device( struct usb_device *d, -- struct usb_interface *iface, unsigned int ifnum, -- struct usb_midi_state *s) --{ -- struct usb_host_interface *interface; -- struct usb_midi_device *u; -- unsigned char *buffer; -- int bufSize; -- int i; -- int alts=-1; -- int ret; -- -- if (le16_to_cpu(d->descriptor.idVendor) != USB_VENDOR_ID_YAMAHA) { -- return -EINVAL; -- } -- -- for ( i=0 ; i < iface->num_altsetting; i++ ) { -- interface = iface->altsetting + i; -- -- if ( interface->desc.bInterfaceClass != 255 || -- interface->desc.bInterfaceSubClass != 0 ) -- continue; -- alts = interface->desc.bAlternateSetting; -- } -- if ( alts == -1 ) { -- return -EINVAL; -- } -- -- printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", -- le16_to_cpu(d->descriptor.idVendor), -- le16_to_cpu(d->descriptor.idProduct), ifnum); -- -- i = d->actconfig - d->config; -- buffer = d->rawdescriptors[i]; -- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength); -- -- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1); -- if ( u == NULL ) { -- return -EINVAL; -- } -- -- ret = alloc_usb_midi_device( d, s, u ); -- -- kfree(u); -- -- return ret; --} -- -- --/** Scan table of known devices which are only partially compliant with -- * the MIDIStreaming specification. -- * Called by usb_midi_probe(); -- * -- **/ -- --static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s ) --{ -- struct usb_midi_device *u; -- int i; -- int ret = -ENXIO; -- -- for ( i=0; i<VENDOR_SPECIFIC_USB_MIDI_DEVICES ; i++ ) { -- u=&(usb_midi_devices[i]); -- -- if ( le16_to_cpu(d->descriptor.idVendor) != u->idVendor || -- le16_to_cpu(d->descriptor.idProduct) != u->idProduct || -- ifnum != u->interface ) -- continue; -- -- ret = alloc_usb_midi_device( d, s, u ); -- break; -- } -- -- return ret; --} -- -- --/** Attempt to match any config of an interface to a MIDISTREAMING interface. -- * Returns 0 on success, negative on failure. -- * Called by usb_midi_probe(); -- **/ --static int detect_midi_subclass(struct usb_device *d, -- struct usb_interface *iface, unsigned int ifnum, -- struct usb_midi_state *s) --{ -- struct usb_host_interface *interface; -- struct usb_midi_device *u; -- unsigned char *buffer; -- int bufSize; -- int i; -- int alts=-1; -- int ret; -- -- for ( i=0 ; i < iface->num_altsetting; i++ ) { -- interface = iface->altsetting + i; -- -- if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO || -- interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING ) -- continue; -- alts = interface->desc.bAlternateSetting; -- } -- if ( alts == -1 ) { -- return -EINVAL; -- } -- -- printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n", -- le16_to_cpu(d->descriptor.idVendor), -- le16_to_cpu(d->descriptor.idProduct), ifnum); -- -- -- /* From USB Spec v2.0, Section 9.5. -- If the class or vendor specific descriptors use the same format -- as standard descriptors (e.g., start with a length byte and -- followed by a type byte), they must be returned interleaved with -- standard descriptors in the configuration information returned by -- a GetDescriptor(Configuration) request. In this case, the class -- or vendor-specific descriptors must follow a related standard -- descriptor they modify or extend. -- */ -- -- i = d->actconfig - d->config; -- buffer = d->rawdescriptors[i]; -- bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength); -- -- u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0); -- if ( u == NULL ) { -- return -EINVAL; -- } -- -- ret = alloc_usb_midi_device( d, s, u ); -- -- kfree(u); -- -- return ret; --} -- -- --/** When user has requested a specific device, match it exactly. -- * -- * Uses uvendor, uproduct, uinterface, ualt, umin, umout and ucable. -- * Called by usb_midi_probe(); -- * -- **/ --static int detect_by_hand(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) --{ -- struct usb_midi_device u; -- -- if ( le16_to_cpu(d->descriptor.idVendor) != uvendor || -- le16_to_cpu(d->descriptor.idProduct) != uproduct || -- ifnum != uinterface ) { -- return -EINVAL; -- } -- -- if ( ualt < 0 ) -- ualt = -1; -- -- if ( umin < 0 || umin > 15 ) -- umin = 0x01 | USB_DIR_IN; -- if ( umout < 0 || umout > 15 ) -- umout = 0x01; -- if ( ucable < 0 || ucable > 15 ) -- ucable = 0; -- -- u.deviceName = NULL; /* A flag for alloc_usb_midi_device to get device -- name from device. */ -- u.idVendor = uvendor; -- u.idProduct = uproduct; -- u.interface = uinterface; -- u.altSetting = ualt; -- -- u.in[0].endpoint = umin; -- u.in[0].cableId = (1<<ucable); -- -- u.out[0].endpoint = umout; -- u.out[0].cableId = (1<<ucable); -- -- return alloc_usb_midi_device( d, s, &u ); --} -- -- -- --/* ------------------------------------------------------------------------- */ -- --static int usb_midi_probe(struct usb_interface *intf, -- const struct usb_device_id *id) --{ -- struct usb_midi_state *s; -- struct usb_device *dev = interface_to_usbdev(intf); -- int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; -- -- s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL); -- if ( !s ) -- return -ENOMEM; -- -- memset( s, 0, sizeof(struct usb_midi_state) ); -- INIT_LIST_HEAD(&s->midiDevList); -- INIT_LIST_HEAD(&s->inEndpointList); -- INIT_LIST_HEAD(&s->outEndpointList); -- s->usbdev = dev; -- s->count = 0; -- spin_lock_init(&s->lock); -- -- if ( -- detect_by_hand( dev, ifnum, s ) && -- detect_midi_subclass( dev, intf, ifnum, s ) && -- detect_vendor_specific_device( dev, ifnum, s ) && -- detect_yamaha_device( dev, intf, ifnum, s) ) { -- kfree(s); -- return -EIO; -- } -- -- down(&open_sem); -- list_add_tail(&s->mididev, &mididevs); -- up(&open_sem); -- -- usb_set_intfdata (intf, s); -- return 0; --} -- -- --static void usb_midi_disconnect(struct usb_interface *intf) --{ -- struct usb_midi_state *s = usb_get_intfdata (intf); -- struct usb_mididev *m; -- -- if ( !s ) -- return; -- -- if ( s == (struct usb_midi_state *)-1 ) { -- return; -- } -- if ( !s->usbdev ) { -- return; -- } -- down(&open_sem); -- list_del(&s->mididev); -- INIT_LIST_HEAD(&s->mididev); -- s->usbdev = NULL; -- usb_set_intfdata (intf, NULL); -- -- list_for_each_entry(m, &s->midiDevList, list) { -- wake_up(&(m->min.ep->wait)); -- wake_up(&(m->mout.ep->wait)); -- if ( m->dev_midi >= 0 ) { -- unregister_sound_midi(m->dev_midi); -- } -- m->dev_midi = -1; -- } -- release_midi_device(s); -- wake_up(&open_wait); --} -- --/* we want to look at all devices by hand */ --static struct usb_device_id id_table[] = { -- {.driver_info = 42}, -- {} --}; -- --static struct usb_driver usb_midi_driver = { -- .name = "midi", -- .probe = usb_midi_probe, -- .disconnect = usb_midi_disconnect, -- .id_table = id_table, --}; -- --/* ------------------------------------------------------------------------- */ -- --static int __init usb_midi_init(void) --{ -- return usb_register(&usb_midi_driver); --} -- --static void __exit usb_midi_exit(void) --{ -- usb_deregister(&usb_midi_driver); --} -- --module_init(usb_midi_init) ; --module_exit(usb_midi_exit) ; -- --#ifdef HAVE_ALSA_SUPPORT --#define SNDRV_MAIN_OBJECT_FILE --#include "../../include/driver.h" --#include "../../include/control.h" --#include "../../include/info.h" --#include "../../include/cs46xx.h" -- --/* ------------------------------------------------------------------------- */ -- --static int snd_usbmidi_input_close(snd_rawmidi_substream_t * substream) --{ -- return 0; --} -- --static int snd_usbmidi_input_open(snd_rawmidi_substream_t * substream ) --{ -- return 0; --} -- --static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t * substream, int up) --{ -- return 0; --} -- -- --/* ------------------------------------------------------------------------- */ -- --static int snd_usbmidi_output_close(snd_rawmidi_substream_t * substream) --{ -- return 0; --} -- --static int snd_usbmidi_output_open(snd_rawmidi_substream_t * substream) --{ -- return 0; --} -- --static void snd_usb_midi_output_trigger(snd_rawmidi_substream_t * substream, -- int up) --{ -- return 0; --} -- --/* ------------------------------------------------------------------------- */ -- --static snd_rawmidi_ops_t snd_usbmidi_output = --{ -- .open = snd_usbmidi_output_open, -- .close = snd_usbmidi_output_close, -- .trigger = snd_usbmidi_output_trigger, --}; --static snd_rawmidi_ops_t snd_usbmidi_input = --{ -- .open = snd_usbmidi_input_open, -- .close = snd_usbmidi_input_close, -- .trigger = snd_usbmidi_input_trigger, --}; -- --int snd_usbmidi_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi) --{ -- snd_rawmidi_t *rmidi; -- int err; -- -- if (rrawmidi) -- *rrawmidi = NULL; -- if ((err = snd_rawmidi_new(chip->card, "USB-MIDI", device, 1, 1, &rmidi)) < 0) -- return err; -- strcpy(rmidi->name, "USB-MIDI"); -- -- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output ); -- snd_rawmidi_set_ops( rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_usbmidi_input ); -- -- rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; -- -- rmidi->private_data = chip; -- chip->rmidi = rmidi; -- if (rrawmidi) -- *rrawmidi = NULL; -- -- return 0; --} -- --int snd_usbmidi_create( snd_card_t * card, -- struct pci_dev * pci, -- usbmidi_t ** rchip ) --{ -- usbmidi_t *chip; -- int err, idx; -- snd_region_t *region; -- static snd_device_opt_t ops = { -- .dev_free = snd_usbmidi_dev_free, -- }; -- -- *rchip = NULL; -- chip = snd_magic_kcalloc( usbmidi_t, 0, GFP_KERNEL ); -- if ( chip == NULL ) -- return -ENOMEM; --} -- --EXPORT_SYMBOL(snd_usbmidi_create); --EXPORT_SYMBOL(snd_usbmidi_midi); --#endif /* HAVE_ALSA_SUPPORT */ -- ---- gregkh-2.6.orig/drivers/usb/class/usb-midi.h -+++ /dev/null -@@ -1,164 +0,0 @@ --/* -- usb-midi.h -- USB-MIDI driver -- -- Copyright (C) 2001 -- NAGANO Daisuke <breeze.nagano@nifty.ne.jp> -- -- 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, or (at your option) -- any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- */ -- --/* ------------------------------------------------------------------------- */ -- --#ifndef _USB_MIDI_H_ --#define _USB_MIDI_H_ -- --#ifndef USB_SUBCLASS_MIDISTREAMING --#define USB_SUBCLASS_MIDISTREAMING 3 --#endif -- --/* ------------------------------------------------------------------------- */ --/* Roland MIDI Devices */ -- --#define USB_VENDOR_ID_ROLAND 0x0582 --#define USBMIDI_ROLAND_UA100G 0x0000 --#define USBMIDI_ROLAND_MPU64 0x0002 --#define USBMIDI_ROLAND_SC8850 0x0003 --#define USBMIDI_ROLAND_SC8820 0x0007 --#define USBMIDI_ROLAND_UM2 0x0005 --#define USBMIDI_ROLAND_UM1 0x0009 --#define USBMIDI_ROLAND_PC300 0x0008 -- --/* YAMAHA MIDI Devices */ --#define USB_VENDOR_ID_YAMAHA 0x0499 --#define USBMIDI_YAMAHA_MU1000 0x1001 -- --/* Steinberg MIDI Devices */ --#define USB_VENDOR_ID_STEINBERG 0x0763 --#define USBMIDI_STEINBERG_USB2MIDI 0x1001 -- --/* Mark of the Unicorn MIDI Devices */ --#define USB_VENDOR_ID_MOTU 0x07fd --#define USBMIDI_MOTU_FASTLANE 0x0001 -- --/* ------------------------------------------------------------------------- */ --/* Supported devices */ -- --struct usb_midi_endpoint { -- int endpoint; -- int cableId; /* if bit-n == 1 then cableId-n is enabled (n: 0 - 15) */ --}; -- --struct usb_midi_device { -- char *deviceName; -- -- u16 idVendor; -- u16 idProduct; -- int interface; -- int altSetting; /* -1: auto detect */ -- -- struct usb_midi_endpoint in[15]; -- struct usb_midi_endpoint out[15]; --}; -- --static struct usb_midi_device usb_midi_devices[] = { -- { /* Roland UM-1 */ -- "Roland UM-1", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1, 2, -1, -- { { 0x81, 1 }, {-1, -1} }, -- { { 0x01, 1,}, {-1, -1} }, -- }, -- -- { /* Roland UM-2 */ -- "Roland UM-2" , -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2, 2, -1, -- { { 0x81, 3 }, {-1, -1} }, -- { { 0x01, 3,}, {-1, -1} }, -- }, -- --/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/ -- { /* Roland UA-100 */ -- "Roland UA-100", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G, 2, -1, -- { { 0x82, 7 }, {-1, -1} }, /** cables 0,1 and 2 for SYSEX **/ -- { { 0x02, 7 }, {-1, -1} }, -- }, -- --/** Next entry courtesy research by Michael Minn <michael@michaelminn.com> **/ -- { /* Roland SC8850 */ -- "Roland SC8850", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1, -- { { 0x81, 0x3f }, {-1, -1} }, -- { { 0x01, 0x3f }, {-1, -1} }, -- }, -- -- { /* Roland SC8820 */ -- "Roland SC8820", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, -- { { 0x81, 0x13 }, {-1, -1} }, -- { { 0x01, 0x13 }, {-1, -1} }, -- }, -- -- { /* Roland SC8820 */ -- "Roland SC8820", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, -- { { 0x81, 17 }, {-1, -1} }, -- { { 0x01, 17 }, {-1, -1} }, -- }, -- -- { /* YAMAHA MU1000 */ -- "YAMAHA MU1000", -- USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1, -- { { 0x81, 1 }, {-1, -1} }, -- { { 0x01, 15 }, {-1, -1} }, -- }, -- { /* Roland PC-300 */ -- "Roland PC-300", -- USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, -- { { 0x81, 1 }, {-1, -1} }, -- { { 0x01, 1 }, {-1, -1} }, -- }, -- { /* MOTU Fastlane USB */ -- "MOTU Fastlane USB", -- USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0, -- { { 0x82, 3 }, {-1, -1} }, -- { { 0x02, 3 }, {-1, -1} }, -- } --}; -- --#define VENDOR_SPECIFIC_USB_MIDI_DEVICES (sizeof(usb_midi_devices)/sizeof(struct usb_midi_device)) -- --/* for Hot-Plugging */ -- --static struct usb_device_id usb_midi_ids [] = { -- { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), -- .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING}, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM1 ) }, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UM2 ) }, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) }, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) }, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) }, -- { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) }, -- { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) }, -- { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) }, --/* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/ -- { } /* Terminating entry */ --}; -- --MODULE_DEVICE_TABLE (usb, usb_midi_ids); -- --/* ------------------------------------------------------------------------- */ --#endif /* _USB_MIDI_H_ */ -- -- diff --git a/usb/usb-remove-usbcore-specific-wakeup-flags.patch b/usb/usb-remove-usbcore-specific-wakeup-flags.patch deleted file mode 100644 index a4595fdb4fbdc..0000000000000 --- a/usb/usb-remove-usbcore-specific-wakeup-flags.patch +++ /dev/null @@ -1,181 +0,0 @@ -From david-b@pacbell.net Tue Jan 24 08:40:38 2006 -From: David Brownell <david-b@pacbell.net> -Subject: USB: remove usbcore-specific wakeup flags -Date: Tue, 24 Jan 2006 08:40:27 -0800 -Cc: Alan Stern <stern@rowland.harvard.edu>, Greg KH <greg@kroah.com> -Message-Id: <200601240840.27533.david-b@pacbell.net> - - -This makes usbcore use the driver model wakeup flags for host controllers -and for their root hubs. Since previous patches have removed all users of -the HCD flags they replace, this converts the last users of those flags. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/hcd-pci.c | 11 ++++++++--- - drivers/usb/core/hcd.c | 40 ++++++++++++++++++++++++++-------------- - drivers/usb/core/hcd.h | 2 -- - drivers/usb/core/hub.c | 22 ++++++++++++++-------- - 4 files changed, 48 insertions(+), 27 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/hcd-pci.c -+++ gregkh-2.6/drivers/usb/core/hcd-pci.c -@@ -264,14 +264,19 @@ int usb_hcd_pci_suspend (struct pci_dev - */ - retval = pci_set_power_state (dev, PCI_D3hot); - if (retval == 0) { -- dev_dbg (hcd->self.controller, "--> PCI D3\n"); -+ 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", -+ 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, hcd->remote_wakeup); -- (void) pci_enable_wake (dev, PCI_D3cold, hcd->remote_wakeup); -+ (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", - retval); ---- gregkh-2.6.orig/drivers/usb/core/hcd.c -+++ gregkh-2.6/drivers/usb/core/hcd.c -@@ -367,21 +367,39 @@ static int rh_call_control (struct usb_h - - /* DEVICE REQUESTS */ - -+ /* The root hub's remote wakeup enable bit is implemented using -+ * driver model wakeup flags. If this system supports wakeup -+ * through USB, userspace may change the default "allow wakeup" -+ * policy through sysfs or these calls. -+ * -+ * Most root hubs support wakeup from downstream devices, for -+ * runtime power management (disabling USB clocks and reducing -+ * VBUS power usage). However, not all of them do so; silicon, -+ * board, and BIOS bugs here are not uncommon, so these can't -+ * be treated quite like external hubs. -+ * -+ * Likewise, not all root hubs will pass wakeup events upstream, -+ * to wake up the whole system. So don't assume root hub and -+ * controller capabilities are identical. -+ */ -+ - case DeviceRequest | USB_REQ_GET_STATUS: -- tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP) -+ tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev) -+ << USB_DEVICE_REMOTE_WAKEUP) - | (1 << USB_DEVICE_SELF_POWERED); - tbuf [1] = 0; - len = 2; - break; - case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: - if (wValue == USB_DEVICE_REMOTE_WAKEUP) -- hcd->remote_wakeup = 0; -+ device_set_wakeup_enable(&hcd->self.root_hub->dev, 0); - else - goto error; - break; - case DeviceOutRequest | USB_REQ_SET_FEATURE: -- if (hcd->can_wakeup && wValue == USB_DEVICE_REMOTE_WAKEUP) -- hcd->remote_wakeup = 1; -+ if (device_can_wakeup(&hcd->self.root_hub->dev) -+ && wValue == USB_DEVICE_REMOTE_WAKEUP) -+ device_set_wakeup_enable(&hcd->self.root_hub->dev, 1); - else - goto error; - break; -@@ -410,7 +428,7 @@ static int rh_call_control (struct usb_h - bufp = fs_rh_config_descriptor; - len = sizeof fs_rh_config_descriptor; - } -- if (hcd->can_wakeup) -+ if (device_can_wakeup(&hcd->self.root_hub->dev)) - patch_wakeup = 1; - break; - case USB_DT_STRING << 8: -@@ -1804,16 +1822,10 @@ int usb_add_hcd(struct usb_hcd *hcd, - device_init_wakeup(&rhdev->dev, - device_can_wakeup(hcd->self.controller)); - -- // ... all these hcd->*_wakeup flags will vanish -- hcd->can_wakeup = device_can_wakeup(hcd->self.controller); -- -- /* hcd->driver->reset() reported can_wakeup, probably with -- * assistance from board's boot firmware. -- * NOTE: normal devices won't enable wakeup by default. -- */ -- if (hcd->can_wakeup) -+ /* NOTE: root hub and controller capabilities may not be the same */ -+ if (device_can_wakeup(hcd->self.controller) -+ && device_can_wakeup(&hcd->self.root_hub->dev)) - dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); -- hcd->remote_wakeup = hcd->can_wakeup; - - /* enable irqs just before we start the controller */ - if (hcd->driver->irq) { ---- gregkh-2.6.orig/drivers/usb/core/hcd.h -+++ gregkh-2.6/drivers/usb/core/hcd.h -@@ -78,8 +78,6 @@ struct usb_hcd { /* usb_bus.hcpriv point - #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 - #define HCD_FLAG_SAW_IRQ 0x00000002 - -- unsigned can_wakeup:1; /* hw supports wakeup? */ -- unsigned remote_wakeup:1;/* sw should use wakeup? */ - unsigned rh_registered:1;/* is root hub registered? */ - - /* The next flag is a stopgap, to be removed when all the HCDs ---- gregkh-2.6.orig/drivers/usb/core/hub.c -+++ gregkh-2.6/drivers/usb/core/hub.c -@@ -1006,12 +1006,18 @@ void usb_set_device_state(struct usb_dev - ; /* do nothing */ - else if (new_state != USB_STATE_NOTATTACHED) { - udev->state = new_state; -- if (new_state == USB_STATE_CONFIGURED) -- device_init_wakeup(&udev->dev, -- (udev->actconfig->desc.bmAttributes -- & USB_CONFIG_ATT_WAKEUP)); -- else if (new_state != USB_STATE_SUSPENDED) -- device_init_wakeup(&udev->dev, 0); -+ -+ /* root hub wakeup capabilities are managed out-of-band -+ * and may involve silicon errata ... ignore them here. -+ */ -+ if (udev->parent) { -+ if (new_state == USB_STATE_CONFIGURED) -+ device_init_wakeup(&udev->dev, -+ (udev->actconfig->desc.bmAttributes -+ & USB_CONFIG_ATT_WAKEUP)); -+ else if (new_state != USB_STATE_SUSPENDED) -+ device_init_wakeup(&udev->dev, 0); -+ } - } else - recursively_mark_NOTATTACHED(udev); - spin_unlock_irqrestore(&device_state_lock, flags); -@@ -1877,9 +1883,9 @@ int usb_resume_device(struct usb_device - if (udev->state == USB_STATE_NOTATTACHED) - return -ENODEV; - --#ifdef CONFIG_USB_SUSPEND - /* selective resume of one downstream hub-to-device port */ - if (udev->parent) { -+#ifdef CONFIG_USB_SUSPEND - if (udev->state == USB_STATE_SUSPENDED) { - // NOTE swsusp may bork us, device state being wrong... - // NOTE this fails if parent is also suspended... -@@ -1887,8 +1893,8 @@ int usb_resume_device(struct usb_device - udev->portnum, udev); - } else - status = 0; -- } else - #endif -+ } else - status = finish_device_resume(udev); - if (status < 0) - dev_dbg(&udev->dev, "can't resume, status %d\n", diff --git a/usb/usb-rtl8150-small-fix.patch b/usb/usb-rtl8150-small-fix.patch deleted file mode 100644 index ec92259f1ec0d..0000000000000 --- a/usb/usb-rtl8150-small-fix.patch +++ /dev/null @@ -1,37 +0,0 @@ -From petkan@nucleusys.com Wed Mar 15 06:29:32 2006 -Date: Wed, 15 Mar 2006 16:29:38 +0200 (EET) -From: Petko Manolov <petkan@nucleusys.com> -To: Greg KH <greg@kroah.com> -Subject: USB: rtl8150 small fix -Message-ID: <Pine.LNX.4.62.0603151626570.2354@localhost.localdomain> - -This one is about announcing the device registration after the last check -has been made. - -From: Petko Manolov <petkan@nucleusys.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/net/rtl8150.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/net/rtl8150.c -+++ gregkh-2.6/drivers/usb/net/rtl8150.c -@@ -880,7 +880,6 @@ static int rtl8150_probe(struct usb_inte - } - fill_skb_pool(dev); - set_ethernet_addr(dev); -- info("%s: rtl8150 is detected", netdev->name); - - usb_set_intfdata(intf, dev); - SET_NETDEV_DEV(netdev, &intf->dev); -@@ -888,6 +887,9 @@ static int rtl8150_probe(struct usb_inte - err("couldn't register the device"); - goto out2; - } -+ -+ info("%s: rtl8150 is detected", netdev->name); -+ - return 0; - - out2: diff --git a/usb/usb-sn9c10x-driver-updates.patch b/usb/usb-sn9c10x-driver-updates.patch deleted file mode 100644 index d90c465bf5847..0000000000000 --- a/usb/usb-sn9c10x-driver-updates.patch +++ /dev/null @@ -1,1073 +0,0 @@ -From luca.risolia@studio.unibo.it Fri Feb 24 21:49:15 2006 -Date: Sat, 25 Feb 2006 06:50:47 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: SN9C10x driver updates -Message-ID: <20060225065047.GA31623@studio.unibo.it> -Content-Disposition: inline - -SN9C10x driver updates. - -Changes: + new, - removed, * cleanup, @ bugfix - -@ Fix stream_interrupt() -@ Fix vidioc_enum_input() and split vidioc_gs_input() -@ Need usb_get|put_dev() when disconnecting, if the device is open -* Use wait_event_interruptible_timeout() instead of wait_event_interruptible() - when waiting for video frames -* replace wake_up_interruptible(&wait_stream) with wake_up(&wait_stream) -* Cleanups and updates in the documentation -+ Use per-device sensor structures -+ Add support for PAS202BCA image sensors -+ Add frame_timeout module parameter - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/sn9c102.txt | 11 + - drivers/usb/media/Makefile | 5 - drivers/usb/media/sn9c102.h | 23 ++- - drivers/usb/media/sn9c102_core.c | 170 +++++++++++++---------- - drivers/usb/media/sn9c102_ov7630.c | 33 ++-- - drivers/usb/media/sn9c102_pas202bca.c | 238 +++++++++++++++++++++++++++++++++ - drivers/usb/media/sn9c102_pas202bcb.c | 2 - drivers/usb/media/sn9c102_sensor.h | 15 +- - drivers/usb/media/sn9c102_tas5110c1b.c | 14 + - drivers/usb/media/sn9c102_tas5130d1b.c | 12 + - 10 files changed, 416 insertions(+), 107 deletions(-) - ---- gregkh-2.6.orig/Documentation/usb/sn9c102.txt -+++ gregkh-2.6/Documentation/usb/sn9c102.txt -@@ -196,6 +196,14 @@ Description: Force the application to - 1 = force memory unmapping (save memory) - Default: 0 - ------------------------------------------------------------------------------- -+Name: frame_timeout -+Type: uint array (min = 0, max = 64) -+Syntax: <n[,...]> -+Description: Timeout for a video frame in seconds. This parameter is -+ specific for each detected camera. This parameter can be -+ changed at runtime thanks to the /sys filesystem interface. -+Default: 2 -+------------------------------------------------------------------------------- - Name: debug - Type: ushort - Syntax: <n> -@@ -321,6 +329,7 @@ Vendor ID Product ID - --------- ---------- - 0x0c45 0x6001 - 0x0c45 0x6005 -+0x0c45 0x6007 - 0x0c45 0x6009 - 0x0c45 0x600d - 0x0c45 0x6024 -@@ -370,6 +379,7 @@ HV7131D Hynix Semiconductor, Inc. - MI-0343 Micron Technology, Inc. - OV7630 OmniVision Technologies, Inc. - PAS106B PixArt Imaging, Inc. -+PAS202BCA PixArt Imaging, Inc. - PAS202BCB PixArt Imaging, Inc. - TAS5110C1B Taiwan Advanced Sensor Corporation - TAS5130D1B Taiwan Advanced Sensor Corporation -@@ -493,6 +503,7 @@ Many thanks to following persons for the - order): - - - Luca Capello for the donation of a webcam; -+- Philippe Coval for having helped testing the PAS202BCA image sensor; - - Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the - donation of a webcam; - - Jon Hollstrom for the donation of a webcam; ---- gregkh-2.6.orig/drivers/usb/media/Makefile -+++ gregkh-2.6/drivers/usb/media/Makefile -@@ -2,7 +2,10 @@ - # Makefile for USB Media drivers - # - --sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o -+sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \ -+ sn9c102_ov7630.o sn9c102_pas106b.o sn9c102_pas202bca.o \ -+ sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \ -+ sn9c102_tas5130d1b.o - et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o - zc0301-objs := zc0301_core.o zc0301_pas202bcb.o - ---- gregkh-2.6.orig/drivers/usb/media/sn9c102.h -+++ gregkh-2.6/drivers/usb/media/sn9c102.h -@@ -34,7 +34,8 @@ - #include <linux/param.h> - #include <linux/rwsem.h> - #include <linux/mutex.h> --#include <asm/semaphore.h> -+#include <linux/string.h> -+#include <linux/stddef.h> - - #include "sn9c102_sensor.h" - -@@ -51,6 +52,7 @@ - #define SN9C102_ALTERNATE_SETTING 8 - #define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS) - #define SN9C102_CTRL_TIMEOUT 300 -+#define SN9C102_FRAME_TIMEOUT 2 - - /*****************************************************************************/ - -@@ -108,6 +110,7 @@ struct sn9c102_sysfs_attr { - - struct sn9c102_module_param { - u8 force_munmap; -+ u16 frame_timeout; - }; - - static DEFINE_MUTEX(sn9c102_sysfs_lock); -@@ -117,7 +120,7 @@ struct sn9c102_device { - struct video_device* v4ldev; - - enum sn9c102_bridge bridge; -- struct sn9c102_sensor* sensor; -+ struct sn9c102_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[SN9C102_URBS]; -@@ -149,12 +152,21 @@ struct sn9c102_device { - - /*****************************************************************************/ - -+struct sn9c102_device* -+sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) -+{ -+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) -+ return cam; -+ -+ return NULL; -+} -+ -+ - void - sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) - { -- cam->sensor = sensor; -- cam->sensor->usbdev = cam->usbdev; -+ memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); - } - - /*****************************************************************************/ -@@ -197,7 +209,8 @@ do { - - #undef PDBG - #define PDBG(fmt, args...) \ --dev_info(&cam->dev, "[%s:%d] " fmt "\n", __FUNCTION__, __LINE__ , ## args) -+dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \ -+ __FUNCTION__, __LINE__ , ## args) - - #undef PDBGG - #define PDBGG(fmt, args...) do {;} while(0) /* placeholder */ ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_core.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_core.c -@@ -25,11 +25,9 @@ - #include <linux/moduleparam.h> - #include <linux/errno.h> - #include <linux/slab.h> --#include <linux/string.h> - #include <linux/device.h> - #include <linux/fs.h> - #include <linux/delay.h> --#include <linux/stddef.h> - #include <linux/compiler.h> - #include <linux/ioctl.h> - #include <linux/poll.h> -@@ -49,8 +47,8 @@ - #define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia" - #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" - #define SN9C102_MODULE_LICENSE "GPL" --#define SN9C102_MODULE_VERSION "1:1.26" --#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26) -+#define SN9C102_MODULE_VERSION "1:1.27" -+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 27) - - /*****************************************************************************/ - -@@ -89,6 +87,15 @@ MODULE_PARM_DESC(force_munmap, - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -+static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] = -+ SN9C102_FRAME_TIMEOUT}; -+module_param_array(frame_timeout, uint, NULL, 0644); -+MODULE_PARM_DESC(frame_timeout, -+ "\n<n[,...]> Timeout for a video frame in seconds." -+ "\nThis parameter is specific for each detected camera." -+ "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"." -+ "\n"); -+ - #ifdef SN9C102_DEBUG - static unsigned short debug = SN9C102_DEBUG_LEVEL; - module_param(debug, ushort, 0644); -@@ -128,8 +135,8 @@ static u32 - sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, - enum sn9c102_io_method io) - { -- struct v4l2_pix_format* p = &(cam->sensor->pix_format); -- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); -+ struct v4l2_pix_format* p = &(cam->sensor.pix_format); -+ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : -@@ -449,19 +456,13 @@ sn9c102_i2c_try_write(struct sn9c102_dev - - int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address) - { -- if (!cam->sensor) -- return -1; -- -- return sn9c102_i2c_try_read(cam, cam->sensor, address); -+ return sn9c102_i2c_try_read(cam, &cam->sensor, address); - } - - - int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value) - { -- if (!cam->sensor) -- return -1; -- -- return sn9c102_i2c_try_write(cam, cam->sensor, address, value); -+ return sn9c102_i2c_try_write(cam, &cam->sensor, address, value); - } - - /*****************************************************************************/ -@@ -505,7 +506,7 @@ sn9c102_find_eof_header(struct sn9c102_d - size_t eoflen = sizeof(sn9c102_eof_header_t), i; - unsigned j, n = sizeof(sn9c102_eof_header) / eoflen; - -- if (cam->sensor->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) -+ if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X) - return NULL; /* EOF header does not exist in compressed data */ - - for (i = 0; (len >= eoflen) && (i <= len - eoflen); i++) -@@ -535,7 +536,7 @@ static void sn9c102_urb_complete(struct - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) -@@ -553,9 +554,9 @@ static void sn9c102_urb_complete(struct - (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t, - frame); - -- imagesize = (cam->sensor->pix_format.width * -- cam->sensor->pix_format.height * -- cam->sensor->pix_format.priv) / 8; -+ imagesize = (cam->sensor.pix_format.width * -+ cam->sensor.pix_format.height * -+ cam->sensor.pix_format.priv) / 8; - - soflen = (cam->bridge) == BRIDGE_SN9C103 ? - sizeof(sn9c103_sof_header_t) : -@@ -579,7 +580,7 @@ static void sn9c102_urb_complete(struct - - redo: - sof = sn9c102_find_sof_header(cam, pos, len); -- if (!sof) { -+ if (likely(!sof)) { - eof = sn9c102_find_eof_header(cam, pos, len); - if ((*f)->state == F_GRABBING) { - end_of_frame: -@@ -589,8 +590,9 @@ end_of_frame: - img = (eof > pos) ? eof - pos - 1 : 0; - - if ((*f)->buf.bytesused+img > imagesize) { -- u32 b = (*f)->buf.bytesused + img - -- imagesize; -+ u32 b; -+ b = (*f)->buf.bytesused + img - -+ imagesize; - img = imagesize - (*f)->buf.bytesused; - DBG(3, "Expected EOF not found: " - "video frame cut"); -@@ -608,9 +610,10 @@ end_of_frame: - (*f)->buf.bytesused += img; - - if ((*f)->buf.bytesused == imagesize || -- (cam->sensor->pix_format.pixelformat == -+ (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X && eof)) { -- u32 b = (*f)->buf.bytesused; -+ u32 b; -+ b = (*f)->buf.bytesused; - (*f)->state = F_DONE; - (*f)->buf.sequence= ++cam->frame_count; - spin_lock(&cam->queue_lock); -@@ -667,7 +670,7 @@ start_of_frame: - if (eof && eof < sof) - goto end_of_frame; /* (1) */ - else { -- if (cam->sensor->pix_format.pixelformat == -+ if (cam->sensor.pix_format.pixelformat == - V4L2_PIX_FMT_SN9C10X) { - eof = sof - soflen; - goto end_of_frame; -@@ -808,20 +811,21 @@ static int sn9c102_stop_transfer(struct - - static int sn9c102_stream_interrupt(struct sn9c102_device* cam) - { -- int err = 0; -+ long timeout; - - cam->stream = STREAM_INTERRUPT; -- err = wait_event_timeout(cam->wait_stream, -- (cam->stream == STREAM_OFF) || -- (cam->state & DEV_DISCONNECTED), -- SN9C102_URB_TIMEOUT); -+ timeout = wait_event_timeout(cam->wait_stream, -+ (cam->stream == STREAM_OFF) || -+ (cam->state & DEV_DISCONNECTED), -+ SN9C102_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; -- else if (err) { -+ else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; -- DBG(1, "The camera is misconfigured. To use it, close and " -- "open /dev/video%d again.", cam->v4ldev->minor); -- return err; -+ DBG(1, "URB timeout reached. The camera is misconfigured. " -+ "To use it, close and open /dev/video%d again.", -+ cam->v4ldev->minor); -+ return -EIO; - } - - return 0; -@@ -1057,7 +1061,7 @@ static ssize_t sn9c102_show_i2c_val(stru - return -ENODEV; - } - -- if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) { -+ if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } -@@ -1094,7 +1098,7 @@ sn9c102_store_i2c_val(struct class_devic - return -ENODEV; - } - -- if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) { -+ if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { - mutex_unlock(&sn9c102_sysfs_lock); - return -ENOSYS; - } -@@ -1249,7 +1253,7 @@ static void sn9c102_create_sysfs(struct - video_device_create_file(v4ldev, &class_device_attr_blue); - video_device_create_file(v4ldev, &class_device_attr_red); - } -- if (cam->sensor && cam->sensor->sysfs_ops) { -+ if (cam->sensor.sysfs_ops) { - video_device_create_file(v4ldev, &class_device_attr_i2c_reg); - video_device_create_file(v4ldev, &class_device_attr_i2c_val); - } -@@ -1312,7 +1316,7 @@ static int sn9c102_set_scale(struct sn9c - - static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left), - v_start = (u8)(rect->top - s->cropcap.bounds.top), - h_size = (u8)(rect->width / 16), -@@ -1335,7 +1339,7 @@ static int sn9c102_set_crop(struct sn9c1 - - static int sn9c102_init(struct sn9c102_device* cam) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; -@@ -1428,6 +1432,8 @@ static void sn9c102_release_resources(st - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); - -+ usb_put_dev(cam->usbdev); -+ - mutex_unlock(&sn9c102_sysfs_lock); - - kfree(cam->control_buffer); -@@ -1541,6 +1547,7 @@ sn9c102_read(struct file* filp, char __u - struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); - struct sn9c102_frame_t* f, * i; - unsigned long lock_flags; -+ long timeout; - int err = 0; - - if (mutex_lock_interruptible(&cam->fileop_mutex)) -@@ -1592,20 +1599,22 @@ sn9c102_read(struct file* filp, char __u - mutex_unlock(&cam->fileop_mutex); - return -EAGAIN; - } -- err = wait_event_interruptible -- ( cam->wait_frame, -- (!list_empty(&cam->outqueue)) || -- (cam->state & DEV_DISCONNECTED) || -- (cam->state & DEV_MISCONFIGURED) ); -- if (err) { -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); -+ if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); -- return err; -+ return timeout; - } - if (cam->state & DEV_DISCONNECTED) { - mutex_unlock(&cam->fileop_mutex); - return -ENODEV; - } -- if (cam->state & DEV_MISCONFIGURED) { -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) { - mutex_unlock(&cam->fileop_mutex); - return -EIO; - } -@@ -1816,6 +1825,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_ - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); -+ i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; -@@ -1825,7 +1835,19 @@ sn9c102_vidioc_enuminput(struct sn9c102_ - - - static int --sn9c102_vidioc_gs_input(struct sn9c102_device* cam, void __user * arg) -+sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg) -+{ -+ int index = 0; -+ -+ if (copy_to_user(arg, &index, sizeof(index))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg) - { - int index; - -@@ -1842,7 +1864,7 @@ sn9c102_vidioc_gs_input(struct sn9c102_d - static int - sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - -@@ -1864,7 +1886,7 @@ sn9c102_vidioc_query_ctrl(struct sn9c102 - static int - sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; -@@ -1896,7 +1918,7 @@ exit: - static int - sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; -@@ -1909,6 +1931,8 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_dev - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { -+ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) -+ return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; -@@ -1931,7 +1955,7 @@ sn9c102_vidioc_s_ctrl(struct sn9c102_dev - static int - sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg) - { -- struct v4l2_cropcap* cc = &(cam->sensor->cropcap); -+ struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; -@@ -1947,7 +1971,7 @@ sn9c102_vidioc_cropcap(struct sn9c102_de - static int - sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; -@@ -1964,7 +1988,7 @@ sn9c102_vidioc_g_crop(struct sn9c102_dev - static int - sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); -@@ -2105,7 +2129,7 @@ static int - sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg) - { - struct v4l2_format format; -- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); -+ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; -@@ -2130,7 +2154,7 @@ static int - sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, - void __user * arg) - { -- struct sn9c102_sensor* s = cam->sensor; -+ struct sn9c102_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); -@@ -2417,7 +2441,7 @@ sn9c102_vidioc_dqbuf(struct sn9c102_devi - struct v4l2_buffer b; - struct sn9c102_frame_t *f; - unsigned long lock_flags; -- int err = 0; -+ long timeout; - - if (copy_from_user(&b, arg, sizeof(b))) - return -EFAULT; -@@ -2430,16 +2454,18 @@ sn9c102_vidioc_dqbuf(struct sn9c102_devi - return -EINVAL; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; -- err = wait_event_interruptible -- ( cam->wait_frame, -- (!list_empty(&cam->outqueue)) || -- (cam->state & DEV_DISCONNECTED) || -- (cam->state & DEV_MISCONFIGURED) ); -- if (err) -- return err; -+ timeout = wait_event_interruptible_timeout -+ ( cam->wait_frame, -+ (!list_empty(&cam->outqueue)) || -+ (cam->state & DEV_DISCONNECTED) || -+ (cam->state & DEV_MISCONFIGURED), -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); -+ if (timeout < 0) -+ return timeout; - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; -- if (cam->state & DEV_MISCONFIGURED) -+ if (!timeout || (cam->state & DEV_MISCONFIGURED)) - return -EIO; - } - -@@ -2571,8 +2597,10 @@ static int sn9c102_ioctl_v4l2(struct ino - return sn9c102_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: -+ return sn9c102_vidioc_g_input(cam, arg); -+ - case VIDIOC_S_INPUT: -- return sn9c102_vidioc_gs_input(cam, arg); -+ return sn9c102_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return sn9c102_vidioc_query_ctrl(cam, arg); -@@ -2752,10 +2780,10 @@ sn9c102_usb_probe(struct usb_interface* - break; - } - -- if (!err && cam->sensor) { -- DBG(2, "%s image sensor detected", cam->sensor->name); -+ if (!err) { -+ DBG(2, "%s image sensor detected", cam->sensor.name); - DBG(3, "Support for %s maintained by %s", -- cam->sensor->name, cam->sensor->maintainer); -+ cam->sensor.name, cam->sensor.maintainer); - } else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; -@@ -2793,6 +2821,7 @@ sn9c102_usb_probe(struct usb_interface* - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; -+ cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; - -@@ -2841,7 +2870,8 @@ static void sn9c102_usb_disconnect(struc - sn9c102_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); -+ usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - sn9c102_release_resources(cam); ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_ov7630.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_ov7630.c -@@ -34,8 +34,8 @@ static int ov7630_init(struct sn9c102_de - err += sn9c102_write_reg(cam, 0x0f, 0x18); - err += sn9c102_write_reg(cam, 0x50, 0x19); - -- err += sn9c102_i2c_write(cam, 0x12, 0x8d); -- err += sn9c102_i2c_write(cam, 0x11, 0x00); -+ err += sn9c102_i2c_write(cam, 0x12, 0x80); -+ err += sn9c102_i2c_write(cam, 0x11, 0x01); - err += sn9c102_i2c_write(cam, 0x15, 0x34); - err += sn9c102_i2c_write(cam, 0x16, 0x03); - err += sn9c102_i2c_write(cam, 0x17, 0x1c); -@@ -43,12 +43,14 @@ static int ov7630_init(struct sn9c102_de - err += sn9c102_i2c_write(cam, 0x19, 0x06); - err += sn9c102_i2c_write(cam, 0x1a, 0xf6); - err += sn9c102_i2c_write(cam, 0x1b, 0x04); -- err += sn9c102_i2c_write(cam, 0x20, 0x44); -+ err += sn9c102_i2c_write(cam, 0x20, 0xf6); - err += sn9c102_i2c_write(cam, 0x23, 0xee); - err += sn9c102_i2c_write(cam, 0x26, 0xa0); - err += sn9c102_i2c_write(cam, 0x27, 0x9a); -- err += sn9c102_i2c_write(cam, 0x28, 0x20); -+ err += sn9c102_i2c_write(cam, 0x28, 0xa0); - err += sn9c102_i2c_write(cam, 0x29, 0x30); -+ err += sn9c102_i2c_write(cam, 0x2a, 0xa0); -+ err += sn9c102_i2c_write(cam, 0x2b, 0x1f); - err += sn9c102_i2c_write(cam, 0x2f, 0x3d); - err += sn9c102_i2c_write(cam, 0x30, 0x24); - err += sn9c102_i2c_write(cam, 0x32, 0x86); -@@ -80,7 +82,7 @@ static int ov7630_set_ctrl(struct sn9c10 - err += sn9c102_i2c_write(cam, 0x02, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: -- err += sn9c102_i2c_write(cam, 0x03, ctrl->value); -+ err += sn9c102_i2c_write(cam, 0x01, ctrl->value); - break; - case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); -@@ -108,7 +110,7 @@ static int ov7630_set_ctrl(struct sn9c10 - err += sn9c102_i2c_write(cam, 0x0d, ctrl->value); - break; - case V4L2_CID_AUTO_WHITE_BALANCE: -- err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x09); -+ err += sn9c102_i2c_write(cam, 0x12, (ctrl->value << 2) | 0x78); - break; - case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, ctrl->value); -@@ -371,26 +373,29 @@ static struct sn9c102_sensor ov7630 = { - - int sn9c102_probe_ov7630(struct sn9c102_device* cam) - { -+ const struct usb_device_id ov7630_id_table[] = { -+ { USB_DEVICE(0x0c45, 0x602c), }, -+ { USB_DEVICE(0x0c45, 0x602d), }, -+ { USB_DEVICE(0x0c45, 0x608f), }, -+ { USB_DEVICE(0x0c45, 0x60b0), }, -+ { } -+ }; - int err = 0; - -- sn9c102_attach_sensor(cam, &ov7630); -- -- if (le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602c && -- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x602d && -- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x608f && -- le16_to_cpu(ov7630.usbdev->descriptor.idProduct) != 0x60b0) -+ if (!sn9c102_match_id(cam, ov7630_id_table)) - return -ENODEV; - - err += sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - err += sn9c102_write_reg(cam, 0x28, 0x17); -- - if (err) - return -EIO; - -- err += sn9c102_i2c_write(cam, 0x0b, 0); -+ err += sn9c102_i2c_try_write(cam, &ov7630, 0x0b, 0); - if (err) - return -ENODEV; - -+ sn9c102_attach_sensor(cam, &ov7630); -+ - return 0; - } ---- /dev/null -+++ gregkh-2.6/drivers/usb/media/sn9c102_pas202bca.c -@@ -0,0 +1,238 @@ -+/*************************************************************************** -+ * Plug-in for PAS202BCA image sensor connected to the SN9C10x PC Camera * -+ * Controllers * -+ * * -+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * -+ * * -+ * This program is free software; you can redistribute it and/or modify * -+ * it under the terms of the GNU General Public License as published by * -+ * the Free Software Foundation; either version 2 of the License, or * -+ * (at your option) any later version. * -+ * * -+ * This program is distributed in the hope that it will be useful, * -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of * -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -+ * GNU General Public License for more details. * -+ * * -+ * You should have received a copy of the GNU General Public License * -+ * along with this program; if not, write to the Free Software * -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -+ ***************************************************************************/ -+ -+#include <linux/delay.h> -+#include "sn9c102_sensor.h" -+ -+ -+static struct sn9c102_sensor pas202bca; -+ -+ -+static int pas202bca_init(struct sn9c102_device* cam) -+{ -+ int err = 0; -+ -+ err += sn9c102_write_reg(cam, 0x00, 0x10); -+ err += sn9c102_write_reg(cam, 0x00, 0x11); -+ err += sn9c102_write_reg(cam, 0x00, 0x14); -+ err += sn9c102_write_reg(cam, 0x20, 0x17); -+ err += sn9c102_write_reg(cam, 0x30, 0x19); -+ err += sn9c102_write_reg(cam, 0x09, 0x18); -+ -+ err += sn9c102_i2c_write(cam, 0x02, 0x14); -+ err += sn9c102_i2c_write(cam, 0x03, 0x40); -+ err += sn9c102_i2c_write(cam, 0x0d, 0x2c); -+ err += sn9c102_i2c_write(cam, 0x0e, 0x01); -+ err += sn9c102_i2c_write(cam, 0x0f, 0xa9); -+ err += sn9c102_i2c_write(cam, 0x10, 0x08); -+ err += sn9c102_i2c_write(cam, 0x13, 0x63); -+ err += sn9c102_i2c_write(cam, 0x15, 0x70); -+ err += sn9c102_i2c_write(cam, 0x11, 0x01); -+ -+ msleep(400); -+ -+ return err; -+} -+ -+ -+static int pas202bca_set_pix_format(struct sn9c102_device* cam, -+ const struct v4l2_pix_format* pix) -+{ -+ int err = 0; -+ -+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) -+ err += sn9c102_write_reg(cam, 0x24, 0x17); -+ else -+ err += sn9c102_write_reg(cam, 0x20, 0x17); -+ -+ return err; -+} -+ -+ -+static int pas202bca_set_ctrl(struct sn9c102_device* cam, -+ const struct v4l2_control* ctrl) -+{ -+ int err = 0; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_EXPOSURE: -+ err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6); -+ err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f); -+ break; -+ case V4L2_CID_RED_BALANCE: -+ err += sn9c102_i2c_write(cam, 0x09, ctrl->value); -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ err += sn9c102_i2c_write(cam, 0x07, ctrl->value); -+ break; -+ case V4L2_CID_GAIN: -+ err += sn9c102_i2c_write(cam, 0x10, ctrl->value); -+ break; -+ case SN9C102_V4L2_CID_GREEN_BALANCE: -+ err += sn9c102_i2c_write(cam, 0x08, ctrl->value); -+ break; -+ case SN9C102_V4L2_CID_DAC_MAGNITUDE: -+ err += sn9c102_i2c_write(cam, 0x0c, ctrl->value); -+ break; -+ default: -+ return -EINVAL; -+ } -+ err += sn9c102_i2c_write(cam, 0x11, 0x01); -+ -+ return err ? -EIO : 0; -+} -+ -+ -+static int pas202bca_set_crop(struct sn9c102_device* cam, -+ const struct v4l2_rect* rect) -+{ -+ struct sn9c102_sensor* s = &pas202bca; -+ int err = 0; -+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3, -+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3; -+ -+ err += sn9c102_write_reg(cam, h_start, 0x12); -+ err += sn9c102_write_reg(cam, v_start, 0x13); -+ -+ return err; -+} -+ -+ -+static struct sn9c102_sensor pas202bca = { -+ .name = "PAS202BCA", -+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", -+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE, -+ .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ, -+ .interface = SN9C102_I2C_2WIRES, -+ .i2c_slave_id = 0x40, -+ .init = &pas202bca_init, -+ .qctrl = { -+ { -+ .id = V4L2_CID_EXPOSURE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "exposure", -+ .minimum = 0x01e5, -+ .maximum = 0x3fff, -+ .step = 0x0001, -+ .default_value = 0x01e5, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_GAIN, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "global gain", -+ .minimum = 0x00, -+ .maximum = 0x1f, -+ .step = 0x01, -+ .default_value = 0x0c, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_RED_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "red balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x01, -+ .flags = 0, -+ }, -+ { -+ .id = V4L2_CID_BLUE_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "blue balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x05, -+ .flags = 0, -+ }, -+ { -+ .id = SN9C102_V4L2_CID_GREEN_BALANCE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "green balance", -+ .minimum = 0x00, -+ .maximum = 0x0f, -+ .step = 0x01, -+ .default_value = 0x00, -+ .flags = 0, -+ }, -+ { -+ .id = SN9C102_V4L2_CID_DAC_MAGNITUDE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "DAC magnitude", -+ .minimum = 0x00, -+ .maximum = 0xff, -+ .step = 0x01, -+ .default_value = 0x04, -+ .flags = 0, -+ }, -+ }, -+ .set_ctrl = &pas202bca_set_ctrl, -+ .cropcap = { -+ .bounds = { -+ .left = 0, -+ .top = 0, -+ .width = 640, -+ .height = 480, -+ }, -+ .defrect = { -+ .left = 0, -+ .top = 0, -+ .width = 640, -+ .height = 480, -+ }, -+ }, -+ .set_crop = &pas202bca_set_crop, -+ .pix_format = { -+ .width = 640, -+ .height = 480, -+ .pixelformat = V4L2_PIX_FMT_SBGGR8, -+ .priv = 8, -+ }, -+ .set_pix_format = &pas202bca_set_pix_format -+}; -+ -+ -+int sn9c102_probe_pas202bca(struct sn9c102_device* cam) -+{ -+ const struct usb_device_id pas202bca_id_table[] = { -+ { USB_DEVICE(0x0c45, 0x60af), }, -+ { } -+ }; -+ int err = 0; -+ -+ if (!sn9c102_match_id(cam,pas202bca_id_table)) -+ return -ENODEV; -+ -+ err += sn9c102_write_reg(cam, 0x01, 0x01); -+ err += sn9c102_write_reg(cam, 0x40, 0x01); -+ err += sn9c102_write_reg(cam, 0x28, 0x17); -+ if (err) -+ return -EIO; -+ -+ if (sn9c102_i2c_try_write(cam, &pas202bca, 0x10, 0)) /* try to write */ -+ return -ENODEV; -+ -+ sn9c102_attach_sensor(cam, &pas202bca); -+ -+ return 0; -+} ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_pas202bcb.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_pas202bcb.c -@@ -263,7 +263,7 @@ static struct sn9c102_sensor pas202bcb = - - - int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) --{ -+{ - int r0 = 0, r1 = 0, err = 0; - unsigned int pid = 0; - ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_sensor.h -+++ gregkh-2.6/drivers/usb/media/sn9c102_sensor.h -@@ -66,6 +66,7 @@ extern int sn9c102_probe_hv7131d(struct - extern int sn9c102_probe_mi0343(struct sn9c102_device* cam); - extern int sn9c102_probe_ov7630(struct sn9c102_device* cam); - extern int sn9c102_probe_pas106b(struct sn9c102_device* cam); -+extern int sn9c102_probe_pas202bca(struct sn9c102_device* cam); - extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam); - extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam); - extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam); -@@ -81,12 +82,17 @@ static int (*sn9c102_sensor_table[])(str - &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \ - &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \ -+ &sn9c102_probe_pas202bca, /* detection mostly based on USB pid/vid */ \ - &sn9c102_probe_ov7630, /* detection mostly based on USB pid/vid */ \ - &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \ - &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \ - NULL, \ - }; - -+/* Device identification */ -+extern struct sn9c102_device* -+sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); -+ - /* Attach a probed sensor to the camera. */ - extern void - sn9c102_attach_sensor(struct sn9c102_device* cam, -@@ -108,6 +114,7 @@ sn9c102_attach_sensor(struct sn9c102_dev - static const struct usb_device_id sn9c102_id_table[] = { \ - { USB_DEVICE(0x0c45, 0x6001), }, /* TAS5110C1B */ \ - { USB_DEVICE(0x0c45, 0x6005), }, /* TAS5110C1B */ \ -+ { USB_DEVICE(0x0c45, 0x6007), }, \ - { USB_DEVICE(0x0c45, 0x6009), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x600d), }, /* PAS106B */ \ - { USB_DEVICE(0x0c45, 0x6024), }, \ -@@ -126,7 +133,7 @@ static const struct usb_device_id sn9c10 - { SN9C102_USB_DEVICE(0x0c45, 0x6088, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608a, 0xff), }, \ - { SN9C102_USB_DEVICE(0x0c45, 0x608b, 0xff), }, \ -- { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131x */ \ -+ { SN9C102_USB_DEVICE(0x0c45, 0x608c, 0xff), }, /* HV7131/R */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x608e, 0xff), }, /* CIS-VF10 */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x608f, 0xff), }, /* OV7630 */ \ - { SN9C102_USB_DEVICE(0x0c45, 0x60a0, 0xff), }, \ -@@ -359,12 +366,6 @@ struct sn9c102_sensor { - error code without rolling back. - */ - -- const struct usb_device* usbdev; -- /* -- Points to the usb_device struct after the sensor is attached. -- Do not touch unless you know what you are doing. -- */ -- - /* - Do NOT write to the data below, it's READ ONLY. It is used by the - core module to store successfully updated values of the above ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_tas5110c1b.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_tas5110c1b.c -@@ -142,14 +142,18 @@ static struct sn9c102_sensor tas5110c1b - - int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam) - { -- /* This sensor has no identifiers, so let's attach it anyway */ -- sn9c102_attach_sensor(cam, &tas5110c1b); -+ const struct usb_device_id tas5110c1b_id_table[] = { -+ { USB_DEVICE(0x0c45, 0x6001), }, -+ { USB_DEVICE(0x0c45, 0x6005), }, -+ { USB_DEVICE(0x0c45, 0x60ab), }, -+ { } -+ }; - - /* Sensor detection is based on USB pid/vid */ -- if (le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6001 && -- le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6005 && -- le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x60ab) -+ if (!sn9c102_match_id(cam, tas5110c1b_id_table)) - return -ENODEV; - -+ sn9c102_attach_sensor(cam, &tas5110c1b); -+ - return 0; - } ---- gregkh-2.6.orig/drivers/usb/media/sn9c102_tas5130d1b.c -+++ gregkh-2.6/drivers/usb/media/sn9c102_tas5130d1b.c -@@ -153,13 +153,17 @@ static struct sn9c102_sensor tas5130d1b - - int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam) - { -- /* This sensor has no identifiers, so let's attach it anyway */ -- sn9c102_attach_sensor(cam, &tas5130d1b); -+ const struct usb_device_id tas5130d1b_id_table[] = { -+ { USB_DEVICE(0x0c45, 0x6025), }, -+ { USB_DEVICE(0x0c45, 0x60aa), }, -+ { } -+ }; - - /* Sensor detection is based on USB pid/vid */ -- if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6025 && -- le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x60aa) -+ if (!sn9c102_match_id(cam, tas5130d1b_id_table)) - return -ENODEV; - -+ sn9c102_attach_sensor(cam, &tas5130d1b); -+ - return 0; - } diff --git a/usb/usb-storage-another-unusual_devs.h-entry.patch b/usb/usb-storage-another-unusual_devs.h-entry.patch deleted file mode 100644 index 4008b1c66305e..0000000000000 --- a/usb/usb-storage-another-unusual_devs.h-entry.patch +++ /dev/null @@ -1,35 +0,0 @@ -From phil@ipom.com Sun Mar 5 21:43:46 2006 -Message-ID: <440BCC0C.1090103@ipom.com> -Date: Sun, 05 Mar 2006 21:43:40 -0800 -From: Phil Dibowitz <phil@ipom.com> -To: Greg KH <greg@kroah.com>, <chris@rebelbase.com>, <zaitcev@redhat.com> -Subject: USB: storage: another unusual_devs.h entry - -From: Pete Zaitcev <zaitcev@redhat.com> - -Signed-off-by: Phil Dibowitz <phil@ipom.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/storage/unusual_devs.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h -+++ gregkh-2.6/drivers/usb/storage/unusual_devs.h -@@ -1080,6 +1080,16 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xf - 0), - #endif - -+/* -+ * Pete Zaitcev <zaitcev@yahoo.com>, bz#164688. -+ * The device blatantly ignores LUN and returns 1 in GetMaxLUN. -+ */ -+UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, -+ "Unknown", -+ "Unknown", -+ US_SC_DEVICE, US_PR_DEVICE, NULL, -+ US_FL_SINGLE_LUN ), -+ - /* Submitted by Joris Struyve <joris@struyve.be> */ - UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, - "Medion", diff --git a/usb/usb-storage-new-unusual_devs.h-entry-mitsumi-7in1-card-reader.patch b/usb/usb-storage-new-unusual_devs.h-entry-mitsumi-7in1-card-reader.patch deleted file mode 100644 index 7428f1225b8aa..0000000000000 --- a/usb/usb-storage-new-unusual_devs.h-entry-mitsumi-7in1-card-reader.patch +++ /dev/null @@ -1,37 +0,0 @@ -From stern@rowland.harvard.edu Mon Mar 6 07:45:50 2006 -Date: Mon, 6 Mar 2006 10:45:42 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -cc: "Rodolfo Quesada Z." <rquesada@eml.cc>, Phil Dibowitz <phil@ipom.com> -Subject: USB: storage: new unusual_devs.h entry: Mitsumi 7in1 Card Reader -Message-ID: <Pine.LNX.4.44L0.0603061042190.5142-100000@iolanthe.rowland.org> - -From: Rodolfo Quesada <rquesada@roqz.net> - -This patch (as661) adds an unusual_devs entry for the Mitsumi 7in1 Card -Reader. - -From: Rodolfo Quesada <rquesada@roqz.net> -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/storage/unusual_devs.h | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h -+++ gregkh-2.6/drivers/usb/storage/unusual_devs.h -@@ -62,6 +62,13 @@ UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN ), - -+/* Reported by Rodolfo Quesada <rquesada@roqz.net> */ -+UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003, -+ "VIA Technologies Inc.", -+ "Mitsumi multi cardreader", -+ US_SC_DEVICE, US_PR_DEVICE, NULL, -+ US_FL_IGNORE_RESIDUE ), -+ - UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, - "HP", - "CD-Writer+", diff --git a/usb/usb-storage-sandisk-unusual_devices-entry.patch b/usb/usb-storage-sandisk-unusual_devices-entry.patch deleted file mode 100644 index 3f9895e62d20c..0000000000000 --- a/usb/usb-storage-sandisk-unusual_devices-entry.patch +++ /dev/null @@ -1,45 +0,0 @@ -From phil@ipom.com Sun Mar 5 21:36:56 2006 -Message-ID: <440BCA73.1050904@ipom.com> -Date: Sun, 05 Mar 2006 21:36:51 -0800 -From: Phil Dibowitz <phil@ipom.com> -To: Roman Hodek <roman@hodek.net>, Greg KH <greg@kroah.com> -Subject: USB: storage: sandisk unusual_devices entry - - -The following adds an unusual_devs entry for the SanDisk ImageMate CompactFlash -USB drive, for the US_FL_FIX_CAPACITY flag. Additionally, it removes trailing -whitespace from the previous entry. It's based on the patch sent by Roman Hodek -<roman@hodek.net>. - -Signed-off-by: Phil Dibowitz <phil@ipom.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - - ---- - drivers/usb/storage/unusual_devs.h | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h -+++ gregkh-2.6/drivers/usb/storage/unusual_devs.h -@@ -760,12 +760,19 @@ UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - --UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, -+/* Submitted by Roman Hodek <roman@hodek.net> */ -+UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200, - "Sandisk", - "ImageMate SDDR-05a", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN ), - -+UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, -+ "SanDisk Corporation", -+ "ImageMate CompactFlash USB", -+ US_SC_DEVICE, US_PR_DEVICE, NULL, -+ US_FL_FIX_CAPACITY ), -+ - #ifdef CONFIG_USB_STORAGE_USBAT - UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, - "Sandisk", diff --git a/usb/usb-storage-unusual_devs.h-entry-0420-0001.patch b/usb/usb-storage-unusual_devs.h-entry-0420-0001.patch deleted file mode 100644 index 9aa41aae402c0..0000000000000 --- a/usb/usb-storage-unusual_devs.h-entry-0420-0001.patch +++ /dev/null @@ -1,34 +0,0 @@ -From phil@ipom.com Sun Mar 5 21:45:49 2006 -Message-ID: <440BCC88.4040001@ipom.com> -Date: Sun, 05 Mar 2006 21:45:44 -0800 -From: Phil Dibowitz <phil@ipom.com> -To: Greg KH <greg@kroah.com>, <zaitcev@redhat.com>, <chris@rebelbase.com> -Subject: USB: storage: unusual_devs.h entry 0420:0001 - -From: Pete Zaitcev <zaitcev@redhat.com> - -Ref -https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=176584 - -Signed-off-by: Phil Dibowitz <phil@ipom.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/storage/unusual_devs.h | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/storage/unusual_devs.h -+++ gregkh-2.6/drivers/usb/storage/unusual_devs.h -@@ -120,6 +120,12 @@ UNUSUAL_DEV( 0x0419, 0xaaf6, 0x0100, 0x - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE ), - -+/* Reported by Pete Zaitcev <zaitcev@redhat.com>, bz#176584 */ -+UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, -+ "GENERIC", "MP3 PLAYER", /* MyMusix PD-205 on the outside. */ -+ US_SC_DEVICE, US_PR_DEVICE, NULL, -+ US_FL_IGNORE_RESIDUE ), -+ - /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ - UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, - "SMSC", diff --git a/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch b/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch deleted file mode 100644 index 043b322d58df9..0000000000000 --- a/usb/usb-support-for-usb-to-serial-cable-from-speed-dragon-multimedia.patch +++ /dev/null @@ -1,42 +0,0 @@ -From akpm@osdl.org Wed Mar 1 15:57:52 2006 -Message-Id: <200603010854.k218sepU024122@shell0.pdx.osdl.net> -Subject: USB: support for USB-to-serial cable from Speed Dragon Multimedia -To: dick@streefland.net, greg@kroah.com, mm-commits@vger.kernel.org -From: akpm@osdl.org -Date: Wed, 01 Mar 2006 00:53:33 -0800 - -From: Dick Streefland <dick@streefland.net> - -The USB data cable for my Samsung GSM phone contains the USB-to-serial -converter chip MS3303H from Speed Dragon Multimedia, Inc. that appears to -be compatible with the PL2303 chip. The following patch adds support for -this chip to the pl2303 driver. - -Signed-off-by: Dick Streefland <dick@streefland.net> -Signed-off-by: Andrew Morton <akpm@osdl.org> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> ---- - drivers/usb/serial/pl2303.c | 1 + - drivers/usb/serial/pl2303.h | 4 ++++ - 2 files changed, 5 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/serial/pl2303.c -+++ gregkh-2.6/drivers/usb/serial/pl2303.c -@@ -77,6 +77,7 @@ static struct usb_device_id id_table [] - { USB_DEVICE(CA_42_CA42_VENDOR_ID, CA_42_CA42_PRODUCT_ID) }, - { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, - { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, -+ { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, - { } /* Terminating entry */ - }; - ---- gregkh-2.6.orig/drivers/usb/serial/pl2303.h -+++ gregkh-2.6/drivers/usb/serial/pl2303.h -@@ -75,3 +75,7 @@ - /* Leadtek GPS 9531 (ID 0413:2101) */ - #define LEADTEK_VENDOR_ID 0x0413 - #define LEADTEK_9531_PRODUCT_ID 0x2101 -+ -+/* USB GSM cable from Speed Dragon Multimedia, Ltd */ -+#define SPEEDDRAGON_VENDOR_ID 0x0e55 -+#define SPEEDDRAGON_PRODUCT_ID 0x110b diff --git a/usb/usb-ub-01-remove-first_open.patch b/usb/usb-ub-01-remove-first_open.patch deleted file mode 100644 index 494b3f51bba3b..0000000000000 --- a/usb/usb-ub-01-remove-first_open.patch +++ /dev/null @@ -1,71 +0,0 @@ -From zaitcev@redhat.com Thu Mar 2 16:36:30 2006 -Date: Thu, 2 Mar 2006 16:36:09 -0800 -From: Pete Zaitcev <zaitcev@redhat.com> -To: greg@kroah.com -Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net -Subject: USB: ub 01 remove first_open -Message-Id: <20060302163609.21b4236a.zaitcev@redhat.com> - -The first_open was long overdue for removal, but I wanted to keep this -separate for other changes in case of regressions. - -Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/block/ub.c | 23 ----------------------- - 1 file changed, 23 deletions(-) - ---- gregkh-2.6.orig/drivers/block/ub.c -+++ gregkh-2.6/drivers/block/ub.c -@@ -8,7 +8,6 @@ - * and is not licensed separately. See file COPYING for details. - * - * TODO (sorted by decreasing priority) -- * -- Kill first_open (Al Viro fixed the block layer now) - * -- set readonly flag for CDs, set removable flag for CF readers - * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) - * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries -@@ -334,7 +333,6 @@ struct ub_lun { - int changed; /* Media was changed */ - int removable; - int readonly; -- int first_open; /* Kludge. See ub_bd_open. */ - - struct ub_request urq; - -@@ -1849,26 +1847,6 @@ static int ub_bd_open(struct inode *inod - sc->openc++; - spin_unlock_irqrestore(&ub_lock, flags); - -- /* -- * This is a workaround for a specific problem in our block layer. -- * In 2.6.9, register_disk duplicates the code from rescan_partitions. -- * However, if we do add_disk with a device which persistently reports -- * a changed media, add_disk calls register_disk, which does do_open, -- * which will call rescan_paritions for changed media. After that, -- * register_disk attempts to do it all again and causes double kobject -- * registration and a eventually an oops on module removal. -- * -- * The bottom line is, Al Viro says that we should not allow -- * bdev->bd_invalidated to be set when doing add_disk no matter what. -- */ -- if (lun->first_open) { -- lun->first_open = 0; -- if (lun->changed) { -- rc = -ENOMEDIUM; -- goto err_open; -- } -- } -- - if (lun->removable || lun->readonly) - check_disk_change(inode->i_bdev); - -@@ -2537,7 +2515,6 @@ static int ub_probe_lun(struct ub_dev *s - - lun->removable = 1; /* XXX Query this from the device */ - lun->changed = 1; /* ub_revalidate clears only */ -- lun->first_open = 1; - ub_revalidate(sc, lun); - - rc = -ENOMEM; diff --git a/usb/usb-ub-02-remove-diag.patch b/usb/usb-ub-02-remove-diag.patch deleted file mode 100644 index 85b976ec58830..0000000000000 --- a/usb/usb-ub-02-remove-diag.patch +++ /dev/null @@ -1,395 +0,0 @@ -From zaitcev@redhat.com Thu Mar 2 16:43:23 2006 -Date: Thu, 2 Mar 2006 16:42:59 -0800 -From: Pete Zaitcev <zaitcev@redhat.com> -To: greg@kroah.com -Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net, viro@www.linux.org.uk -Subject: USB: ub 02 remove diag -Message-Id: <20060302164259.095ab85b.zaitcev@redhat.com> - -Remove the "diag" file from the sysfs. The usbmon is good enough these days -so I do not need this feature anymore. Also, sysfs is a pain. Al Viro caught -a race in this, which I thought too bothersome to fix. - -Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/block/ub.c | 197 +---------------------------------------------------- - 1 file changed, 4 insertions(+), 193 deletions(-) - ---- gregkh-2.6.orig/drivers/block/ub.c -+++ gregkh-2.6/drivers/block/ub.c -@@ -180,6 +180,7 @@ struct ub_dev; - #define UB_DIR_ILLEGAL2 2 - #define UB_DIR_WRITE 3 - -+/* P3 */ - #define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ - (((c)==UB_DIR_READ)? 'r': 'n')) - -@@ -195,24 +196,11 @@ enum ub_scsi_cmd_state { - UB_CMDST_DONE /* Final state */ - }; - --static char *ub_scsi_cmd_stname[] = { -- ". ", -- "Cmd", -- "dat", -- "c2s", -- "sts", -- "clr", -- "crs", -- "Sen", -- "fin" --}; -- - struct ub_scsi_cmd { - unsigned char cdb[UB_MAX_CDB_SIZE]; - unsigned char cdb_len; - - unsigned char dir; /* 0 - none, 1 - read, 3 - write. */ -- unsigned char trace_index; - enum ub_scsi_cmd_state state; - unsigned int tag; - struct ub_scsi_cmd *next; -@@ -249,28 +237,6 @@ struct ub_capacity { - }; - - /* -- * The SCSI command tracing structure. -- */ -- --#define SCMD_ST_HIST_SZ 8 --#define SCMD_TRACE_SZ 63 /* Less than 4KB of 61-byte lines */ -- --struct ub_scsi_cmd_trace { -- int hcur; -- unsigned int tag; -- unsigned int req_size, act_size; -- unsigned char op; -- unsigned char dir; -- unsigned char key, asc, ascq; -- char st_hst[SCMD_ST_HIST_SZ]; --}; -- --struct ub_scsi_trace { -- int cur; -- struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ]; --}; -- --/* - * This is a direct take-off from linux/include/completion.h - * The difference is that I do not wait on this thing, just poll. - * When I want to wait (ub_probe), I just use the stock completion. -@@ -388,7 +354,6 @@ struct ub_dev { - wait_queue_head_t reset_wait; - - int sg_stat[6]; -- struct ub_scsi_trace tr; - }; - - /* -@@ -458,137 +423,6 @@ static int ub_qlock_next = 0; - static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ - - /* -- * The SCSI command tracing procedures. -- */ -- --static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd) --{ -- int n; -- struct ub_scsi_cmd_trace *t; -- -- if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0; -- t = &sc->tr.vec[n]; -- -- memset(t, 0, sizeof(struct ub_scsi_cmd_trace)); -- t->tag = cmd->tag; -- t->op = cmd->cdb[0]; -- t->dir = cmd->dir; -- t->req_size = cmd->len; -- t->st_hst[0] = cmd->state; -- -- sc->tr.cur = n; -- cmd->trace_index = n; --} -- --static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd) --{ -- int n; -- struct ub_scsi_cmd_trace *t; -- -- t = &sc->tr.vec[cmd->trace_index]; -- if (t->tag == cmd->tag) { -- if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0; -- t->st_hst[n] = cmd->state; -- t->hcur = n; -- } --} -- --static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd) --{ -- struct ub_scsi_cmd_trace *t; -- -- t = &sc->tr.vec[cmd->trace_index]; -- if (t->tag == cmd->tag) -- t->act_size = cmd->act_len; --} -- --static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd, -- unsigned char *sense) --{ -- struct ub_scsi_cmd_trace *t; -- -- t = &sc->tr.vec[cmd->trace_index]; -- if (t->tag == cmd->tag) { -- t->key = sense[2] & 0x0F; -- t->asc = sense[12]; -- t->ascq = sense[13]; -- } --} -- --static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, -- char *page) --{ -- struct usb_interface *intf; -- struct ub_dev *sc; -- struct list_head *p; -- struct ub_lun *lun; -- int cnt; -- unsigned long flags; -- int nc, nh; -- int i, j; -- struct ub_scsi_cmd_trace *t; -- -- intf = to_usb_interface(dev); -- sc = usb_get_intfdata(intf); -- if (sc == NULL) -- return 0; -- -- cnt = 0; -- spin_lock_irqsave(sc->lock, flags); -- -- cnt += sprintf(page + cnt, -- "poison %d reset %d\n", -- atomic_read(&sc->poison), sc->reset); -- cnt += sprintf(page + cnt, -- "qlen %d qmax %d\n", -- sc->cmd_queue.qlen, sc->cmd_queue.qmax); -- cnt += sprintf(page + cnt, -- "sg %d %d %d %d %d .. %d\n", -- sc->sg_stat[0], -- sc->sg_stat[1], -- sc->sg_stat[2], -- sc->sg_stat[3], -- sc->sg_stat[4], -- sc->sg_stat[5]); -- -- list_for_each (p, &sc->luns) { -- lun = list_entry(p, struct ub_lun, link); -- cnt += sprintf(page + cnt, -- "lun %u changed %d removable %d readonly %d\n", -- lun->num, lun->changed, lun->removable, lun->readonly); -- } -- -- if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0; -- for (j = 0; j < SCMD_TRACE_SZ; j++) { -- t = &sc->tr.vec[nc]; -- -- cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op); -- if (t->op == REQUEST_SENSE) { -- cnt += sprintf(page + cnt, " [sense %x %02x %02x]", -- t->key, t->asc, t->ascq); -- } else { -- cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir)); -- cnt += sprintf(page + cnt, " [%5d %5d]", -- t->req_size, t->act_size); -- } -- if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0; -- for (i = 0; i < SCMD_ST_HIST_SZ; i++) { -- cnt += sprintf(page + cnt, " %s", -- ub_scsi_cmd_stname[(int)t->st_hst[nh]]); -- if (++nh == SCMD_ST_HIST_SZ) nh = 0; -- } -- cnt += sprintf(page + cnt, "\n"); -- -- if (++nc == SCMD_TRACE_SZ) nc = 0; -- } -- -- spin_unlock_irqrestore(sc->lock, flags); -- return cnt; --} -- --static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */ -- --/* - * The id allocator. - * - * This also stores the host for indexing by minor, which is somewhat dirty. -@@ -1090,7 +924,6 @@ static int ub_scsi_cmd_start(struct ub_d - add_timer(&sc->work_timer); - - cmd->state = UB_CMDST_CMD; -- ub_cmdtr_state(sc, cmd); - return 0; - } - -@@ -1143,12 +976,10 @@ static void ub_scsi_dispatch(struct ub_d - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - } else if (cmd->state == UB_CMDST_INIT) { -- ub_cmdtr_new(sc, cmd); - if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) - break; - cmd->error = rc; - cmd->state = UB_CMDST_DONE; -- ub_cmdtr_state(sc, cmd); - } else { - if (!ub_is_completed(&sc->work_done)) - break; -@@ -1245,7 +1076,6 @@ static void ub_scsi_urb_compl(struct ub_ - return; - } - cmd->state = UB_CMDST_CLEAR; -- ub_cmdtr_state(sc, cmd); - return; - case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timeout on uhci */ -@@ -1277,7 +1107,6 @@ static void ub_scsi_urb_compl(struct ub_ - return; - } - cmd->state = UB_CMDST_CLR2STS; -- ub_cmdtr_state(sc, cmd); - return; - } - if (urb->status == -EOVERFLOW) { -@@ -1302,7 +1131,6 @@ static void ub_scsi_urb_compl(struct ub_ - if (urb->status != 0 || - len != cmd->sgv[cmd->current_sg].length) { - cmd->act_len += len; -- ub_cmdtr_act_len(sc, cmd); - - cmd->error = -EIO; - ub_state_stat(sc, cmd); -@@ -1329,7 +1157,6 @@ static void ub_scsi_urb_compl(struct ub_ - } - - cmd->act_len += urb->actual_length; -- ub_cmdtr_act_len(sc, cmd); - - if (++cmd->current_sg < cmd->nsg) { - ub_data_start(sc, cmd); -@@ -1355,7 +1182,6 @@ static void ub_scsi_urb_compl(struct ub_ - cmd->error = -EIO; /* A cheap trick... */ - - cmd->state = UB_CMDST_CLRRS; -- ub_cmdtr_state(sc, cmd); - return; - } - -@@ -1439,7 +1265,6 @@ static void ub_scsi_urb_compl(struct ub_ - return; - } - cmd->state = UB_CMDST_DONE; -- ub_cmdtr_state(sc, cmd); - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - -@@ -1494,7 +1319,6 @@ static void ub_data_start(struct ub_dev - add_timer(&sc->work_timer); - - cmd->state = UB_CMDST_DATA; -- ub_cmdtr_state(sc, cmd); - } - - /* -@@ -1506,7 +1330,6 @@ static void ub_state_done(struct ub_dev - - cmd->error = rc; - cmd->state = UB_CMDST_DONE; -- ub_cmdtr_state(sc, cmd); - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - } -@@ -1552,7 +1375,6 @@ static void ub_state_stat(struct ub_dev - - cmd->stat_count = 0; - cmd->state = UB_CMDST_STAT; -- ub_cmdtr_state(sc, cmd); - } - - /* -@@ -1571,7 +1393,6 @@ static void ub_state_stat_counted(struct - return; - - cmd->state = UB_CMDST_STAT; -- ub_cmdtr_state(sc, cmd); - } - - /* -@@ -1609,7 +1430,6 @@ static void ub_state_sense(struct ub_dev - scmd->tag = sc->tagcnt++; - - cmd->state = UB_CMDST_SENSE; -- ub_cmdtr_state(sc, cmd); - - ub_cmdq_insert(sc, scmd); - return; -@@ -1666,11 +1486,6 @@ static void ub_top_sense_done(struct ub_ - struct ub_scsi_cmd *cmd; - - /* -- * Ignoring scmd->act_len, because the buffer was pre-zeroed. -- */ -- ub_cmdtr_sense(sc, scmd, sense); -- -- /* - * Find the command which triggered the unit attention or a check, - * save the sense into it, and advance its state machine. - */ -@@ -1691,6 +1506,9 @@ static void ub_top_sense_done(struct ub_ - return; - } - -+ /* -+ * Ignoring scmd->act_len, because the buffer was pre-zeroed. -+ */ - cmd->key = sense[2] & 0x0F; - cmd->asc = sense[12]; - cmd->ascq = sense[13]; -@@ -2413,9 +2231,6 @@ static int ub_probe(struct usb_interface - if (ub_get_pipes(sc, sc->dev, intf) != 0) - goto err_dev_desc; - -- if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) -- goto err_diag; -- - /* - * At this point, all USB initialization is done, do upper layer. - * We really hate halfway initialized structures, so from the -@@ -2480,8 +2295,6 @@ static int ub_probe(struct usb_interface - } - return 0; - -- /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */ --err_diag: - err_dev_desc: - usb_set_intfdata(intf, NULL); - // usb_put_intf(sc->intf); -@@ -2609,7 +2422,6 @@ static void ub_disconnect(struct usb_int - while ((cmd = ub_cmdq_peek(sc)) != NULL) { - cmd->error = -ENOTCONN; - cmd->state = UB_CMDST_DONE; -- ub_cmdtr_state(sc, cmd); - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - cnt++; -@@ -2660,7 +2472,6 @@ static void ub_disconnect(struct usb_int - * and no URBs left in transit. - */ - -- device_remove_file(&sc->intf->dev, &dev_attr_diag); - usb_set_intfdata(intf, NULL); - // usb_put_intf(sc->intf); - sc->intf = NULL; diff --git a/usb/usb-ub-03-drop-stall-clearing.patch b/usb/usb-ub-03-drop-stall-clearing.patch deleted file mode 100644 index 8f98647bb621b..0000000000000 --- a/usb/usb-ub-03-drop-stall-clearing.patch +++ /dev/null @@ -1,45 +0,0 @@ -From zaitcev@redhat.com Thu Mar 2 16:53:17 2006 -Date: Thu, 2 Mar 2006 16:53:00 -0800 -From: Pete Zaitcev <zaitcev@redhat.com> -To: greg@kroah.com -Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net -Subject: USB: ub 03 drop stall clearing -Message-Id: <20060302165300.211eb11c.zaitcev@redhat.com> - -Matt mentioned that a very old ZIP-100 actually does need this, but I am -yet to see anyone who actually has one still working and uses ub with it. -He/she must be a retrocomputing geek, who can easily bias it to usb-storage -with libusual, if needed. Meanwhile, common folks have trouble with poorly -designed USB keys and some el-cheapo European music players. I think we -better drop this for now. - -Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/block/ub.c | 13 +------------ - 1 file changed, 1 insertion(+), 12 deletions(-) - ---- gregkh-2.6.orig/drivers/block/ub.c -+++ gregkh-2.6/drivers/block/ub.c -@@ -2270,19 +2270,8 @@ static int ub_probe(struct usb_interface - - nluns = 1; - for (i = 0; i < 3; i++) { -- if ((rc = ub_sync_getmaxlun(sc)) < 0) { -- /* -- * This segment is taken from usb-storage. They say -- * that ZIP-100 needs this, but my own ZIP-100 works -- * fine without this. -- * Still, it does not seem to hurt anything. -- */ -- if (rc == -EPIPE) { -- ub_probe_clear_stall(sc, sc->recv_bulk_pipe); -- ub_probe_clear_stall(sc, sc->send_bulk_pipe); -- } -+ if ((rc = ub_sync_getmaxlun(sc)) < 0) - break; -- } - if (rc != 0) { - nluns = rc; - break; diff --git a/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch b/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch deleted file mode 100644 index 5058539a7913f..0000000000000 --- a/usb/usb-uhci-increase-port-reset-completion-delay-for-hp-controllers.patch +++ /dev/null @@ -1,59 +0,0 @@ -From stern@rowland.harvard.edu Wed Mar 1 15:58:26 2006 -Date: Tue, 28 Feb 2006 10:16:12 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -cc: "Frantz, Chris" <Chris.Frantz@hp.com>, Brian Baker <brian.b@hp.com>, Pete Zaitcev <zaitcev@redhat.com> -Subject: USB: UHCI: Increase port-reset completion delay for HP controllers -Message-ID: <Pine.LNX.4.44L0.0602281011040.4987-100000@iolanthe.rowland.org> - -This patch (as657) increases the port-reset completion delay in uhci-hcd -for HP's embedded controllers. Unlike other UHCI controllers, the HP -chips can take as long as 250 us to carry out the processing associated -with finishing a port reset. - -This fixes Novell bug #148761. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/host/uhci-hub.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - ---- gregkh-2.6.orig/drivers/usb/host/uhci-hub.c -+++ gregkh-2.6/drivers/usb/host/uhci-hub.c -@@ -99,6 +99,21 @@ static void uhci_finish_suspend(struct u - } - } - -+/* Wait for the UHCI controller in HP's iLO2 server management chip. -+ * It can take up to 250 us to finish a reset and set the CSC bit. -+ */ -+static void wait_for_HP(unsigned long port_addr) -+{ -+ int i; -+ -+ for (i = 10; i < 250; i += 10) { -+ if (inw(port_addr) & USBPORTSC_CSC) -+ return; -+ udelay(10); -+ } -+ /* Log a warning? */ -+} -+ - static void uhci_check_ports(struct uhci_hcd *uhci) - { - unsigned int port; -@@ -113,6 +128,12 @@ static void uhci_check_ports(struct uhci - CLR_RH_PORTSTAT(USBPORTSC_PR); - udelay(10); - -+ /* HP's server management chip requires -+ * a longer delay. */ -+ if (to_pci_dev(uhci_dev(uhci))->vendor == -+ PCI_VENDOR_ID_HP) -+ wait_for_HP(port_addr); -+ - /* If the port was enabled before, turning - * reset on caused a port enable change. - * Turning reset off causes a port connect diff --git a/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch b/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch deleted file mode 100644 index 8728992353852..0000000000000 --- a/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch +++ /dev/null @@ -1,66 +0,0 @@ -From stern@rowland.harvard.edu Wed Mar 8 12:14:14 2006 -Date: Wed, 8 Mar 2006 15:14:09 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: David Brownell <david-b@pacbell.net> -cc: Greg KH <greg@kroah.com>, Andrew Morton <akpm@osdl.org>, Linus Torvalds <torvalds@osdl.org>, <mingo@elte.hu> -Subject: USB: usbcore: Don't assume a USB configuration includes any interfaces -Message-ID: <Pine.LNX.4.44L0.0603081509100.5360-100000@iolanthe.rowland.org> - -In a couple of places, usbcore assumes that a USB device configuration -will have a nonzero number of interfaces. Having no interfaces may or -may not be allowed by the USB spec; in any event we shouldn't die if we -encounter such a thing. This patch (as662) removes the assumptions. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/hub.c | 16 ++++++++++------ - 1 file changed, 10 insertions(+), 6 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/hub.c -+++ gregkh-2.6/drivers/usb/core/hub.c -@@ -1179,8 +1179,11 @@ static int choose_configuration(struct u - c = udev->config; - num_configs = udev->descriptor.bNumConfigurations; - for (i = 0; i < num_configs; (i++, c++)) { -- struct usb_interface_descriptor *desc = -- &c->intf_cache[0]->altsetting->desc; -+ struct usb_interface_descriptor *desc = NULL; -+ -+ /* It's possible that a config has no interfaces! */ -+ if (c->desc.bNumInterfaces > 0) -+ desc = &c->intf_cache[0]->altsetting->desc; - - /* - * HP's USB bus-powered keyboard has only one configuration -@@ -1215,7 +1218,8 @@ static int choose_configuration(struct u - /* If the first config's first interface is COMM/2/0xff - * (MSFT RNDIS), rule it out unless Linux has host-side - * RNDIS support. */ -- if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM -+ if (i == 0 && desc -+ && desc->bInterfaceClass == USB_CLASS_COMM - && desc->bInterfaceSubClass == 2 - && desc->bInterfaceProtocol == 0xff) { - #ifndef CONFIG_USB_NET_RNDIS -@@ -1231,8 +1235,8 @@ static int choose_configuration(struct u - * than a vendor-specific driver. */ - else if (udev->descriptor.bDeviceClass != - USB_CLASS_VENDOR_SPEC && -- desc->bInterfaceClass != -- USB_CLASS_VENDOR_SPEC) { -+ (!desc || desc->bInterfaceClass != -+ USB_CLASS_VENDOR_SPEC)) { - best = c; - break; - } -@@ -3024,7 +3028,7 @@ int usb_reset_device(struct usb_device * - parent_hub = hdev_to_hub(parent_hdev); - - /* If we're resetting an active hub, take some special actions */ -- if (udev->actconfig && -+ if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && - udev->actconfig->interface[0]->dev.driver == - &hub_driver.driver && - (hub = hdev_to_hub(udev)) != NULL) { diff --git a/usb/usb-usbcore-sets-up-root-hubs-earlier.patch b/usb/usb-usbcore-sets-up-root-hubs-earlier.patch deleted file mode 100644 index 487b93a213bec..0000000000000 --- a/usb/usb-usbcore-sets-up-root-hubs-earlier.patch +++ /dev/null @@ -1,198 +0,0 @@ -From david-b@pacbell.net Mon Jan 23 16:29:38 2006 -From: David Brownell <david-b@pacbell.net> -To: Greg KH <greg@kroah.com> -Subject: USB: usbcore sets up root hubs earlier -Date: Mon, 23 Jan 2006 15:25:40 -0800 -Message-Id: <200601231525.41094.david-b@pacbell.net> - -Make the HCD initialization sequence more sane ... notably, setting up -root hubs before HCDs are asked to do their one-time init. Among other -things, that lets the HCDs do custom root hub init along with all the -other one-time initialization done in the (now misnamed) reset() method. - -This also copies the controller wakeup flags into the root hub; it's -done a bit later than would be ideal, but that'll be necessary until -the PCI code initializes them correctly. (The PCI patch breaks on PPC -due to how it sequences PCI initialization.) - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/hcd.c | 104 +++++++++++++++++++++++++------------------------ - 1 file changed, 55 insertions(+), 49 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/hcd.c -+++ gregkh-2.6/drivers/usb/core/hcd.c -@@ -823,18 +823,17 @@ static void usb_deregister_bus (struct u - - /** - * register_root_hub - called by usb_add_hcd() to register a root hub -- * @usb_dev: the usb root hub device to be registered. - * @hcd: host controller for this root hub - * - * This function registers the root hub with the USB subsystem. It sets up -- * the device properly in the device tree and stores the root_hub pointer -- * in the bus structure, then calls usb_new_device() to register the usb -- * device. It also assigns the root hub's USB address (always 1). -+ * the device properly in the device tree and then calls usb_new_device() -+ * to register the usb device. It also assigns the root hub's USB address -+ * (always 1). - */ --static int register_root_hub (struct usb_device *usb_dev, -- struct usb_hcd *hcd) -+static int register_root_hub(struct usb_hcd *hcd) - { - struct device *parent_dev = hcd->self.controller; -+ struct usb_device *usb_dev = hcd->self.root_hub; - const int devnum = 1; - int retval; - -@@ -846,12 +845,10 @@ static int register_root_hub (struct usb - usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - - mutex_lock(&usb_bus_list_lock); -- usb_dev->bus->root_hub = usb_dev; - - usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); - retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); - if (retval != sizeof usb_dev->descriptor) { -- usb_dev->bus->root_hub = NULL; - mutex_unlock(&usb_bus_list_lock); - dev_dbg (parent_dev, "can't read %s device descriptor %d\n", - usb_dev->dev.bus_id, retval); -@@ -860,7 +857,6 @@ static int register_root_hub (struct usb - - retval = usb_new_device (usb_dev); - if (retval) { -- usb_dev->bus->root_hub = NULL; - dev_err (parent_dev, "can't register root hub for %s, %d\n", - usb_dev->dev.bus_id, retval); - } -@@ -1772,12 +1768,10 @@ int usb_add_hcd(struct usb_hcd *hcd, - - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - -- /* till now HC has been in an indeterminate state ... */ -- if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { -- dev_err(hcd->self.controller, "can't reset\n"); -- return retval; -- } -- -+ /* HC is in reset state, but accessible. Now do the one-time init, -+ * bottom up so that hcds can customize the root hubs before khubd -+ * starts talking to them. (Note, bus id is assigned early too.) -+ */ - if ((retval = hcd_buffer_create(hcd)) != 0) { - dev_dbg(hcd->self.controller, "pool alloc failed\n"); - return retval; -@@ -1786,6 +1780,42 @@ int usb_add_hcd(struct usb_hcd *hcd, - if ((retval = usb_register_bus(&hcd->self)) < 0) - goto err_register_bus; - -+ if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { -+ dev_err(hcd->self.controller, "unable to allocate root hub\n"); -+ retval = -ENOMEM; -+ goto err_allocate_root_hub; -+ } -+ rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : -+ USB_SPEED_FULL; -+ hcd->self.root_hub = rhdev; -+ -+ /* "reset" is misnamed; its role is now one-time init. the controller -+ * should already have been reset (and boot firmware kicked off etc). -+ */ -+ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { -+ dev_err(hcd->self.controller, "can't setup\n"); -+ goto err_hcd_driver_setup; -+ } -+ -+ /* wakeup flag init is in transition; for now we can't rely on PCI to -+ * initialize these bits properly, so we let reset() override it. -+ * This init should _precede_ the reset() once PCI behaves. -+ */ -+ device_init_wakeup(&rhdev->dev, -+ device_can_wakeup(hcd->self.controller)); -+ -+ // ... all these hcd->*_wakeup flags will vanish -+ hcd->can_wakeup = device_can_wakeup(hcd->self.controller); -+ -+ /* hcd->driver->reset() reported can_wakeup, probably with -+ * assistance from board's boot firmware. -+ * NOTE: normal devices won't enable wakeup by default. -+ */ -+ if (hcd->can_wakeup) -+ dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); -+ hcd->remote_wakeup = hcd->can_wakeup; -+ -+ /* enable irqs just before we start the controller */ - if (hcd->driver->irq) { - char buf[8], *bufp = buf; - -@@ -1817,56 +1847,32 @@ int usb_add_hcd(struct usb_hcd *hcd, - (unsigned long long)hcd->rsrc_start); - } - -- /* Allocate the root hub before calling hcd->driver->start(), -- * but don't register it until afterward so that the hardware -- * is running. -- */ -- if ((rhdev = usb_alloc_dev(NULL, &hcd->self, 0)) == NULL) { -- dev_err(hcd->self.controller, "unable to allocate root hub\n"); -- retval = -ENOMEM; -- goto err_allocate_root_hub; -- } -- -- /* Although in principle hcd->driver->start() might need to use rhdev, -- * none of the current drivers do. -- */ - if ((retval = hcd->driver->start(hcd)) < 0) { - dev_err(hcd->self.controller, "startup error %d\n", retval); - goto err_hcd_driver_start; - } - -- /* hcd->driver->start() reported can_wakeup, probably with -- * assistance from board's boot firmware. -- * NOTE: normal devices won't enable wakeup by default. -- */ -- if (hcd->can_wakeup) -- dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); -- hcd->remote_wakeup = hcd->can_wakeup; -- -- rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH : -- USB_SPEED_FULL; -+ /* starting here, usbcore will pay attention to this root hub */ - rhdev->bus_mA = min(500u, hcd->power_budget); -- if ((retval = register_root_hub(rhdev, hcd)) != 0) -+ if ((retval = register_root_hub(hcd)) != 0) - goto err_register_root_hub; - - if (hcd->uses_new_polling && hcd->poll_rh) - usb_hcd_poll_rh_status(hcd); - return retval; - -- err_register_root_hub: -+err_register_root_hub: - hcd->driver->stop(hcd); -- -- err_hcd_driver_start: -- usb_put_dev(rhdev); -- -- err_allocate_root_hub: -+err_hcd_driver_start: - if (hcd->irq >= 0) - free_irq(irqnum, hcd); -- -- err_request_irq: -+err_request_irq: -+err_hcd_driver_setup: -+ hcd->self.root_hub = NULL; -+ usb_put_dev(rhdev); -+err_allocate_root_hub: - usb_deregister_bus(&hcd->self); -- -- err_register_bus: -+err_register_bus: - hcd_buffer_destroy(hcd); - return retval; - } diff --git a/usb/usb-usbcore-usb_set_configuration-oops.patch b/usb/usb-usbcore-usb_set_configuration-oops.patch deleted file mode 100644 index 057dfe1016baa..0000000000000 --- a/usb/usb-usbcore-usb_set_configuration-oops.patch +++ /dev/null @@ -1,43 +0,0 @@ -From horst@schirmeier.com Thu Mar 9 05:10:56 2006 -Date: Thu, 9 Mar 2006 14:10:49 +0100 -From: Horst Schirmeier <horst@schirmeier.com> -To: Alan Stern <stern@rowland.harvard.edu> -Cc: Greg KH <greg@kroah.com> -Subject: USB: usbcore: usb_set_configuration oops (NULL ptr dereference) -Message-ID: <20060309131048.GL22994@quickstop.soohrt.org> -Content-Disposition: inline - -When trying to deconfigure a device via usb_set_configuration(dev, 0), -2.6.16-rc kernels after 55c527187c9d78f840b284d596a0b298bc1493af oops -with "Unable to handle NULL pointer dereference at...". This is due to -an unchecked dereference of cp in the power budget part. - -Signed-off-by: Horst Schirmeier <horst@schirmeier.com> -Acked-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/core/message.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/core/message.c -+++ gregkh-2.6/drivers/usb/core/message.c -@@ -1388,11 +1388,13 @@ free_interfaces: - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device (dev, 1); // Skip ep0 - -- i = dev->bus_mA - cp->desc.bMaxPower * 2; -- if (i < 0) -- dev_warn(&dev->dev, "new config #%d exceeds power " -- "limit by %dmA\n", -- configuration, -i); -+ if (cp) { -+ i = dev->bus_mA - cp->desc.bMaxPower * 2; -+ if (i < 0) -+ dev_warn(&dev->dev, "new config #%d exceeds power " -+ "limit by %dmA\n", -+ configuration, -i); -+ } - - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, diff --git a/usb/usb-vicam.c-fix-a-null-pointer-dereference.patch b/usb/usb-vicam.c-fix-a-null-pointer-dereference.patch deleted file mode 100644 index de4e31540d7cf..0000000000000 --- a/usb/usb-vicam.c-fix-a-null-pointer-dereference.patch +++ /dev/null @@ -1,29 +0,0 @@ -From bunk@stusta.de Fri Mar 10 14:25:09 2006 -Date: Fri, 10 Mar 2006 23:25:06 +0100 -From: Adrian Bunk <bunk@stusta.de> -To: gregkh@suse.de -Subject: USB: vicam.c: fix a NULL pointer dereference -Message-ID: <20060310222506.GA21864@stusta.de> -Content-Disposition: inline - -This patch fixes a NULL pointer dereference spotted by the Coverity -checker. - - -Signed-off-by: Adrian Bunk <bunk@stusta.de> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/media/vicam.c | 1 + - 1 file changed, 1 insertion(+) - ---- gregkh-2.6.orig/drivers/usb/media/vicam.c -+++ gregkh-2.6/drivers/usb/media/vicam.c -@@ -764,6 +764,7 @@ vicam_open(struct inode *inode, struct f - if (!cam) { - printk(KERN_ERR - "vicam video_device improperly initialized"); -+ return -EINVAL; - } - - /* the videodev_lock held above us protects us from diff --git a/usb/usb-zc0301-driver-bugfix.patch b/usb/usb-zc0301-driver-bugfix.patch deleted file mode 100644 index 4879273b81f06..0000000000000 --- a/usb/usb-zc0301-driver-bugfix.patch +++ /dev/null @@ -1,111 +0,0 @@ -From luca.risolia@studio.unibo.it Fri Mar 3 00:56:06 2006 -Date: Fri, 3 Mar 2006 09:58:39 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: ZC0301 driver bugfix -Message-ID: <20060303095839.GA3857@studio.unibo.it> -Content-Disposition: inline - -ZC0301 driver bugfix. - -Use correct PID/VID USB entries. - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/zc0301.txt | 12 ++++++------ - drivers/usb/media/zc0301.h | 5 +---- - drivers/usb/media/zc0301_core.c | 6 +++--- - drivers/usb/media/zc0301_sensor.h | 12 ++++++------ - 4 files changed, 16 insertions(+), 19 deletions(-) - ---- gregkh-2.6.orig/Documentation/usb/zc0301.txt -+++ gregkh-2.6/Documentation/usb/zc0301.txt -@@ -201,14 +201,14 @@ devices mounting the ZC0301 Image Proces - - Vendor ID Product ID - --------- ---------- --0x10fd 0x8050 --0x041e 0x0417 --0x041e 0x041e --0x041e 0x081c --0x041e 0x0834 --0x041e 0x0835 -+0x041e 0x4017 -+0x041e 0x401c -+0x041e 0x401e -+0x041e 0x4034 -+0x041e 0x4035 - 0x046d 0x08ae - 0x0ac8 0x0301 -+0x10fd 0x8050 - - The list above does not imply that all those devices work with this driver: up - until now only the ones that mount the following image sensors are supported; ---- gregkh-2.6.orig/drivers/usb/media/zc0301.h -+++ gregkh-2.6/drivers/usb/media/zc0301.h -@@ -134,10 +134,7 @@ struct zc0301_device { - struct zc0301_device* - zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) - { -- if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) -- return cam; -- -- return NULL; -+ return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; - } - - void ---- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c -+++ gregkh-2.6/drivers/usb/media/zc0301_core.c -@@ -52,8 +52,8 @@ - #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" - #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" - #define ZC0301_MODULE_LICENSE "GPL" --#define ZC0301_MODULE_VERSION "1:1.02" --#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) -+#define ZC0301_MODULE_VERSION "1:1.03" -+#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 3) - - /*****************************************************************************/ - -@@ -637,7 +637,6 @@ static void zc0301_release_resources(str - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); -- usb_put_dev(cam->usbdev); - kfree(cam->control_buffer); - } - -@@ -727,6 +726,7 @@ static int zc0301_release(struct inode* - - if (cam->state & DEV_DISCONNECTED) { - zc0301_release_resources(cam); -+ usb_put_dev(cam->usbdev); - mutex_unlock(&cam->dev_mutex); - kfree(cam); - return 0; ---- gregkh-2.6.orig/drivers/usb/media/zc0301_sensor.h -+++ gregkh-2.6/drivers/usb/media/zc0301_sensor.h -@@ -58,14 +58,14 @@ zc0301_attach_sensor(struct zc0301_devic - - #define ZC0301_ID_TABLE \ - static const struct usb_device_id zc0301_id_table[] = { \ -- { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ -- { ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \ -- { ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \ -- { ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \ -- { ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \ -- { ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, \ -+ { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ - { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ -+ { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ - { } \ - }; - diff --git a/usb/usb-zc0301-driver-updates-2.patch b/usb/usb-zc0301-driver-updates-2.patch deleted file mode 100644 index f64108145e65a..0000000000000 --- a/usb/usb-zc0301-driver-updates-2.patch +++ /dev/null @@ -1,496 +0,0 @@ -From luca.risolia@studio.unibo.it Fri Feb 24 21:56:12 2006 -Date: Sat, 25 Feb 2006 06:57:49 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Subject: USB: ZC0301 driver updates -Message-ID: <20060225065749.GC31623@studio.unibo.it> -Content-Disposition: inline - -ZC0301 driver updates. - -Changes: + new, - removed, * cleanup, @ bugfix - -@ Need usb_get|put_dev() when disconnecting, if the device is open -* Cleanups and updates in the documentation -+ Use per-device sensor structures -+ Add frame_timeout module parameter - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/zc0301.txt | 29 +++++++++++------ - drivers/usb/media/zc0301.h | 20 +++++++++--- - drivers/usb/media/zc0301_core.c | 58 +++++++++++++++++++++-------------- - drivers/usb/media/zc0301_pas202bcb.c | 38 +++++++++++++--------- - drivers/usb/media/zc0301_sensor.h | 25 +++++++++------ - 5 files changed, 108 insertions(+), 62 deletions(-) - ---- gregkh-2.6.orig/Documentation/usb/zc0301.txt -+++ gregkh-2.6/Documentation/usb/zc0301.txt -@@ -68,11 +68,6 @@ Some of the features of the driver are: - data transfers; - - automatic detection of image sensor; - - video format is standard JPEG; --- full support for the capabilities of every possible image sensors that can -- be connected to the ZC0301 bridges, including, for istance, red, green, -- blue and global gain adjustments and exposure control (see "Supported -- devices" paragraph for details); --- use of default color settings for sunlight conditions; - - dynamic driver control thanks to various module parameters (see "Module - parameters" paragraph); - - up to 64 cameras can be handled at the same time; they can be connected and -@@ -171,6 +166,14 @@ Description: Force the application to - 1 = force memory unmapping (save memory) - Default: 0 - ------------------------------------------------------------------------------- -+Name: frame_timeout -+Type: uint array (min = 0, max = 64) -+Syntax: <n[,...]> -+Description: Timeout for a video frame in seconds. This parameter is -+ specific for each detected camera. This parameter can be -+ changed at runtime thanks to the /sys filesystem interface. -+Default: 2 -+------------------------------------------------------------------------------- - Name: debug - Type: ushort - Syntax: <n> -@@ -198,17 +201,23 @@ devices mounting the ZC0301 Image Proces - - Vendor ID Product ID - --------- ---------- -+0x10fd 0x8050 -+0x041e 0x0417 -+0x041e 0x041e -+0x041e 0x081c -+0x041e 0x0834 -+0x041e 0x0835 - 0x046d 0x08ae -+0x0ac8 0x0301 - --The following image sensors are supported: -+The list above does not imply that all those devices work with this driver: up -+until now only the ones that mount the following image sensors are supported; -+kernel messages will always tell you whether this is the case: - - Model Manufacturer - ----- ------------ - PAS202BCB PixArt Imaging, Inc. - --All the available control settings of each image sensor are supported through --the V4L2 interface. -- - - 9. Notes for V4L2 application developers - ======================================== -@@ -240,6 +249,6 @@ the fingerprint is: '88E8 F32F 7244 68BA - - Informations about the chip internals needed to enable the I2C protocol have - been taken from the documentation of the ZC030x Video4Linux1 driver written - by Andrew Birkett <andy@nobugs.org>; --- Initialization values of the ZC0301 controller connected to the PAS202BCB -+- The initialization values of the ZC0301 controller connected to the PAS202BCB - image sensor have been taken from the SPCA5XX driver maintained by - Michel Xhaard <mxhaard@magic.fr>. ---- gregkh-2.6.orig/drivers/usb/media/zc0301.h -+++ gregkh-2.6/drivers/usb/media/zc0301.h -@@ -34,7 +34,8 @@ - #include <linux/param.h> - #include <linux/mutex.h> - #include <linux/rwsem.h> --#include <asm/semaphore.h> -+#include <linux/stddef.h> -+#include <linux/string.h> - - #include "zc0301_sensor.h" - -@@ -51,7 +52,7 @@ - #define ZC0301_ALTERNATE_SETTING 7 - #define ZC0301_URB_TIMEOUT msecs_to_jiffies(2 * ZC0301_ISO_PACKETS) - #define ZC0301_CTRL_TIMEOUT 100 --#define ZC0301_FRAME_TIMEOUT 2 * 1000 * msecs_to_jiffies(1) -+#define ZC0301_FRAME_TIMEOUT 2 - - /*****************************************************************************/ - -@@ -94,6 +95,7 @@ enum zc0301_stream_state { - - struct zc0301_module_param { - u8 force_munmap; -+ u16 frame_timeout; - }; - - static DECLARE_RWSEM(zc0301_disconnect); -@@ -101,7 +103,7 @@ static DECLARE_RWSEM(zc0301_disconnect); - struct zc0301_device { - struct video_device* v4ldev; - -- struct zc0301_sensor* sensor; -+ struct zc0301_sensor sensor; - - struct usb_device* usbdev; - struct urb* urb[ZC0301_URBS]; -@@ -129,11 +131,19 @@ struct zc0301_device { - - /*****************************************************************************/ - -+struct zc0301_device* -+zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id) -+{ -+ if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) -+ return cam; -+ -+ return NULL; -+} -+ - void - zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor) - { -- cam->sensor = sensor; -- cam->sensor->usbdev = cam->usbdev; -+ memcpy(&cam->sensor, sensor, sizeof(struct zc0301_sensor)); - } - - /*****************************************************************************/ ---- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c -+++ gregkh-2.6/drivers/usb/media/zc0301_core.c -@@ -29,11 +29,9 @@ - #include <linux/moduleparam.h> - #include <linux/errno.h> - #include <linux/slab.h> --#include <linux/string.h> - #include <linux/device.h> - #include <linux/fs.h> - #include <linux/delay.h> --#include <linux/stddef.h> - #include <linux/compiler.h> - #include <linux/ioctl.h> - #include <linux/poll.h> -@@ -54,8 +52,8 @@ - #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" - #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" - #define ZC0301_MODULE_LICENSE "GPL" --#define ZC0301_MODULE_VERSION "1:1.01" --#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) -+#define ZC0301_MODULE_VERSION "1:1.02" -+#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) - - /*****************************************************************************/ - -@@ -94,6 +92,15 @@ MODULE_PARM_DESC(force_munmap, - "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." - "\n"); - -+static unsigned int frame_timeout[] = {[0 ... ZC0301_MAX_DEVICES-1] = -+ ZC0301_FRAME_TIMEOUT}; -+module_param_array(frame_timeout, uint, NULL, 0644); -+MODULE_PARM_DESC(frame_timeout, -+ "\n<n[,...]> Timeout for a video frame in seconds." -+ "\nThis parameter is specific for each detected camera." -+ "\nDefault value is "__MODULE_STRING(ZC0301_FRAME_TIMEOUT)"." -+ "\n"); -+ - #ifdef ZC0301_DEBUG - static unsigned short debug = ZC0301_DEBUG_LEVEL; - module_param(debug, ushort, 0644); -@@ -115,8 +122,8 @@ static u32 - zc0301_request_buffers(struct zc0301_device* cam, u32 count, - enum zc0301_io_method io) - { -- struct v4l2_pix_format* p = &(cam->sensor->pix_format); -- struct v4l2_rect* r = &(cam->sensor->cropcap.bounds); -+ struct v4l2_pix_format* p = &(cam->sensor.pix_format); -+ struct v4l2_rect* r = &(cam->sensor.cropcap.bounds); - const size_t imagesize = cam->module_param.force_munmap || - io == IO_READ ? - (p->width * p->height * p->priv) / 8 : -@@ -332,9 +339,9 @@ static void zc0301_urb_complete(struct u - (*f) = list_entry(cam->inqueue.next, struct zc0301_frame_t, - frame); - -- imagesize = (cam->sensor->pix_format.width * -- cam->sensor->pix_format.height * -- cam->sensor->pix_format.priv) / 8; -+ imagesize = (cam->sensor.pix_format.width * -+ cam->sensor.pix_format.height * -+ cam->sensor.pix_format.priv) / 8; - - for (i = 0; i < urb->number_of_packets; i++) { - unsigned int len, status; -@@ -555,7 +562,7 @@ zc0301_set_compression(struct zc0301_dev - - static int zc0301_init(struct zc0301_device* cam) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - struct v4l2_queryctrl *qctrl; - struct v4l2_rect* rect; -@@ -630,6 +637,7 @@ static void zc0301_release_resources(str - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); - video_set_drvdata(cam->v4ldev, NULL); - video_unregister_device(cam->v4ldev); -+ usb_put_dev(cam->usbdev); - kfree(cam->control_buffer); - } - -@@ -798,7 +806,8 @@ zc0301_read(struct file* filp, char __us - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), -- ZC0301_FRAME_TIMEOUT ); -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) { - mutex_unlock(&cam->fileop_mutex); - return timeout; -@@ -1056,7 +1065,7 @@ zc0301_vidioc_s_input(struct zc0301_devi - static int - zc0301_vidioc_query_ctrl(struct zc0301_device* cam, void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_queryctrl qc; - u8 i; - -@@ -1078,7 +1087,7 @@ zc0301_vidioc_query_ctrl(struct zc0301_d - static int - zc0301_vidioc_g_ctrl(struct zc0301_device* cam, void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - int err = 0; - u8 i; -@@ -1110,7 +1119,7 @@ exit: - static int - zc0301_vidioc_s_ctrl(struct zc0301_device* cam, void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_control ctrl; - u8 i; - int err = 0; -@@ -1123,6 +1132,8 @@ zc0301_vidioc_s_ctrl(struct zc0301_devic - - for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) - if (ctrl.id == s->qctrl[i].id) { -+ if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED) -+ return -EINVAL; - if (ctrl.value < s->qctrl[i].minimum || - ctrl.value > s->qctrl[i].maximum) - return -ERANGE; -@@ -1142,7 +1153,7 @@ zc0301_vidioc_s_ctrl(struct zc0301_devic - static int - zc0301_vidioc_cropcap(struct zc0301_device* cam, void __user * arg) - { -- struct v4l2_cropcap* cc = &(cam->sensor->cropcap); -+ struct v4l2_cropcap* cc = &(cam->sensor.cropcap); - - cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - cc->pixelaspect.numerator = 1; -@@ -1158,7 +1169,7 @@ zc0301_vidioc_cropcap(struct zc0301_devi - static int - zc0301_vidioc_g_crop(struct zc0301_device* cam, void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - }; -@@ -1175,7 +1186,7 @@ zc0301_vidioc_g_crop(struct zc0301_devic - static int - zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_crop crop; - struct v4l2_rect* rect; - struct v4l2_rect* bounds = &(s->cropcap.bounds); -@@ -1304,7 +1315,7 @@ static int - zc0301_vidioc_g_fmt(struct zc0301_device* cam, void __user * arg) - { - struct v4l2_format format; -- struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format); -+ struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format); - - if (copy_from_user(&format, arg, sizeof(format))) - return -EFAULT; -@@ -1328,7 +1339,7 @@ static int - zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, - void __user * arg) - { -- struct zc0301_sensor* s = cam->sensor; -+ struct zc0301_sensor* s = &cam->sensor; - struct v4l2_format format; - struct v4l2_pix_format* pix; - struct v4l2_pix_format* pfmt = &(s->pix_format); -@@ -1612,7 +1623,8 @@ zc0301_vidioc_dqbuf(struct zc0301_device - (!list_empty(&cam->outqueue)) || - (cam->state & DEV_DISCONNECTED) || - (cam->state & DEV_MISCONFIGURED), -- ZC0301_FRAME_TIMEOUT ); -+ cam->module_param.frame_timeout * -+ 1000 * msecs_to_jiffies(1) ); - if (timeout < 0) - return timeout; - if (cam->state & DEV_DISCONNECTED) -@@ -1911,8 +1923,8 @@ zc0301_usb_probe(struct usb_interface* i - break; - } - -- if (!err && cam->sensor) -- DBG(2, "%s image sensor detected", cam->sensor->name); -+ if (!err) -+ DBG(2, "%s image sensor detected", cam->sensor.name); - else { - DBG(1, "No supported image sensor detected"); - err = -ENODEV; -@@ -1950,6 +1962,7 @@ zc0301_usb_probe(struct usb_interface* i - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); - - cam->module_param.force_munmap = force_munmap[dev_nr]; -+ cam->module_param.frame_timeout = frame_timeout[dev_nr]; - - dev_nr = (dev_nr < ZC0301_MAX_DEVICES-1) ? dev_nr+1 : 0; - -@@ -1994,6 +2007,7 @@ static void zc0301_usb_disconnect(struct - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); - wake_up(&cam->wait_stream); -+ usb_get_dev(cam->usbdev); - } else { - cam->state |= DEV_DISCONNECTED; - zc0301_release_resources(cam); ---- gregkh-2.6.orig/drivers/usb/media/zc0301_pas202bcb.c -+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c -@@ -22,6 +22,14 @@ - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - ***************************************************************************/ - -+/* -+ NOTE: Sensor controls are disabled for now, becouse changing them while -+ streaming sometimes results in out-of-sync video frames. We'll use -+ the default initialization, until we know how to stop and start video -+ in the chip. However, the image quality still looks good under various -+ light conditions. -+*/ -+ - #include <linux/delay.h> - #include "zc0301_sensor.h" - -@@ -245,7 +253,7 @@ static struct zc0301_sensor pas202bcb = - .maximum = 0x3fff, - .step = 0x0001, - .default_value = 0x01e5, -- .flags = 0, -+ .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_GAIN, -@@ -255,7 +263,17 @@ static struct zc0301_sensor pas202bcb = - .maximum = 0x1f, - .step = 0x01, - .default_value = 0x0c, -- .flags = 0, -+ .flags = V4L2_CTRL_FLAG_DISABLED, -+ }, -+ { -+ .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "DAC magnitude", -+ .minimum = 0x00, -+ .maximum = 0xff, -+ .step = 0x01, -+ .default_value = 0x00, -+ .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_RED_BALANCE, -@@ -265,7 +283,7 @@ static struct zc0301_sensor pas202bcb = - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x01, -- .flags = 0, -+ .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_BLUE_BALANCE, -@@ -275,7 +293,7 @@ static struct zc0301_sensor pas202bcb = - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x05, -- .flags = 0, -+ .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = ZC0301_V4L2_CID_GREEN_BALANCE, -@@ -285,17 +303,7 @@ static struct zc0301_sensor pas202bcb = - .maximum = 0x0f, - .step = 0x01, - .default_value = 0x00, -- .flags = 0, -- }, -- { -- .id = ZC0301_V4L2_CID_DAC_MAGNITUDE, -- .type = V4L2_CTRL_TYPE_INTEGER, -- .name = "DAC magnitude", -- .minimum = 0x00, -- .maximum = 0xff, -- .step = 0x01, -- .default_value = 0x04, -- .flags = 0, -+ .flags = V4L2_CTRL_FLAG_DISABLED, - }, - }, - .get_ctrl = &pas202bcb_get_ctrl, ---- gregkh-2.6.orig/drivers/usb/media/zc0301_sensor.h -+++ gregkh-2.6/drivers/usb/media/zc0301_sensor.h -@@ -43,9 +43,11 @@ static int (*zc0301_sensor_table[])(stru - NULL, \ - }; - -+extern struct zc0301_device* -+zc0301_match_id(struct zc0301_device* cam, const struct usb_device_id *id); -+ - extern void --zc0301_attach_sensor(struct zc0301_device* cam, -- struct zc0301_sensor* sensor); -+zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor); - - #define ZC0301_USB_DEVICE(vend, prod, intclass) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ -@@ -56,7 +58,14 @@ zc0301_attach_sensor(struct zc0301_devic - - #define ZC0301_ID_TABLE \ - static const struct usb_device_id zc0301_id_table[] = { \ -+ { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x0417, 0xff), }, \ -+ { ZC0301_USB_DEVICE(0x041e, 0x041e, 0xff), }, /* HV7131B */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x081c, 0xff), }, /* PAS106 */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x0834, 0xff), }, /* PAS106 */ \ -+ { ZC0301_USB_DEVICE(0x041e, 0x0835, 0xff), }, /* PAS106 */ \ - { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */ \ -+ { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), }, \ - { } \ - }; - -@@ -80,15 +89,11 @@ struct zc0301_sensor { - struct v4l2_cropcap cropcap; - struct v4l2_pix_format pix_format; - -- int (*init)(struct zc0301_device* cam); -- int (*get_ctrl)(struct zc0301_device* cam, -- struct v4l2_control* ctrl); -- int (*set_ctrl)(struct zc0301_device* cam, -+ int (*init)(struct zc0301_device*); -+ int (*get_ctrl)(struct zc0301_device*, struct v4l2_control* ctrl); -+ int (*set_ctrl)(struct zc0301_device*, - const struct v4l2_control* ctrl); -- int (*set_crop)(struct zc0301_device* cam, -- const struct v4l2_rect* rect); -- -- const struct usb_device* usbdev; -+ int (*set_crop)(struct zc0301_device*, const struct v4l2_rect* rect); - - /* Private */ - struct v4l2_queryctrl _qctrl[ZC0301_MAX_CTRLS]; diff --git a/usb/usb-zc0301-driver-updates.patch b/usb/usb-zc0301-driver-updates.patch deleted file mode 100644 index 7450846719b59..0000000000000 --- a/usb/usb-zc0301-driver-updates.patch +++ /dev/null @@ -1,214 +0,0 @@ -From luca.risolia@studio.unibo.it Tue Feb 7 15:03:45 2006 -Date: Wed, 8 Feb 2006 00:05:27 +0000 -From: Luca Risolia <luca.risolia@studio.unibo.it> -To: Greg Kroah-Hartman <gregkh@suse.de> -Cc: Andrew Morton <akpm@osdl.org> -Subject: USB: ZC0301 driver updates -Message-ID: <20060208000527.GA10310@studio.unibo.it> -Content-Disposition: inline - -"Cosmetic" driver updates for the ZC0301 driver: - -- Fix stream_interrupt() (and work around a possible kernel bug); - -- Fix vidioc_enum_input() and split vidioc_gs_input() in two parts; -- Use wait_event_interruptible_timeout() instead of wait_event_interruptible() - when waiting for video frames; -- replace erroneous wake_up_interruptible(&wait_stream) with - wake_up(&wait_stream); -- Cosmetic cleanups in the documentation. - -Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - Documentation/usb/zc0301.txt | 19 +++++---------- - drivers/usb/media/zc0301.h | 2 - - drivers/usb/media/zc0301_core.c | 43 ++++++++++++++++++++++------------- - drivers/usb/media/zc0301_pas202bcb.c | 2 - - 4 files changed, 37 insertions(+), 29 deletions(-) - ---- gregkh-2.6.orig/Documentation/usb/zc0301.txt -+++ gregkh-2.6/Documentation/usb/zc0301.txt -@@ -67,8 +67,7 @@ Some of the features of the driver are: - - available mmap or read/poll methods for video streaming through isochronous - data transfers; - - automatic detection of image sensor; --- video formats is standard JPEG in various compression qualities -- (see also "Notes for V4L2 application developers" paragraph); -+- video format is standard JPEG; - - full support for the capabilities of every possible image sensors that can - be connected to the ZC0301 bridges, including, for istance, red, green, - blue and global gain adjustments and exposure control (see "Supported -@@ -226,10 +225,6 @@ The same number of buffers as before wil - of the new video frames, so you have to map the buffers again before any I/O - attempts on them. - --This driver supports the standard JPEG video format. The current compression --quality may vary from 0 to 3 and can be selected or queried thanks to the --VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. -- - - 10. Contact information - ======================= -@@ -242,9 +237,9 @@ the fingerprint is: '88E8 F32F 7244 68BA - - 11. Credits - =========== --- Informations about the chip internals to enable the I2C protocol have been -- taken from the documentation of the ZC030x Video4Linux1 driver written by -- Andrew Birkett <andy@nobugs.org>; --- Initialization values of the ZC0301 connected to the PAS202BCB image sensor -- have been taken from the SPCA5XX driver maintained by -- Michel Xhaard <mxhaard@magic.fr> -+- Informations about the chip internals needed to enable the I2C protocol have -+ been taken from the documentation of the ZC030x Video4Linux1 driver written -+ by Andrew Birkett <andy@nobugs.org>; -+- Initialization values of the ZC0301 controller connected to the PAS202BCB -+ image sensor have been taken from the SPCA5XX driver maintained by -+ Michel Xhaard <mxhaard@magic.fr>. ---- gregkh-2.6.orig/drivers/usb/media/zc0301.h -+++ gregkh-2.6/drivers/usb/media/zc0301.h -@@ -45,7 +45,7 @@ - #define ZC0301_MAX_DEVICES 64 - #define ZC0301_FORCE_MUNMAP 0 - #define ZC0301_MAX_FRAMES 32 --#define ZC0301_COMPRESSION_QUALITY 2 -+#define ZC0301_COMPRESSION_QUALITY 0 - #define ZC0301_URBS 2 - #define ZC0301_ISO_PACKETS 7 - #define ZC0301_ALTERNATE_SETTING 7 ---- gregkh-2.6.orig/drivers/usb/media/zc0301_core.c -+++ gregkh-2.6/drivers/usb/media/zc0301_core.c -@@ -3,9 +3,9 @@ - * * - * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * - * * -- * Informations about the chip internals to enable the I2C protocol have * -- * been taken from the documentation of the ZC030x Video4Linux1 driver * -- * written by Andrew Birkett <andy@nobugs.org> * -+ * Informations about the chip internals needed to enable the I2C protocol * -+ * have been taken from the documentation of the ZC030x Video4Linux1 * -+ * driver written by Andrew Birkett <andy@nobugs.org> * - * * - * 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 * -@@ -54,8 +54,8 @@ - #define ZC0301_MODULE_AUTHOR "(C) 2006 Luca Risolia" - #define ZC0301_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" - #define ZC0301_MODULE_LICENSE "GPL" --#define ZC0301_MODULE_VERSION "1:1.00" --#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 0) -+#define ZC0301_MODULE_VERSION "1:1.01" -+#define ZC0301_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 1) - - /*****************************************************************************/ - -@@ -314,7 +314,7 @@ static void zc0301_urb_complete(struct u - if ((*f)) - (*f)->state = F_QUEUED; - DBG(3, "Stream interrupted"); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); - } - - if (cam->state & DEV_DISCONNECTED) -@@ -526,7 +526,7 @@ static int zc0301_stream_interrupt(struc - ZC0301_URB_TIMEOUT); - if (cam->state & DEV_DISCONNECTED) - return -ENODEV; -- else if (!timeout) { -+ else if (cam->stream != STREAM_OFF) { - cam->state |= DEV_MISCONFIGURED; - DBG(1, "URB timeout reached. The camera is misconfigured. To " - "use it, close and open /dev/video%d again.", -@@ -547,8 +547,7 @@ zc0301_set_compression(struct zc0301_dev - - if ((r = zc0301_read_reg(cam, 0x0008)) < 0) - err += r; -- err += zc0301_write_reg(cam, 0x0008, -- r | 0x11 | (compression->quality >> 1)); -+ err += zc0301_write_reg(cam, 0x0008, r | 0x11 | compression->quality); - - return err ? -EIO : 0; - } -@@ -737,8 +736,7 @@ static int zc0301_release(struct inode* - - - static ssize_t --zc0301_read(struct file* filp, char __user * buf, -- size_t count, loff_t* f_pos) -+zc0301_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos) - { - struct zc0301_device* cam = video_get_drvdata(video_devdata(filp)); - struct zc0301_frame_t* f, * i; -@@ -1019,6 +1017,7 @@ zc0301_vidioc_enuminput(struct zc0301_de - - memset(&i, 0, sizeof(i)); - strcpy(i.name, "Camera"); -+ i.type = V4L2_INPUT_TYPE_CAMERA; - - if (copy_to_user(arg, &i, sizeof(i))) - return -EFAULT; -@@ -1028,7 +1027,19 @@ zc0301_vidioc_enuminput(struct zc0301_de - - - static int --zc0301_vidioc_gs_input(struct zc0301_device* cam, void __user * arg) -+zc0301_vidioc_g_input(struct zc0301_device* cam, void __user * arg) -+{ -+ int index = 0; -+ -+ if (copy_to_user(arg, &index, sizeof(index))) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+ -+static int -+zc0301_vidioc_s_input(struct zc0301_device* cam, void __user * arg) - { - int index; - -@@ -1446,7 +1457,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_d - if (copy_from_user(&jc, arg, sizeof(jc))) - return -EFAULT; - -- if (jc.quality < 0 || jc.quality > 3) -+ if (jc.quality != 0) - return -EINVAL; - - if (cam->stream == STREAM_ON) -@@ -1738,8 +1749,10 @@ static int zc0301_ioctl_v4l2(struct inod - return zc0301_vidioc_enuminput(cam, arg); - - case VIDIOC_G_INPUT: -+ return zc0301_vidioc_g_input(cam, arg); -+ - case VIDIOC_S_INPUT: -- return zc0301_vidioc_gs_input(cam, arg); -+ return zc0301_vidioc_s_input(cam, arg); - - case VIDIOC_QUERYCTRL: - return zc0301_vidioc_query_ctrl(cam, arg); -@@ -1980,7 +1993,7 @@ static void zc0301_usb_disconnect(struct - zc0301_stop_transfer(cam); - cam->state |= DEV_DISCONNECTED; - wake_up_interruptible(&cam->wait_frame); -- wake_up_interruptible(&cam->wait_stream); -+ wake_up(&cam->wait_stream); - } else { - cam->state |= DEV_DISCONNECTED; - zc0301_release_resources(cam); ---- gregkh-2.6.orig/drivers/usb/media/zc0301_pas202bcb.c -+++ gregkh-2.6/drivers/usb/media/zc0301_pas202bcb.c -@@ -318,7 +318,7 @@ static struct zc0301_sensor pas202bcb = - .width = 640, - .height = 480, - .pixelformat = V4L2_PIX_FMT_JPEG, -- .priv = 16, -+ .priv = 8, - }, - }; - diff --git a/usb/usb-zero-driver-removed-duplicated-code.patch b/usb/usb-zero-driver-removed-duplicated-code.patch deleted file mode 100644 index bf06e88e13a4f..0000000000000 --- a/usb/usb-zero-driver-removed-duplicated-code.patch +++ /dev/null @@ -1,30 +0,0 @@ -From linux-usb-devel-admin@lists.sourceforge.net Tue Feb 7 00:07:07 2006 -Message-ID: <cda58cb80602070006k29e9ea67v@mail.gmail.com> -From: Franck Bui-Huu <vagabon.xyz@gmail.com> -Cc: David Brownell <david-b@pacbell.net>, Alan Stern <stern@rowland.harvard.edu> -Content-Disposition: inline -Subject: USB: Zero driver: Removed duplicated code -Date: Tue, 7 Feb 2006 09:06:17 +0100 - -Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com> - - ---- - drivers/usb/gadget/zero.c | 6 ------ - 1 file changed, 6 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/gadget/zero.c -+++ gregkh-2.6/drivers/usb/gadget/zero.c -@@ -1224,12 +1224,6 @@ autoconf_fail: - loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; - } - -- if (gadget->is_otg) { -- otg_descriptor.bmAttributes |= USB_OTG_HNP, -- source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; -- loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; -- } -- - usb_gadget_set_selfpowered (gadget); - - init_timer (&dev->resume); diff --git a/usb/usbcore-fix-compile-error-with-config_usb_suspend-n.patch b/usb/usbcore-fix-compile-error-with-config_usb_suspend-n.patch deleted file mode 100644 index a48ffab904d84..0000000000000 --- a/usb/usbcore-fix-compile-error-with-config_usb_suspend-n.patch +++ /dev/null @@ -1,29 +0,0 @@ -From stern@rowland.harvard.edu Wed Feb 1 07:47:21 2006 -Date: Wed, 1 Feb 2006 10:47:11 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Andrew Morton <akpm@osdl.org> -cc: David Brownell <david-b@pacbell.net>, Greg KH <greg@kroah.com> -Subject: usbcore: fix compile error with CONFIG_USB_SUSPEND=n -Message-ID: <Pine.LNX.4.44L0.0602011044270.5635-100000@iolanthe.rowland.org> - -This patch (as647) fixes a small error introduced by a recent change to -the USB core suspend/resume code. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> - ---- - drivers/usb/core/hub.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- gregkh-2.6.orig/drivers/usb/core/hub.c -+++ gregkh-2.6/drivers/usb/core/hub.c -@@ -1892,8 +1892,8 @@ int usb_resume_device(struct usb_device - status = hub_port_resume(hdev_to_hub(udev->parent), - udev->portnum, udev); - } else -- status = 0; - #endif -+ status = 0; - } else - status = finish_device_resume(udev); - if (status < 0) diff --git a/usb/usbhid-add-error-handling.patch b/usb/usbhid-add-error-handling.patch deleted file mode 100644 index 987cf224b0ea7..0000000000000 --- a/usb/usbhid-add-error-handling.patch +++ /dev/null @@ -1,298 +0,0 @@ -From stern@rowland.harvard.edu Tue Jan 31 09:59:01 2006 -Date: Tue, 31 Jan 2006 12:58:38 -0500 (EST) -From: Alan Stern <stern@rowland.harvard.edu> -To: Greg KH <greg@kroah.com> -cc: Pete Zaitcev <zaitcev@redhat.com>, Dmitry Torokhov <dtor_core@ameritech.net> -Subject: [PATCH] usbhid: add error handling -Message-ID: <Pine.LNX.4.44L0.0601311251270.5380-100000@iolanthe.rowland.org> - -This patch (as628c) adds error handling to the USB HID core. When an -error is reported for an interrupt URB, the driver will do delayed -retries, at increasing intervals, for up to one second. If that doesn't -work, it will try to reset the device. Testing by users has shown that -both the retries and the resets end up getting used. - -Signed-off-by: Alan Stern <stern@rowland.harvard.edu> -Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> - ---- - drivers/usb/input/hid-core.c | 153 +++++++++++++++++++++++++++++++++++++------ - drivers/usb/input/hid.h | 10 ++ - 2 files changed, 142 insertions(+), 21 deletions(-) - ---- gregkh-2.6.orig/drivers/usb/input/hid-core.c -+++ gregkh-2.6/drivers/usb/input/hid-core.c -@@ -903,6 +903,99 @@ static int hid_input_report(int type, st - } - - /* -+ * Input submission and I/O error handler. -+ */ -+ -+static void hid_io_error(struct hid_device *hid); -+ -+/* Start up the input URB */ -+static int hid_start_in(struct hid_device *hid) -+{ -+ unsigned long flags; -+ int rc = 0; -+ -+ spin_lock_irqsave(&hid->inlock, flags); -+ if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) && -+ !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) { -+ rc = usb_submit_urb(hid->urbin, GFP_ATOMIC); -+ if (rc != 0) -+ clear_bit(HID_IN_RUNNING, &hid->iofl); -+ } -+ spin_unlock_irqrestore(&hid->inlock, flags); -+ return rc; -+} -+ -+/* I/O retry timer routine */ -+static void hid_retry_timeout(unsigned long _hid) -+{ -+ struct hid_device *hid = (struct hid_device *) _hid; -+ -+ dev_dbg(&hid->intf->dev, "retrying intr urb\n"); -+ if (hid_start_in(hid)) -+ hid_io_error(hid); -+} -+ -+/* Workqueue routine to reset the device */ -+static void hid_reset(void *_hid) -+{ -+ struct hid_device *hid = (struct hid_device *) _hid; -+ int rc_lock, rc; -+ -+ dev_dbg(&hid->intf->dev, "resetting device\n"); -+ rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); -+ if (rc_lock >= 0) { -+ rc = usb_reset_device(hid->dev); -+ if (rc_lock) -+ usb_unlock_device(hid->dev); -+ } -+ clear_bit(HID_RESET_PENDING, &hid->iofl); -+ -+ if (rc == 0) { -+ hid->retry_delay = 0; -+ if (hid_start_in(hid)) -+ hid_io_error(hid); -+ } else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR)) -+ err("can't reset device, %s-%s/input%d, status %d", -+ hid->dev->bus->bus_name, -+ hid->dev->devpath, -+ hid->ifnum, rc); -+} -+ -+/* Main I/O error handler */ -+static void hid_io_error(struct hid_device *hid) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&hid->inlock, flags); -+ -+ /* Stop when disconnected */ -+ if (usb_get_intfdata(hid->intf) == NULL) -+ goto done; -+ -+ /* When an error occurs, retry at increasing intervals */ -+ if (hid->retry_delay == 0) { -+ hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ -+ hid->stop_retry = jiffies + msecs_to_jiffies(1000); -+ } else if (hid->retry_delay < 100) -+ hid->retry_delay *= 2; -+ -+ if (time_after(jiffies, hid->stop_retry)) { -+ -+ /* Retries failed, so do a port reset */ -+ if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { -+ if (schedule_work(&hid->reset_work)) -+ goto done; -+ clear_bit(HID_RESET_PENDING, &hid->iofl); -+ } -+ } -+ -+ mod_timer(&hid->io_retry, -+ jiffies + msecs_to_jiffies(hid->retry_delay)); -+done: -+ spin_unlock_irqrestore(&hid->inlock, flags); -+} -+ -+/* - * Input interrupt completion handler. - */ - -@@ -913,25 +1006,35 @@ static void hid_irq_in(struct urb *urb, - - switch (urb->status) { - case 0: /* success */ -+ hid->retry_delay = 0; - hid_input_report(HID_INPUT_REPORT, urb, 1, regs); - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: -- case -EPERM: - case -ESHUTDOWN: /* unplug */ -- case -EILSEQ: /* unplug timeout on uhci */ -+ clear_bit(HID_IN_RUNNING, &hid->iofl); - return; -+ case -EILSEQ: /* protocol error or unplug */ -+ case -EPROTO: /* protocol error or unplug */ - case -ETIMEDOUT: /* NAK */ -- break; -+ clear_bit(HID_IN_RUNNING, &hid->iofl); -+ hid_io_error(hid); -+ return; - default: /* error */ - warn("input irq status %d received", urb->status); - } - - status = usb_submit_urb(urb, SLAB_ATOMIC); -- if (status) -- err("can't resubmit intr, %s-%s/input%d, status %d", -- hid->dev->bus->bus_name, hid->dev->devpath, -- hid->ifnum, status); -+ if (status) { -+ clear_bit(HID_IN_RUNNING, &hid->iofl); -+ if (status != -EPERM) { -+ err("can't resubmit intr, %s-%s/input%d, status %d", -+ hid->dev->bus->bus_name, -+ hid->dev->devpath, -+ hid->ifnum, status); -+ hid_io_error(hid); -+ } -+ } - } - - /* -@@ -1093,8 +1196,9 @@ static void hid_irq_out(struct urb *urb, - case 0: /* success */ - break; - case -ESHUTDOWN: /* unplug */ -- case -EILSEQ: /* unplug timeout on uhci */ - unplug = 1; -+ case -EILSEQ: /* protocol error or unplug */ -+ case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - break; -@@ -1141,8 +1245,9 @@ static void hid_ctrl(struct urb *urb, st - hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs); - break; - case -ESHUTDOWN: /* unplug */ -- case -EILSEQ: /* unplug timectrl on uhci */ - unplug = 1; -+ case -EILSEQ: /* protocol error or unplug */ -+ case -EPROTO: /* protocol error or unplug */ - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -EPIPE: /* report not available */ -@@ -1255,14 +1360,9 @@ static int hid_get_class_descriptor(stru - - int hid_open(struct hid_device *hid) - { -- if (hid->open++) -- return 0; -- -- hid->urbin->dev = hid->dev; -- -- if (usb_submit_urb(hid->urbin, GFP_KERNEL)) -- return -EIO; -- -+ ++hid->open; -+ if (hid_start_in(hid)) -+ hid_io_error(hid); - return 0; - } - -@@ -1787,6 +1887,10 @@ static struct hid_device *usb_hid_config - - init_waitqueue_head(&hid->wait); - -+ INIT_WORK(&hid->reset_work, hid_reset, hid); -+ setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); -+ -+ spin_lock_init(&hid->inlock); - spin_lock_init(&hid->outlock); - spin_lock_init(&hid->ctrllock); - -@@ -1855,11 +1959,16 @@ static void hid_disconnect(struct usb_in - if (!hid) - return; - -+ spin_lock_irq(&hid->inlock); /* Sync with error handler */ - usb_set_intfdata(intf, NULL); -+ spin_unlock_irq(&hid->inlock); - usb_kill_urb(hid->urbin); - usb_kill_urb(hid->urbout); - usb_kill_urb(hid->urbctrl); - -+ del_timer_sync(&hid->io_retry); -+ flush_scheduled_work(); -+ - if (hid->claimed & HID_CLAIMED_INPUT) - hidinput_disconnect(hid); - if (hid->claimed & HID_CLAIMED_HIDDEV) -@@ -1934,6 +2043,10 @@ static int hid_suspend(struct usb_interf - { - struct hid_device *hid = usb_get_intfdata (intf); - -+ spin_lock_irq(&hid->inlock); /* Sync with error handler */ -+ set_bit(HID_SUSPENDED, &hid->iofl); -+ spin_unlock_irq(&hid->inlock); -+ del_timer(&hid->io_retry); - usb_kill_urb(hid->urbin); - dev_dbg(&intf->dev, "suspend\n"); - return 0; -@@ -1944,10 +2057,8 @@ static int hid_resume(struct usb_interfa - struct hid_device *hid = usb_get_intfdata (intf); - int status; - -- if (hid->open) -- status = usb_submit_urb(hid->urbin, GFP_NOIO); -- else -- status = 0; -+ clear_bit(HID_SUSPENDED, &hid->iofl); -+ status = hid_start_in(hid); - dev_dbg(&intf->dev, "resume status %d\n", status); - return status; - } ---- gregkh-2.6.orig/drivers/usb/input/hid.h -+++ gregkh-2.6/drivers/usb/input/hid.h -@@ -31,6 +31,8 @@ - #include <linux/types.h> - #include <linux/slab.h> - #include <linux/list.h> -+#include <linux/timer.h> -+#include <linux/workqueue.h> - - /* - * USB HID (Human Interface Device) interface class code -@@ -370,6 +372,9 @@ struct hid_control_fifo { - - #define HID_CTRL_RUNNING 1 - #define HID_OUT_RUNNING 2 -+#define HID_IN_RUNNING 3 -+#define HID_RESET_PENDING 4 -+#define HID_SUSPENDED 5 - - struct hid_input { - struct list_head list; -@@ -393,12 +398,17 @@ struct hid_device { /* device repo - int ifnum; /* USB interface number */ - - unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ -+ struct timer_list io_retry; /* Retry timer */ -+ unsigned long stop_retry; /* Time to give up, in jiffies */ -+ unsigned int retry_delay; /* Delay length in ms */ -+ struct work_struct reset_work; /* Task context for resets */ - - unsigned int bufsize; /* URB buffer size */ - - struct urb *urbin; /* Input URB */ - char *inbuf; /* Input buffer */ - dma_addr_t inbuf_dma; /* Input buffer dma */ -+ spinlock_t inlock; /* Input fifo spinlock */ - - struct urb *urbctrl; /* Control URB */ - struct usb_ctrlrequest *cr; /* Control request struct */ |