From 831c70fc13ca8c6074ab0c9d1121a93fd6c5a34a Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 13 Jul 2007 21:25:25 +0200 Subject: USB: use mutex instead of semaphore in the USB gadget serial driver The USB gadget serial driver uses a semaphore as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 38138bb9ddb0..9cd98e73dc1d 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -258,7 +259,7 @@ static const char *EP_IN_NAME; static const char *EP_OUT_NAME; static const char *EP_NOTIFY_NAME; -static struct semaphore gs_open_close_sem[GS_NUM_PORTS]; +static struct mutex gs_open_close_lock[GS_NUM_PORTS]; static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; @@ -595,7 +596,7 @@ static int __init gs_module_init(void) tty_set_operations(gs_tty_driver, &gs_tty_ops); for (i=0; i < GS_NUM_PORTS; i++) - sema_init(&gs_open_close_sem[i], 1); + mutex_init(&gs_open_close_lock[i]); retval = tty_register_driver(gs_tty_driver); if (retval) { @@ -635,7 +636,7 @@ static int gs_open(struct tty_struct *tty, struct file *file) struct gs_port *port; struct gs_dev *dev; struct gs_buf *buf; - struct semaphore *sem; + struct mutex *mtx; int ret; port_num = tty->index; @@ -656,10 +657,10 @@ static int gs_open(struct tty_struct *tty, struct file *file) return -ENODEV; } - sem = &gs_open_close_sem[port_num]; - if (down_interruptible(sem)) { + mtx = &gs_open_close_lock[port_num]; + if (mutex_lock_interruptible(mtx)) { printk(KERN_ERR - "gs_open: (%d,%p,%p) interrupted waiting for semaphore\n", + "gs_open: (%d,%p,%p) interrupted waiting for mutex\n", port_num, tty, file); return -ERESTARTSYS; } @@ -754,12 +755,12 @@ static int gs_open(struct tty_struct *tty, struct file *file) exit_unlock_port: spin_unlock_irqrestore(&port->port_lock, flags); - up(sem); + mutex_unlock(mtx); return ret; exit_unlock_dev: spin_unlock_irqrestore(&dev->dev_lock, flags); - up(sem); + mutex_unlock(mtx); return ret; } @@ -781,7 +782,7 @@ exit_unlock_dev: static void gs_close(struct tty_struct *tty, struct file *file) { struct gs_port *port = tty->driver_data; - struct semaphore *sem; + struct mutex *mtx; if (port == NULL) { printk(KERN_ERR "gs_close: NULL port pointer\n"); @@ -790,8 +791,8 @@ static void gs_close(struct tty_struct *tty, struct file *file) gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file); - sem = &gs_open_close_sem[port->port_num]; - down(sem); + mtx = &gs_open_close_lock[port->port_num]; + mutex_lock(mtx); spin_lock_irq(&port->port_lock); @@ -846,7 +847,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) exit: spin_unlock_irq(&port->port_lock); - up(sem); + mutex_unlock(mtx); } /* -- cgit v1.2.2 From d2066eb659e6ee915383510c136da38eff86ef15 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 13 Jul 2007 21:26:59 +0200 Subject: USB: use mutex instead of semaphore in the ELAN U132 adapter driver The ELAN U132 adapter driver uses the semaphore u132_module_lock as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index e98df2ee9901..7f765ec038cd 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +84,7 @@ static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); * u132_module_lock exists to protect access to global variables * */ -static struct semaphore u132_module_lock; +static struct mutex u132_module_lock; static int u132_exiting = 0; static int u132_instances = 0; static struct list_head u132_static_list; @@ -258,10 +259,10 @@ static void u132_hcd_delete(struct kref *kref) struct platform_device *pdev = u132->platform_dev; struct usb_hcd *hcd = u132_to_hcd(u132); u132->going += 1; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); list_del_init(&u132->u132_list); u132_instances -= 1; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13" "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev); usb_put_hcd(hcd); @@ -3111,10 +3112,10 @@ static int __devinit u132_probe(struct platform_device *pdev) int retval = 0; struct u132 *u132 = hcd_to_u132(hcd); hcd->rsrc_start = 0; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); list_add_tail(&u132->u132_list, &u132_static_list); u132->sequence_num = ++u132_instances; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); u132_u132_init_kref(u132); u132_initialise(u132, pdev); hcd->product_desc = "ELAN U132 Host Controller"; @@ -3216,7 +3217,7 @@ static int __init u132_hcd_init(void) INIT_LIST_HEAD(&u132_static_list); u132_instances = 0; u132_exiting = 0; - init_MUTEX(&u132_module_lock); + mutex_init(&u132_module_lock); if (usb_disabled()) return -ENODEV; printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__, @@ -3232,9 +3233,9 @@ static void __exit u132_hcd_exit(void) { struct u132 *u132; struct u132 *temp; - down(&u132_module_lock); + mutex_lock(&u132_module_lock); u132_exiting += 1; - up(&u132_module_lock); + mutex_unlock(&u132_module_lock); list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) { platform_device_unregister(u132->platform_dev); } platform_driver_unregister(&u132_platform_driver); -- cgit v1.2.2 From 8293c568b25611cdc4ac54ded438d8d7938c593c Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 13 Jul 2007 21:28:31 +0200 Subject: USB: use mutex instead of semaphore in the Adutux driver The Adutux driver uses a semaphore as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index d72c42e5f22d..274d08ecf291 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef CONFIG_USB_DEBUG @@ -80,7 +81,7 @@ MODULE_DEVICE_TABLE(usb, device_table); /* Structure to hold all of our device specific stuff */ struct adu_device { - struct semaphore sem; /* locks this structure */ + struct mutex mtx; /* locks this structure */ struct usb_device* udev; /* save off the usb device pointer */ struct usb_interface* interface; unsigned char minor; /* the starting minor number for this device */ @@ -269,8 +270,8 @@ static int adu_open(struct inode *inode, struct file *file) } /* lock this device */ - if ((retval = down_interruptible(&dev->sem))) { - dbg(2, "%s : sem down failed", __FUNCTION__); + if ((retval = mutex_lock_interruptible(&dev->mtx))) { + dbg(2, "%s : mutex lock failed", __FUNCTION__); goto exit_no_device; } @@ -299,7 +300,7 @@ static int adu_open(struct inode *inode, struct file *file) if (retval) --dev->open_count; } - up(&dev->sem); + mutex_unlock(&dev->mtx); exit_no_device: dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); @@ -347,7 +348,7 @@ static int adu_release(struct inode *inode, struct file *file) } /* lock our device */ - down(&dev->sem); /* not interruptible */ + mutex_lock(&dev->mtx); /* not interruptible */ if (dev->open_count <= 0) { dbg(1," %s : device not opened", __FUNCTION__); @@ -357,7 +358,7 @@ static int adu_release(struct inode *inode, struct file *file) if (dev->udev == NULL) { /* the device was unplugged before the file was released */ - up(&dev->sem); + mutex_unlock(&dev->mtx); adu_delete(dev); dev = NULL; } else { @@ -367,7 +368,7 @@ static int adu_release(struct inode *inode, struct file *file) exit: if (dev) - up(&dev->sem); + mutex_unlock(&dev->mtx); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } @@ -390,7 +391,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, dev = file->private_data; dbg(2," %s : dev=%p", __FUNCTION__, dev); /* lock this object */ - if (down_interruptible(&dev->sem)) + if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; /* verify that the device wasn't unplugged */ @@ -522,7 +523,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, exit: /* unlock the device */ - up(&dev->sem); + mutex_unlock(&dev->mtx); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; @@ -543,7 +544,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, dev = file->private_data; /* lock this object */ - retval = down_interruptible(&dev->sem); + retval = mutex_lock_interruptible(&dev->mtx); if (retval) goto exit_nolock; @@ -571,9 +572,9 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, retval = -EINTR; goto exit; } - up(&dev->sem); + mutex_unlock(&dev->mtx); timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout); - retval = down_interruptible(&dev->sem); + retval = mutex_lock_interruptible(&dev->mtx); if (retval) { retval = bytes_written ? bytes_written : retval; goto exit_nolock; @@ -638,7 +639,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: /* unlock the device */ - up(&dev->sem); + mutex_unlock(&dev->mtx); exit_nolock: dbg(2," %s : leave, return value %d", __FUNCTION__, retval); @@ -698,7 +699,7 @@ static int adu_probe(struct usb_interface *interface, goto exit; } - init_MUTEX(&dev->sem); + mutex_init(&dev->mtx); spin_lock_init(&dev->buflock); dev->udev = udev; init_waitqueue_head(&dev->read_wait); @@ -835,16 +836,16 @@ static void adu_disconnect(struct usb_interface *interface) usb_deregister_dev(interface, &adu_class); dev->minor = 0; - down(&dev->sem); /* not interruptible */ + mutex_lock(&dev->mtx); /* not interruptible */ /* if the device is not opened, then we clean up right now */ dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); if (!dev->open_count) { - up(&dev->sem); + mutex_unlock(&dev->mtx); adu_delete(dev); } else { dev->udev = NULL; - up(&dev->sem); + mutex_unlock(&dev->mtx); } dev_info(&interface->dev, "ADU device adutux%d now disconnected", -- cgit v1.2.2 From eb33caec1ed29fa2b04a2c5f02e3fed2add91db4 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 13 Jul 2007 21:29:46 +0200 Subject: USB: use mutex instead of semaphore in the FTDI ELAN driver The FTDI ELAN driver uses a semaphore as mutex. Use the mutex API instead of the (binary) semaphore. Signed-off-by: Matthias Kaehlcke Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index e0f122e131d7..7cc6883a6fa3 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,7 @@ static struct workqueue_struct *respond_queue; * ftdi_module_lock exists to protect access to global variables * */ -static struct semaphore ftdi_module_lock; +static struct mutex ftdi_module_lock; static int ftdi_instances = 0; static struct list_head ftdi_static_list; /* @@ -199,10 +200,10 @@ static void ftdi_elan_delete(struct kref *kref) dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi); usb_put_dev(ftdi->udev); ftdi->disconnected += 1; - down(&ftdi_module_lock); + mutex_lock(&ftdi_module_lock); list_del_init(&ftdi->ftdi_list); ftdi_instances -= 1; - up(&ftdi_module_lock); + mutex_unlock(&ftdi_module_lock); kfree(ftdi->bulk_in_buffer); ftdi->bulk_in_buffer = NULL; } @@ -2780,10 +2781,10 @@ static int ftdi_elan_probe(struct usb_interface *interface, return -ENOMEM; } memset(ftdi, 0x00, sizeof(struct usb_ftdi)); - down(&ftdi_module_lock); + mutex_lock(&ftdi_module_lock); list_add_tail(&ftdi->ftdi_list, &ftdi_static_list); ftdi->sequence_num = ++ftdi_instances; - up(&ftdi_module_lock); + mutex_unlock(&ftdi_module_lock); ftdi_elan_init_kref(ftdi); init_MUTEX(&ftdi->sw_lock); ftdi->udev = usb_get_dev(interface_to_usbdev(interface)); @@ -2909,7 +2910,7 @@ static int __init ftdi_elan_init(void) int result; printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name, __TIME__, __DATE__); - init_MUTEX(&ftdi_module_lock); + mutex_init(&ftdi_module_lock); INIT_LIST_HEAD(&ftdi_static_list); status_queue = create_singlethread_workqueue("ftdi-status-control"); if (!status_queue) -- cgit v1.2.2 From 112225b13cedd53dfd6455038b8843cf004ddec9 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Mon, 16 Jul 2007 13:49:27 -0700 Subject: USB: sierra: Add TRU-Install (c) Support This patch adds compatibility with Sierra Wireless' new TRU-Install feature. Future devices that use this feature will not work unless this patch has been applied. Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 98 ++++++++++++++++++++++++++++++-------- drivers/usb/storage/unusual_devs.h | 11 +++++ 2 files changed, 89 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index e7db20343d1a..c137c8962b9f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -1,7 +1,7 @@ /* USB Driver for Sierra Wireless - Copyright (C) 2006 Kevin Lloyd + Copyright (C) 2006, 2007 Kevin Lloyd IMPORTANT DISCLAIMER: This driver is not commercially supported by Sierra Wireless. Use at your own risk. @@ -12,10 +12,9 @@ Portions based on the option driver by Matthias Urlichs Whom based his on the Keyspan driver by Hugh Blemings - */ -#define DRIVER_VERSION "v.1.0.6" +#define DRIVER_VERSION "v.1.2.4b" #define DRIVER_AUTHOR "Kevin Lloyd " #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -28,6 +27,71 @@ #include #include +#define SWIMS_USB_REQUEST_SetMode 0x0B +#define SWIMS_USB_REQUEST_TYPE_SetMode 0x40 +#define SWIMS_USB_INDEX_SetMode 0x0000 +#define SWIMS_SET_MODE_Modem 0x0001 + +/* per port private data */ +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 + +static int debug; + +enum devicetype { + DEVICE_3_PORT = 0, + DEVICE_1_PORT = 1, + DEVICE_INSTALLER = 2, +}; + +int sierra_set_power_state(struct usb_device *udev, __u16 swiState) +{ + int result; + dev_dbg(&udev->dev, "%s", "SET POWER STATE"); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x00, /* __u8 request */ + 0x40, /* __u8 request type */ + swiState, /* __u16 value */ + 0, /* __u16 index */ + NULL, /* void *data */ + 0, /* __u16 size */ + USB_CTRL_SET_TIMEOUT); /* int timeout */ + return result; +} + +int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) +{ + int result; + dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH"); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + SWIMS_USB_REQUEST_SetMode, /* __u8 request */ + SWIMS_USB_REQUEST_TYPE_SetMode, /* __u8 request type */ + eSocMode, /* __u16 value */ + SWIMS_USB_INDEX_SetMode, /* __u16 index */ + NULL, /* void *data */ + 0, /* __u16 size */ + USB_CTRL_SET_TIMEOUT); /* int timeout */ + return result; +} + +int sierra_probe(struct usb_interface *iface, const struct usb_device_id *id) +{ + int result; + struct usb_device *udev; + + udev = usb_get_dev(interface_to_usbdev(iface)); + + /* Check if in installer mode */ + if (id->driver_info == DEVICE_INSTALLER) { + dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n"); + result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem); + /*We do not want to bind to the device when in installer mode*/ + return -EIO; + } + + return usb_serial_probe(iface, id); +} static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ @@ -43,8 +107,10 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ - { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ - { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */ + { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */ + { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */ + + { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER}, { } }; MODULE_DEVICE_TABLE(usb, id_table); @@ -56,6 +122,7 @@ static struct usb_device_id id_table_1port [] = { }; static struct usb_device_id id_table_3port [] = { + /* CDMA Devices */ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ @@ -63,6 +130,8 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + + /* GSM/UMTS Devices */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ @@ -73,20 +142,13 @@ static struct usb_device_id id_table_3port [] = { static struct usb_driver sierra_driver = { .name = "sierra", - .probe = usb_serial_probe, + .probe = sierra_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, .no_dynamic_id = 1, }; -static int debug; - -/* per port private data */ -#define N_IN_URB 4 -#define N_OUT_URB 4 -#define IN_BUFLEN 4096 - struct sierra_port_private { spinlock_t lock; /* lock the structure */ int outstanding_urbs; /* number of out urbs in flight */ @@ -421,7 +483,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) int i; struct urb *urb; int result; - __u16 set_mode_dzero = 0x0000; portdata = usb_get_serial_port_data(port); @@ -457,12 +518,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) port->tty->low_latency = 1; - /* set mode to D0 */ - result = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x00, 0x40, set_mode_dzero, 0, NULL, - 0, USB_CTRL_SET_TIMEOUT); - sierra_send_setup(port); /* start up the interrupt endpoint if we have one */ @@ -510,6 +565,9 @@ static int sierra_startup(struct usb_serial *serial) dbg("%s", __FUNCTION__); + /*Set Device mode to D0 */ + sierra_set_power_state(serial->dev, 0x0000); + /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b6bf31a97b60..26fd196869b9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1384,6 +1384,17 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110, US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, 0 ), +/* Reported by Kevin Lloyd + * Entry is needed for the initializer function override, + * which instructs the device to load as a modem + * device. + */ +UNUSUAL_DEV( 0x1199, 0x0fff, 0x0000, 0x9999, + "Sierra Wireless", + "USB MMC Storage", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE), + /* Reported by Jaco Kroon * The usb-storage module found on the Digitech GNX4 (and supposedly other * devices) misbehaves and causes a bunch of invalid I/O errors. -- cgit v1.2.2 From 9454c46a89c13fe82a28c91706b86f612fd19462 Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Mon, 16 Jul 2007 13:49:29 -0700 Subject: USB: sierra: Add new devices This patch adds new devices to the Sierra Wireless driver. This is being resubmitted because the dependent patch (patch 01/02) needed to be resubmitted. Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index c137c8962b9f..0794ccdebfd4 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -14,7 +14,7 @@ Whom based his on the Keyspan driver by Hugh Blemings */ -#define DRIVER_VERSION "v.1.2.4b" +#define DRIVER_VERSION "v.1.2.5b" #define DRIVER_AUTHOR "Kevin Lloyd " #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -97,15 +97,23 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ - { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ + { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ - { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ + { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ + { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ + { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ + { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ + { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ + { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */ { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */ { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */ @@ -122,21 +130,26 @@ static struct usb_device_id id_table_1port [] = { }; static struct usb_device_id id_table_3port [] = { - /* CDMA Devices */ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ - { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ + { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ - /* GSM/UMTS Devices */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ - { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ + { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ + { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ + { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ + { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ + { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */ + { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */ { } }; -- cgit v1.2.2 From 10e485221edd2799dc495e4cde98fe74aeb292b1 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 10 Jul 2007 20:09:58 -0700 Subject: USB: usblp: "Big cleanup" breaks O_NONBLOCK I found the first regresson in the rewritten ("all dynamic" and "no races") driver. If application uses O_NONBLOCK, I return -EAGAIN despite the URB being submitted successfuly. This causes the application to resubmit the same data erroneously. The fix is to pretend that the transfer has succeeded even if URB was merely queued. It is the same behaviour as with the old version. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 9a1478972bf5..80ec1039d670 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -741,10 +741,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t */ rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK)); if (rv < 0) { - /* - * If interrupted, we simply leave the URB to dangle, - * so the ->release will call usb_kill_urb(). - */ + if (rv == -EAGAIN) { + /* Presume that it's going to complete well. */ + writecount += transfer_length; + } + /* Leave URB dangling, to be cleaned on close. */ goto collect_error; } -- cgit v1.2.2 From 1b4cd43bd3f9aa7a794e29b80b0d984a8e144df4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Jul 2007 17:03:01 -0400 Subject: isp116x-hcd: prepare for urb->status This patch (as931b), adapted from a patch by Olav Kongas, makes a small set of conservative changes to the isp116x-hcd driver in preparation for the removal of urb->status. finish_request() is moved up in the source and is called as soon as the URB is known to have completed, rather than after all the active endpoints have been scanned. The status of a completed URB is kept in a local variable and copied to urb->status only when the URB is about to be given back. -EREMOTEIO error status for control transfers is set after the status stage rather than when the short packet arrives. Some unnecessary uses of urb->lock are removed. Signed-off-by: Alan Stern Cc: Olav Kongas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x-hcd.c | 187 +++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 101 deletions(-) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 46873f2534b5..5c851a36de72 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -228,7 +228,6 @@ static void preproc_atl_queue(struct isp116x *isp116x) struct urb, urb_list); ptd = &ep->ptd; len = ep->length; - spin_lock(&urb->lock); ep->data = (unsigned char *)urb->transfer_buffer + urb->actual_length; @@ -264,7 +263,6 @@ static void preproc_atl_queue(struct isp116x *isp116x) | PTD_EP(ep->epnum); ptd->len = PTD_LEN(len) | PTD_DIR(dir); ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); - spin_unlock(&urb->lock); if (!ep->active) { ptd->mps |= PTD_LAST_MSK; isp116x->atl_last_dir = dir; @@ -274,6 +272,61 @@ static void preproc_atl_queue(struct isp116x *isp116x) } } +/* + Take done or failed requests out of schedule. Give back + processed urbs. +*/ +static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, + struct urb *urb) +__releases(isp116x->lock) __acquires(isp116x->lock) +{ + unsigned i; + + urb->hcpriv = NULL; + ep->error_count = 0; + + if (usb_pipecontrol(urb->pipe)) + ep->nextpid = USB_PID_SETUP; + + urb_dbg(urb, "Finish"); + + spin_unlock(&isp116x->lock); + usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); + spin_lock(&isp116x->lock); + + /* take idle endpoints out of the schedule */ + if (!list_empty(&ep->hep->urb_list)) + return; + + /* async deschedule */ + if (!list_empty(&ep->schedule)) { + list_del_init(&ep->schedule); + return; + } + + /* periodic deschedule */ + DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); + for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { + struct isp116x_ep *temp; + struct isp116x_ep **prev = &isp116x->periodic[i]; + + while (*prev && ((temp = *prev) != ep)) + prev = &temp->next; + if (*prev) + *prev = ep->next; + isp116x->load[i] -= ep->load; + } + ep->branch = PERIODIC_SIZE; + isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= + ep->load / ep->period; + + /* switch irq type? */ + if (!--isp116x->periodic_count) { + isp116x->irqenb &= ~HCuPINT_SOF; + isp116x->irqenb |= HCuPINT_ATL; + } +} + /* Analyze transfer results, handle partial transfers and errors */ @@ -284,6 +337,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) struct usb_device *udev; struct ptd *ptd; int short_not_ok; + int status; u8 cc; for (ep = isp116x->atl_active; ep; ep = ep->active) { @@ -294,7 +348,7 @@ static void postproc_atl_queue(struct isp116x *isp116x) ptd = &ep->ptd; cc = PTD_GET_CC(ptd); short_not_ok = 1; - spin_lock(&urb->lock); + status = -EINPROGRESS; /* Data underrun is special. For allowed underrun we clear the error and continue as normal. For @@ -302,47 +356,36 @@ static void postproc_atl_queue(struct isp116x *isp116x) immediately while for control transfer, we do a STATUS stage. */ if (cc == TD_DATAUNDERRUN) { - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) { - DBG("Allowed data underrun\n"); + if (!(urb->transfer_flags & URB_SHORT_NOT_OK) || + usb_pipecontrol(urb->pipe)) { + DBG("Allowed or control data underrun\n"); cc = TD_CC_NOERROR; short_not_ok = 0; } else { ep->error_count = 1; - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_ACK; - else - usb_settoggle(udev, ep->epnum, - ep->nextpid == - USB_PID_OUT, - PTD_GET_TOGGLE(ptd)); + usb_settoggle(udev, ep->epnum, + ep->nextpid == USB_PID_OUT, + PTD_GET_TOGGLE(ptd)); urb->actual_length += PTD_GET_COUNT(ptd); - urb->status = cc_to_error[TD_DATAUNDERRUN]; - spin_unlock(&urb->lock); - continue; + status = cc_to_error[TD_DATAUNDERRUN]; + goto done; } } - /* Keep underrun error through the STATUS stage */ - if (urb->status == cc_to_error[TD_DATAUNDERRUN]) - cc = TD_DATAUNDERRUN; if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED && (++ep->error_count >= 3 || cc == TD_CC_STALL || cc == TD_DATAOVERRUN)) { - if (urb->status == -EINPROGRESS) - urb->status = cc_to_error[cc]; + status = cc_to_error[cc]; if (ep->nextpid == USB_PID_ACK) ep->nextpid = 0; - spin_unlock(&urb->lock); - continue; + goto done; } /* According to usb spec, zero-length Int transfer signals finishing of the urb. Hey, does this apply only for IN endpoints? */ if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) { - if (urb->status == -EINPROGRESS) - urb->status = 0; - spin_unlock(&urb->lock); - continue; + status = 0; + goto done; } /* Relax after previously failed, but later succeeded @@ -381,8 +424,8 @@ static void postproc_atl_queue(struct isp116x *isp116x) /* All data for this URB is transferred, let's finish */ if (usb_pipecontrol(urb->pipe)) ep->nextpid = USB_PID_ACK; - else if (urb->status == -EINPROGRESS) - urb->status = 0; + else + status = 0; break; case USB_PID_SETUP: if (PTD_GET_ACTIVE(ptd) @@ -402,69 +445,27 @@ static void postproc_atl_queue(struct isp116x *isp116x) if (PTD_GET_ACTIVE(ptd) || (cc != TD_CC_NOERROR && cc < 0x0E)) break; - if (urb->status == -EINPROGRESS) - urb->status = 0; + if ((urb->transfer_flags & URB_SHORT_NOT_OK) && + urb->actual_length < + urb->transfer_buffer_length) + status = -EREMOTEIO; + else + status = 0; ep->nextpid = 0; break; default: BUG(); } - spin_unlock(&urb->lock); - } -} - -/* - Take done or failed requests out of schedule. Give back - processed urbs. -*/ -static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep, - struct urb *urb) -__releases(isp116x->lock) __acquires(isp116x->lock) -{ - unsigned i; - - urb->hcpriv = NULL; - ep->error_count = 0; - - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_SETUP; - - urb_dbg(urb, "Finish"); - - spin_unlock(&isp116x->lock); - usb_hcd_giveback_urb(isp116x_to_hcd(isp116x), urb); - spin_lock(&isp116x->lock); - - /* take idle endpoints out of the schedule */ - if (!list_empty(&ep->hep->urb_list)) - return; - - /* async deschedule */ - if (!list_empty(&ep->schedule)) { - list_del_init(&ep->schedule); - return; - } - /* periodic deschedule */ - DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); - for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { - struct isp116x_ep *temp; - struct isp116x_ep **prev = &isp116x->periodic[i]; - - while (*prev && ((temp = *prev) != ep)) - prev = &temp->next; - if (*prev) - *prev = ep->next; - isp116x->load[i] -= ep->load; - } - ep->branch = PERIODIC_SIZE; - isp116x_to_hcd(isp116x)->self.bandwidth_allocated -= - ep->load / ep->period; - - /* switch irq type? */ - if (!--isp116x->periodic_count) { - isp116x->irqenb &= ~HCuPINT_SOF; - isp116x->irqenb |= HCuPINT_ATL; + done: + if (status != -EINPROGRESS) { + spin_lock(&urb->lock); + if (urb->status == -EINPROGRESS) + urb->status = status; + spin_unlock(&urb->lock); + } + if (urb->status != -EINPROGRESS) + finish_request(isp116x, ep, urb); } } @@ -570,9 +571,6 @@ static void start_atl_transfers(struct isp116x *isp116x) */ static void finish_atl_transfers(struct isp116x *isp116x) { - struct isp116x_ep *ep; - struct urb *urb; - if (!isp116x->atl_active) return; /* Fifo not ready? */ @@ -582,16 +580,6 @@ static void finish_atl_transfers(struct isp116x *isp116x) atomic_inc(&isp116x->atl_finishing); unpack_fifo(isp116x); postproc_atl_queue(isp116x); - for (ep = isp116x->atl_active; ep; ep = ep->active) { - urb = - container_of(ep->hep->urb_list.next, struct urb, urb_list); - /* USB_PID_ACK check here avoids finishing of - control transfers, for which TD_DATAUNDERRUN - occured, while URB_SHORT_NOT_OK was set */ - if (urb && urb->status != -EINPROGRESS - && ep->nextpid != USB_PID_ACK) - finish_request(isp116x, ep, urb); - } atomic_dec(&isp116x->atl_finishing); } @@ -821,15 +809,12 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, } /* in case of unlink-during-submit */ - spin_lock(&urb->lock); if (urb->status != -EINPROGRESS) { - spin_unlock(&urb->lock); finish_request(isp116x, ep, urb); ret = 0; goto fail; } urb->hcpriv = hep; - spin_unlock(&urb->lock); start_atl_transfers(isp116x); fail: -- cgit v1.2.2 From 69d42a78f935d19384d1f6e4f94b65bb162b36df Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Jul 2007 17:06:23 -0400 Subject: USB: add "descriptors" binary sysfs attribute This patch (as934) adds a new readonly binary sysfs attribute file called "descriptors" for each USB device. The attribute contains the device descriptor followed by the raw descriptor entry (config plug subsidiary descriptors) for the current configuration. Having this information available in fixed-format binary makes life a lot easier for user programs by avoiding the need to open, read, and parse multiple sysfs text files. The information in this attribute file is much like that in usbfs's device file, but there are some significant differences: The 2-byte fields in the device descriptor are left in little-endian byte order, as they appear on the bus and in the kernel. Only one raw descriptor set is presented, that of the current configuration. Opening this file will not cause a suspended device to be autoresumed. The last item in particular should be a big selling point for libusb, which currently forces all USB devices to be resumed as it scans the device tree. Signed-off-by: Alan Stern Cc: Dave Mielke Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index d47ae89154a7..2ab222be8fd1 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -441,6 +441,54 @@ static struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; +/* Binary descriptors */ + +static ssize_t +read_descriptors(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + struct usb_device *udev = to_usb_device( + container_of(kobj, struct device, kobj)); + size_t nleft = count; + size_t srclen, n; + + usb_lock_device(udev); + + /* The binary attribute begins with the device descriptor */ + srclen = sizeof(struct usb_device_descriptor); + if (off < srclen) { + n = min_t(size_t, nleft, srclen - off); + memcpy(buf, off + (char *) &udev->descriptor, n); + nleft -= n; + buf += n; + off = 0; + } else { + off -= srclen; + } + + /* Then follows the raw descriptor entry for the current + * configuration (config plus subsidiary descriptors). + */ + if (udev->actconfig) { + int cfgno = udev->actconfig - udev->config; + + srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength); + if (off < srclen) { + n = min_t(size_t, nleft, srclen - off); + memcpy(buf, off + udev->rawdescriptors[cfgno], n); + nleft -= n; + } + } + usb_unlock_device(udev); + return count - nleft; +} + +static struct bin_attribute dev_bin_attr_descriptors = { + .attr = {.name = "descriptors", .mode = 0444}, + .read = read_descriptors, + .size = 18 + 65535, /* dev descr + max-size raw descriptor */ +}; + int usb_create_sysfs_dev_files(struct usb_device *udev) { struct device *dev = &udev->dev; @@ -450,6 +498,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) if (retval) return retval; + retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); + if (retval) + goto error; + retval = add_persist_attributes(dev); if (retval) goto error; @@ -492,6 +544,7 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) device_remove_file(dev, &dev_attr_serial); remove_power_attributes(dev); remove_persist_attributes(dev); + device_remove_bin_file(dev, &dev_bin_attr_descriptors); sysfs_remove_group(&dev->kobj, &dev_attr_grp); } -- cgit v1.2.2 From 195af2cce5ff81c4609c7ba585b6698a7771cbfc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 Jul 2007 15:28:19 -0400 Subject: USB: fix warning caused by autosuspend counter going negative This patch (as937) fixes a minor bug in the autosuspend usage-counting code. Each hub's usage counter keeps track of the number of unsuspended children. However the current driver increments the counter after registering a new child, by which time the child may already have been suspended and caused the counter to go negative. The obvious solution is to increment the counter before registering the child. Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index fd74c50b1804..e341a1da517f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1335,6 +1335,10 @@ int usb_new_device(struct usb_device *udev) udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); + /* Increment the parent's count of unsuspended children */ + if (udev->parent) + usb_autoresume_device(udev->parent); + /* Register the device. The device driver is responsible * for adding the device files to sysfs and for configuring * the device. @@ -1342,13 +1346,11 @@ int usb_new_device(struct usb_device *udev) err = device_add(&udev->dev); if (err) { dev_err(&udev->dev, "can't device_add, error %d\n", err); + if (udev->parent) + usb_autosuspend_device(udev->parent); goto fail; } - /* Increment the parent's count of unsuspended children */ - if (udev->parent) - usb_autoresume_device(udev->parent); - exit: return err; -- cgit v1.2.2 From e94fa28f137813c2f6e05470b41bd8f3c5422a04 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 16 Jul 2007 11:50:53 -0400 Subject: USB: mos7720, mos7840: remove redundant urb check Coverity (1709, 1710, 1711, 1712, 1713) actually flagged these as REVERSE_INULLs (NULL check performed after dereference). But looking at the other drivers I can't see any similar tests and the USB core already makes sure urb is non-null - so might as well get rid of the checks. Signed-off-by: Florin Malita Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 5 ----- drivers/usb/serial/mos7840.c | 19 ------------------- 2 files changed, 24 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 231b584f6d0f..01e811becec4 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -110,11 +110,6 @@ static void mos7720_interrupt_callback(struct urb *urb) dbg("%s"," : Entering\n"); - if (!urb) { - dbg("%s","Invalid Pointer !!!!:\n"); - return; - } - switch (status) { case 0: /* success */ diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 37f41f576d3d..f76480f1455d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -436,11 +436,6 @@ static void mos7840_control_callback(struct urb *urb) int result = 0; int status = urb->status; - if (!urb) { - dbg("%s", "Invalid Pointer !!!!:\n"); - return; - } - mos7840_port = (struct moschip_port *)urb->context; switch (status) { @@ -525,10 +520,6 @@ static void mos7840_interrupt_callback(struct urb *urb) int status = urb->status; dbg("%s", " : Entering\n"); - if (!urb) { - dbg("%s", "Invalid Pointer !!!!:\n"); - return; - } switch (status) { case 0: @@ -676,11 +667,6 @@ static void mos7840_bulk_in_callback(struct urb *urb) struct tty_struct *tty; int status = urb->status; - if (!urb) { - dbg("%s", "Invalid Pointer !!!!:\n"); - return; - } - if (status) { dbg("nonzero read bulk status received: %d", status); return; @@ -753,11 +739,6 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) int status = urb->status; int i; - if (!urb) { - dbg("%s", "Invalid Pointer !!!!:\n"); - return; - } - mos7840_port = (struct moschip_port *)urb->context; spin_lock(&mos7840_port->pool_lock); for (i = 0; i < NUM_URBS; i++) { -- cgit v1.2.2 From e7e7c360fb07020b24652843aec442325baad0ce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 13 Jul 2007 15:46:29 -0400 Subject: UHCI: short control URBs get a status stage It has recently been pointed out that short control transfers should have a status stage, even if they generate an error because URB_SHORT_NOT_OK was set. This patch (as935) changes uhci-hcd to enable the status stage when this happens. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-q.c | 59 ++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 4aed305982ec..3bb908ca38e9 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -827,8 +827,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, * If direction is "send", change the packet ID from SETUP (0x2D) * to OUT (0xE1). Else change it from SETUP to IN (0x69) and * set Short Packet Detect (SPD) for all data packets. + * + * 0-length transfers always get treated as "send". */ - if (usb_pipeout(urb->pipe)) + if (usb_pipeout(urb->pipe) || len == 0) destination ^= (USB_PID_SETUP ^ USB_PID_OUT); else { destination ^= (USB_PID_SETUP ^ USB_PID_IN); @@ -839,7 +841,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, * Build the DATA TDs */ while (len > 0) { - int pktsze = min(len, maxsze); + int pktsze = maxsze; + + if (len <= pktsze) { /* The last data packet */ + pktsze = len; + status &= ~TD_CTRL_SPD; + } td = uhci_alloc_td(uhci); if (!td) @@ -866,20 +873,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, goto nomem; *plink = LINK_TO_TD(td); - /* - * It's IN if the pipe is an output pipe or we're not expecting - * data back. - */ - destination &= ~TD_TOKEN_PID_MASK; - if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - + /* Change direction for the status transaction */ + destination ^= (USB_PID_IN ^ USB_PID_OUT); destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ - status &= ~TD_CTRL_SPD; - uhci_add_td_to_urbp(td, urbp); uhci_fill_td(td, status | TD_CTRL_IOC, destination | uhci_explen(0), 0); @@ -1185,10 +1182,18 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) } } + /* Did we receive a short packet? */ } else if (len < uhci_expected_length(td_token(td))) { - /* We received a short packet */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) + /* For control transfers, go to the status TD if + * this isn't already the last data TD */ + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + if (td->list.next != urbp->td_list.prev) + ret = 1; + } + + /* For bulk and interrupt, this may be an error */ + else if (urb->transfer_flags & URB_SHORT_NOT_OK) ret = -EREMOTEIO; /* Fixup needed only if this isn't the URB's last TD */ @@ -1208,10 +1213,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) err: if (ret < 0) { - /* In case a control transfer gets an error - * during the setup stage */ - urb->actual_length = max(urb->actual_length, 0); - /* Note that the queue has stopped and save * the next toggle value */ qh->element = UHCI_PTR_TERM; @@ -1489,9 +1490,25 @@ __acquires(uhci->lock) { struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { + + /* urb->actual_length < 0 means the setup transaction didn't + * complete successfully. Either it failed or the URB was + * unlinked first. Regardless, don't confuse people with a + * negative length. */ + urb->actual_length = max(urb->actual_length, 0); + + /* Report erroneous short transfers */ + if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && + urb->actual_length < + urb->transfer_buffer_length && + urb->status == 0)) + urb->status = -EREMOTEIO; + } + /* When giving back the first URB in an Isochronous queue, * reinitialize the QH's iso-related members for the next URB. */ - if (qh->type == USB_ENDPOINT_XFER_ISOC && + else if (qh->type == USB_ENDPOINT_XFER_ISOC && urbp->node.prev == &qh->queue && urbp->node.next != &qh->queue) { struct urb *nurb = list_entry(urbp->node.next, -- cgit v1.2.2 From beafef072af10bc8497c9ee51ce2804aa7da26be Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 13 Jul 2007 15:47:16 -0400 Subject: USB: documentation update for usb_unlink_urb This patch (as936) updates the kerneldoc for usb_unlink_urb. The explanation of how endpoint queues are meant to work is now clearer and in better agreement with reality. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 88 ++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 52ec44b828f3..be630228461c 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -440,55 +440,57 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) * @urb: pointer to urb describing a previously submitted request, * may be NULL * - * This routine cancels an in-progress request. URBs complete only - * once per submission, and may be canceled only once per submission. - * Successful cancellation means the requests's completion handler will - * be called with a status code indicating that the request has been - * canceled (rather than any other code) and will quickly be removed - * from host controller data structures. - * - * This request is always asynchronous. - * Success is indicated by returning -EINPROGRESS, - * at which time the URB will normally have been unlinked but not yet - * given back to the device driver. When it is called, the completion - * function will see urb->status == -ECONNRESET. Failure is indicated - * by any other return value. Unlinking will fail when the URB is not - * currently "linked" (i.e., it was never submitted, or it was unlinked - * before, or the hardware is already finished with it), even if the - * completion handler has not yet run. + * This routine cancels an in-progress request. URBs complete only once + * per submission, and may be canceled only once per submission. + * Successful cancellation means termination of @urb will be expedited + * and the completion handler will be called with a status code + * indicating that the request has been canceled (rather than any other + * code). + * + * This request is always asynchronous. Success is indicated by + * returning -EINPROGRESS, at which time the URB will probably not yet + * have been given back to the device driver. When it is eventually + * called, the completion function will see @urb->status == -ECONNRESET. + * Failure is indicated by usb_unlink_urb() returning any other value. + * Unlinking will fail when @urb is not currently "linked" (i.e., it was + * never submitted, or it was unlinked before, or the hardware is already + * finished with it), even if the completion handler has not yet run. * * Unlinking and Endpoint Queues: * + * [The behaviors and guarantees described below do not apply to virtual + * root hubs but only to endpoint queues for physical USB devices.] + * * Host Controller Drivers (HCDs) place all the URBs for a particular * endpoint in a queue. Normally the queue advances as the controller * hardware processes each request. But when an URB terminates with an - * error its queue stops, at least until that URB's completion routine - * returns. It is guaranteed that the queue will not restart until all - * its unlinked URBs have been fully retired, with their completion - * routines run, even if that's not until some time after the original - * completion handler returns. Normally the same behavior and guarantees - * apply when an URB terminates because it was unlinked; however if an - * URB is unlinked before the hardware has started to execute it, then - * its queue is not guaranteed to stop until all the preceding URBs have - * completed. - * - * This means that USB device drivers can safely build deep queues for - * large or complex transfers, and clean them up reliably after any sort - * of aborted transfer by unlinking all pending URBs at the first fault. - * - * Note that an URB terminating early because a short packet was received - * will count as an error if and only if the URB_SHORT_NOT_OK flag is set. - * Also, that all unlinks performed in any URB completion handler must - * be asynchronous. - * - * Queues for isochronous endpoints are treated differently, because they - * advance at fixed rates. Such queues do not stop when an URB is unlinked. - * An unlinked URB may leave a gap in the stream of packets. It is undefined - * whether such gaps can be filled in. - * - * When a control URB terminates with an error, it is likely that the - * status stage of the transfer will not take place, even if it is merely - * a soft error resulting from a short-packet with URB_SHORT_NOT_OK set. + * error its queue generally stops (see below), at least until that URB's + * completion routine returns. It is guaranteed that a stopped queue + * will not restart until all its unlinked URBs have been fully retired, + * with their completion routines run, even if that's not until some time + * after the original completion handler returns. The same behavior and + * guarantee apply when an URB terminates because it was unlinked. + * + * Bulk and interrupt endpoint queues are guaranteed to stop whenever an + * URB terminates with any sort of error, including -ECONNRESET, -ENOENT, + * and -EREMOTEIO. Control endpoint queues behave the same way except + * that they are not guaranteed to stop for -EREMOTEIO errors. Queues + * for isochronous endpoints are treated differently, because they must + * advance at fixed rates. Such queues do not stop when an URB + * encounters an error or is unlinked. An unlinked isochronous URB may + * leave a gap in the stream of packets; it is undefined whether such + * gaps can be filled in. + * + * Note that early termination of an URB because a short packet was + * received will generate a -EREMOTEIO error if and only if the + * URB_SHORT_NOT_OK flag is set. By setting this flag, USB device + * drivers can build deep queues for large or complex bulk transfers + * and clean them up reliably after any sort of aborted transfer by + * unlinking all pending URBs at the first fault. + * + * When a control URB terminates with an error other than -EREMOTEIO, it + * is quite likely that the status stage of the transfer will not take + * place. */ int usb_unlink_urb(struct urb *urb) { -- cgit v1.2.2 From 55d402d854ade6b63b26e958f201ee2ef00b7b15 Mon Sep 17 00:00:00 2001 From: Thomas Dahlmann Date: Mon, 16 Jul 2007 21:40:54 -0700 Subject: USB: amd5536 UDC driver (in GEODE southbridge) Driver for the AMD5536 UDC, as found in the AMD Geode CS5536 (southbridge). This is a high speed DMA-capable controller, which can also be used in OTG configurations (which are not supported by this patch). Acked-by: Jordan Crouse Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 21 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/amd5536udc.c | 3454 +++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/amd5536udc.h | 626 +++++++ drivers/usb/gadget/ether.c | 4 + drivers/usb/gadget/gadget_chips.h | 8 + 6 files changed, 4114 insertions(+) create mode 100644 drivers/usb/gadget/amd5536udc.c create mode 100644 drivers/usb/gadget/amd5536udc.h diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 45e01e289455..1553e9a649cd 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -82,6 +82,27 @@ choice Many controller drivers are platform-specific; these often need board-specific hooks. +config USB_GADGET_AMD5536UDC + boolean "AMD5536 UDC" + depends on PCI + select USB_GADGET_DUALSPEED + help + The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge. + It is a USB Highspeed DMA capable USB device controller. Beside ep0 + it provides 4 IN and 4 OUT endpoints (bulk or interrupt type). + The UDC port supports OTG operation, and may be used as a host port + if it's not being used to implement peripheral or OTG roles. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "amd5536udc" and force all + gadget drivers to also be dynamically linked. + +config USB_AMD5536UDC + tristate + depends on USB_GADGET_AMD5536UDC + default USB_GADGET + select USB_GADGET_SELECTED + config USB_GADGET_FSL_USB2 boolean "Freescale Highspeed USB DR Peripheral Controller" depends on MPC834x || PPC_MPC831x diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 8ae76f738635..1bc0f03550ce 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -7,6 +7,7 @@ endif obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2280) += net2280.o +obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c new file mode 100644 index 000000000000..714156ca8fe4 --- /dev/null +++ b/drivers/usb/gadget/amd5536udc.c @@ -0,0 +1,3454 @@ +/* + * amd5536.c -- AMD 5536 UDC high/full speed USB device controller + * + * Copyright (C) 2005-2007 AMD (http://www.amd.com) + * Author: Thomas Dahlmann + * + * 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 + */ + +/* + * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536. + * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it + * provides 4 IN and 4 OUT endpoints (bulk or interrupt type). + * + * Make sure that UDC is assigned to port 4 by BIOS settings (port can also + * be used as host port) and UOC bits PAD_EN and APU are set (should be done + * by BIOS init). + * + * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not + * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0") + * can be used with gadget ether. + */ + +/* debug control */ +/* #define UDC_VERBOSE */ + +/* Driver strings */ +#define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller" +#define UDC_DRIVER_VERSION_STRING "01.00.0206 - $Revision: #3 $" + +/* system */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* gadget stack */ +#include +#include + +/* udc specific */ +#include "amd5536udc.h" + + +static void udc_tasklet_disconnect(unsigned long); +static void empty_req_queue(struct udc_ep *); +static int udc_probe(struct udc *dev); +static void udc_basic_init(struct udc *dev); +static void udc_setup_endpoints(struct udc *dev); +static void udc_soft_reset(struct udc *dev); +static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep); +static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq); +static int udc_free_dma_chain(struct udc *dev, struct udc_request *req); +static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req, + unsigned long buf_len, gfp_t gfp_flags); +static int udc_remote_wakeup(struct udc *dev); +static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); +static void udc_pci_remove(struct pci_dev *pdev); + +/* description */ +static const char mod_desc[] = UDC_MOD_DESCRIPTION; +static const char name[] = "amd5536udc"; + +/* structure to hold endpoint function pointers */ +static const struct usb_ep_ops udc_ep_ops; + +/* received setup data */ +static union udc_setup_data setup_data; + +/* pointer to device object */ +static struct udc *udc; + +/* irq spin lock for soft reset */ +static DEFINE_SPINLOCK(udc_irq_spinlock); +/* stall spin lock */ +static DEFINE_SPINLOCK(udc_stall_spinlock); + +/* +* slave mode: pending bytes in rx fifo after nyet, +* used if EPIN irq came but no req was available +*/ +static unsigned int udc_rxfifo_pending; + +/* count soft resets after suspend to avoid loop */ +static int soft_reset_occured; +static int soft_reset_after_usbreset_occured; + +/* timer */ +static struct timer_list udc_timer; +static int stop_timer; + +/* set_rde -- Is used to control enabling of RX DMA. Problem is + * that UDC has only one bit (RDE) to enable/disable RX DMA for + * all OUT endpoints. So we have to handle race conditions like + * when OUT data reaches the fifo but no request was queued yet. + * This cannot be solved by letting the RX DMA disabled until a + * request gets queued because there may be other OUT packets + * in the FIFO (important for not blocking control traffic). + * The value of set_rde controls the correspondig timer. + * + * set_rde -1 == not used, means it is alloed to be set to 0 or 1 + * set_rde 0 == do not touch RDE, do no start the RDE timer + * set_rde 1 == timer function will look whether FIFO has data + * set_rde 2 == set by timer function to enable RX DMA on next call + */ +static int set_rde = -1; + +static DECLARE_COMPLETION(on_exit); +static struct timer_list udc_pollstall_timer; +static int stop_pollstall_timer; +static DECLARE_COMPLETION(on_pollstall_exit); + +/* tasklet for usb disconnect */ +static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, + (unsigned long) &udc); + + +/* endpoint names used for print */ +static const char ep0_string[] = "ep0in"; +static const char *ep_string[] = { + ep0_string, + "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", + "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk", + "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk", + "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk", + "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk", + "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk", + "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk" +}; + +/* DMA usage flag */ +static int use_dma = 1; +/* packet per buffer dma */ +static int use_dma_ppb = 1; +/* with per descr. update */ +static int use_dma_ppb_du; +/* buffer fill mode */ +static int use_dma_bufferfill_mode; +/* full speed only mode */ +static int use_fullspeed; +/* tx buffer size for high speed */ +static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE; + +/* module parameters */ +module_param(use_dma, bool, S_IRUGO); +MODULE_PARM_DESC(use_dma, "true for DMA"); +module_param(use_dma_ppb, bool, S_IRUGO); +MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode"); +module_param(use_dma_ppb_du, bool, S_IRUGO); +MODULE_PARM_DESC(use_dma_ppb_du, + "true for DMA in packet per buffer mode with descriptor update"); +module_param(use_fullspeed, bool, S_IRUGO); +MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only"); + +/*---------------------------------------------------------------------------*/ +/* Prints UDC device registers and endpoint irq registers */ +static void print_regs(struct udc *dev) +{ + DBG(dev, "------- Device registers -------\n"); + DBG(dev, "dev config = %08x\n", readl(&dev->regs->cfg)); + DBG(dev, "dev control = %08x\n", readl(&dev->regs->ctl)); + DBG(dev, "dev status = %08x\n", readl(&dev->regs->sts)); + DBG(dev, "\n"); + DBG(dev, "dev int's = %08x\n", readl(&dev->regs->irqsts)); + DBG(dev, "dev intmask = %08x\n", readl(&dev->regs->irqmsk)); + DBG(dev, "\n"); + DBG(dev, "dev ep int's = %08x\n", readl(&dev->regs->ep_irqsts)); + DBG(dev, "dev ep intmask = %08x\n", readl(&dev->regs->ep_irqmsk)); + DBG(dev, "\n"); + DBG(dev, "USE DMA = %d\n", use_dma); + if (use_dma && use_dma_ppb && !use_dma_ppb_du) { + DBG(dev, "DMA mode = PPBNDU (packet per buffer " + "WITHOUT desc. update)\n"); + dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBNDU"); + } else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) { + DBG(dev, "DMA mode = PPBDU (packet per buffer " + "WITH desc. update)\n"); + dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "PPBDU"); + } + if (use_dma && use_dma_bufferfill_mode) { + DBG(dev, "DMA mode = BF (buffer fill mode)\n"); + dev_info(&dev->pdev->dev, "DMA mode (%s)\n", "BF"); + } + if (!use_dma) { + dev_info(&dev->pdev->dev, "FIFO mode\n"); + } + DBG(dev, "-------------------------------------------------------\n"); +} + +/* Masks unused interrupts */ +static int udc_mask_unused_interrupts(struct udc *dev) +{ + u32 tmp; + + /* mask all dev interrupts */ + tmp = AMD_BIT(UDC_DEVINT_SVC) | + AMD_BIT(UDC_DEVINT_ENUM) | + AMD_BIT(UDC_DEVINT_US) | + AMD_BIT(UDC_DEVINT_UR) | + AMD_BIT(UDC_DEVINT_ES) | + AMD_BIT(UDC_DEVINT_SI) | + AMD_BIT(UDC_DEVINT_SOF)| + AMD_BIT(UDC_DEVINT_SC); + writel(tmp, &dev->regs->irqmsk); + + /* mask all ep interrupts */ + writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk); + + return 0; +} + +/* Enables endpoint 0 interrupts */ +static int udc_enable_ep0_interrupts(struct udc *dev) +{ + u32 tmp; + + DBG(dev, "udc_enable_ep0_interrupts()\n"); + + /* read irq mask */ + tmp = readl(&dev->regs->ep_irqmsk); + /* enable ep0 irq's */ + tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0) + & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0); + writel(tmp, &dev->regs->ep_irqmsk); + + return 0; +} + +/* Enables device interrupts for SET_INTF and SET_CONFIG */ +static int udc_enable_dev_setup_interrupts(struct udc *dev) +{ + u32 tmp; + + DBG(dev, "enable device interrupts for setup data\n"); + + /* read irq mask */ + tmp = readl(&dev->regs->irqmsk); + + /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */ + tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI) + & AMD_UNMASK_BIT(UDC_DEVINT_SC) + & AMD_UNMASK_BIT(UDC_DEVINT_UR) + & AMD_UNMASK_BIT(UDC_DEVINT_SVC) + & AMD_UNMASK_BIT(UDC_DEVINT_ENUM); + writel(tmp, &dev->regs->irqmsk); + + return 0; +} + +/* Calculates fifo start of endpoint based on preceeding endpoints */ +static int udc_set_txfifo_addr(struct udc_ep *ep) +{ + struct udc *dev; + u32 tmp; + int i; + + if (!ep || !(ep->in)) + return -EINVAL; + + dev = ep->dev; + ep->txfifo = dev->txfifo; + + /* traverse ep's */ + for (i = 0; i < ep->num; i++) { + if (dev->ep[i].regs) { + /* read fifo size */ + tmp = readl(&dev->ep[i].regs->bufin_framenum); + tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE); + ep->txfifo += tmp; + } + } + return 0; +} + +/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */ +static u32 cnak_pending; + +static void UDC_QUEUE_CNAK(struct udc_ep *ep, unsigned num) +{ + if (readl(&ep->regs->ctl) & AMD_BIT(UDC_EPCTL_NAK)) { + DBG(ep->dev, "NAK could not be cleared for ep%d\n", num); + cnak_pending |= 1 << (num); + ep->naking = 1; + } else + cnak_pending = cnak_pending & (~(1 << (num))); +} + + +/* Enables endpoint, is called by gadget driver */ +static int +udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) +{ + struct udc_ep *ep; + struct udc *dev; + u32 tmp; + unsigned long iflags; + u8 udc_csr_epix; + + if (!usbep + || usbep->name == ep0_string + || !desc + || desc->bDescriptorType != USB_DT_ENDPOINT) + return -EINVAL; + + ep = container_of(usbep, struct udc_ep, ep); + dev = ep->dev; + + DBG(dev, "udc_ep_enable() ep %d\n", ep->num); + + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + spin_lock_irqsave(&dev->lock, iflags); + ep->desc = desc; + + ep->halted = 0; + + /* set traffic type */ + tmp = readl(&dev->ep[ep->num].regs->ctl); + tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET); + writel(tmp, &dev->ep[ep->num].regs->ctl); + + /* set max packet size */ + tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt); + tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE); + ep->ep.maxpacket = desc->wMaxPacketSize; + writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt); + + /* IN ep */ + if (ep->in) { + + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num; + + /* set buffer size (tx fifo entries) */ + tmp = readl(&dev->ep[ep->num].regs->bufin_framenum); + /* double buffering: fifo size = 2 x max packet size */ + tmp = AMD_ADDBITS( + tmp, + desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT + / UDC_DWORD_BYTES, + UDC_EPIN_BUFF_SIZE); + writel(tmp, &dev->ep[ep->num].regs->bufin_framenum); + + /* calc. tx fifo base addr */ + udc_set_txfifo_addr(ep); + + /* flush fifo */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_F); + writel(tmp, &ep->regs->ctl); + + /* OUT ep */ + } else { + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; + + /* set max packet size UDC CSR */ + tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]); + tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, + UDC_CSR_NE_MAX_PKT); + writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]); + + if (use_dma && !ep->in) { + /* alloc and init BNA dummy request */ + ep->bna_dummy_req = udc_alloc_bna_dummy(ep); + ep->bna_occurred = 0; + } + + if (ep->num != UDC_EP0OUT_IX) + dev->data_ep_enabled = 1; + } + + /* set ep values */ + tmp = readl(&dev->csr->ne[udc_csr_epix]); + /* max packet */ + tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT); + /* ep number */ + tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM); + /* ep direction */ + tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR); + /* ep type */ + tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE); + /* ep config */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG); + /* ep interface */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF); + /* ep alt */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT); + /* write reg */ + writel(tmp, &dev->csr->ne[udc_csr_epix]); + + /* enable ep irq */ + tmp = readl(&dev->regs->ep_irqmsk); + tmp &= AMD_UNMASK_BIT(ep->num); + writel(tmp, &dev->regs->ep_irqmsk); + + /* + * clear NAK by writing CNAK + * avoid BNA for OUT DMA, don't clear NAK until DMA desc. written + */ + if (!use_dma || ep->in) { + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->naking = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } + tmp = desc->bEndpointAddress; + DBG(dev, "%s enabled\n", usbep->name); + + spin_unlock_irqrestore(&dev->lock, iflags); + return 0; +} + +/* Resets endpoint */ +static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep) +{ + u32 tmp; + + VDBG(ep->dev, "ep-%d reset\n", ep->num); + ep->desc = NULL; + ep->ep.ops = &udc_ep_ops; + INIT_LIST_HEAD(&ep->queue); + + ep->ep.maxpacket = (u16) ~0; + /* set NAK */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_SNAK); + writel(tmp, &ep->regs->ctl); + ep->naking = 1; + + /* disable interrupt */ + tmp = readl(®s->ep_irqmsk); + tmp |= AMD_BIT(ep->num); + writel(tmp, ®s->ep_irqmsk); + + if (ep->in) { + /* unset P and IN bit of potential former DMA */ + tmp = readl(&ep->regs->ctl); + tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P); + writel(tmp, &ep->regs->ctl); + + tmp = readl(&ep->regs->sts); + tmp |= AMD_BIT(UDC_EPSTS_IN); + writel(tmp, &ep->regs->sts); + + /* flush the fifo */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_F); + writel(tmp, &ep->regs->ctl); + + } + /* reset desc pointer */ + writel(0, &ep->regs->desptr); +} + +/* Disables endpoint, is called by gadget driver */ +static int udc_ep_disable(struct usb_ep *usbep) +{ + struct udc_ep *ep = NULL; + unsigned long iflags; + + if (!usbep) + return -EINVAL; + + ep = container_of(usbep, struct udc_ep, ep); + if (usbep->name == ep0_string || !ep->desc) + return -EINVAL; + + DBG(ep->dev, "Disable ep-%d\n", ep->num); + + spin_lock_irqsave(&ep->dev->lock, iflags); + udc_free_request(&ep->ep, &ep->bna_dummy_req->req); + empty_req_queue(ep); + ep_init(ep->dev->regs, ep); + spin_unlock_irqrestore(&ep->dev->lock, iflags); + + return 0; +} + +/* Allocates request packet, called by gadget driver */ +static struct usb_request * +udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) +{ + struct udc_request *req; + struct udc_data_dma *dma_desc; + struct udc_ep *ep; + + if (!usbep) + return NULL; + + ep = container_of(usbep, struct udc_ep, ep); + + VDBG(ep->dev, "udc_alloc_req(): ep%d\n", ep->num); + req = kzalloc(sizeof(struct udc_request), gfp); + if (!req) + return NULL; + + req->req.dma = DMA_DONT_USE; + INIT_LIST_HEAD(&req->queue); + + if (ep->dma) { + /* ep0 in requests are allocated from data pool here */ + dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp, + &req->td_phys); + if (!dma_desc) { + kfree(req); + return NULL; + } + + VDBG(ep->dev, "udc_alloc_req: req = %p dma_desc = %p, " + "td_phys = %lx\n", + req, dma_desc, + (unsigned long)req->td_phys); + /* prevent from using desc. - set HOST BUSY */ + dma_desc->status = AMD_ADDBITS(dma_desc->status, + UDC_DMA_STP_STS_BS_HOST_BUSY, + UDC_DMA_STP_STS_BS); + dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE); + req->td_data = dma_desc; + req->td_data_last = NULL; + req->chain_len = 1; + } + + return &req->req; +} + +/* Frees request packet, called by gadget driver */ +static void +udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq) +{ + struct udc_ep *ep; + struct udc_request *req; + + if (!usbep || !usbreq) + return; + + ep = container_of(usbep, struct udc_ep, ep); + req = container_of(usbreq, struct udc_request, req); + VDBG(ep->dev, "free_req req=%p\n", req); + BUG_ON(!list_empty(&req->queue)); + if (req->td_data) { + VDBG(ep->dev, "req->td_data=%p\n", req->td_data); + + /* free dma chain if created */ + if (req->chain_len > 1) { + udc_free_dma_chain(ep->dev, req); + } + + pci_pool_free(ep->dev->data_requests, req->td_data, + req->td_phys); + } + kfree(req); +} + +/* Init BNA dummy descriptor for HOST BUSY and pointing to itself */ +static void udc_init_bna_dummy(struct udc_request *req) +{ + if (req) { + /* set last bit */ + req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L); + /* set next pointer to itself */ + req->td_data->next = req->td_phys; + /* set HOST BUSY */ + req->td_data->status + = AMD_ADDBITS(req->td_data->status, + UDC_DMA_STP_STS_BS_DMA_DONE, + UDC_DMA_STP_STS_BS); +#ifdef UDC_VERBOSE + pr_debug("bna desc = %p, sts = %08x\n", + req->td_data, req->td_data->status); +#endif + } +} + +/* Allocate BNA dummy descriptor */ +static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep) +{ + struct udc_request *req = NULL; + struct usb_request *_req = NULL; + + /* alloc the dummy request */ + _req = udc_alloc_request(&ep->ep, GFP_ATOMIC); + if (_req) { + req = container_of(_req, struct udc_request, req); + ep->bna_dummy_req = req; + udc_init_bna_dummy(req); + } + return req; +} + +/* Write data to TX fifo for IN packets */ +static void +udc_txfifo_write(struct udc_ep *ep, struct usb_request *req) +{ + u8 *req_buf; + u32 *buf; + int i, j; + unsigned bytes = 0; + unsigned remaining = 0; + + if (!req || !ep) + return; + + req_buf = req->buf + req->actual; + prefetch(req_buf); + remaining = req->length - req->actual; + + buf = (u32 *) req_buf; + + bytes = ep->ep.maxpacket; + if (bytes > remaining) + bytes = remaining; + + /* dwords first */ + for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { + writel(*(buf + i), ep->txfifo); + } + + /* remaining bytes must be written by byte access */ + for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) { + writeb((u8)(*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)), + ep->txfifo); + } + + /* dummy write confirm */ + writel(0, &ep->regs->confirm); +} + +/* Read dwords from RX fifo for OUT transfers */ +static int udc_rxfifo_read_dwords(struct udc *dev, u32 *buf, int dwords) +{ + int i; + + VDBG(dev, "udc_read_dwords(): %d dwords\n", dwords); + + for (i = 0; i < dwords; i++) { + *(buf + i) = readl(dev->rxfifo); + } + return 0; +} + +/* Read bytes from RX fifo for OUT transfers */ +static int udc_rxfifo_read_bytes(struct udc *dev, u8 *buf, int bytes) +{ + int i, j; + u32 tmp; + + VDBG(dev, "udc_read_bytes(): %d bytes\n", bytes); + + /* dwords first */ + for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { + *((u32 *)(buf + (i<<2))) = readl(dev->rxfifo); + } + + /* remaining bytes must be read by byte access */ + if (bytes % UDC_DWORD_BYTES) { + tmp = readl(dev->rxfifo); + for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) { + *(buf + (i<<2) + j) = (u8)(tmp & UDC_BYTE_MASK); + tmp = tmp >> UDC_BITS_PER_BYTE; + } + } + + return 0; +} + +/* Read data from RX fifo for OUT transfers */ +static int +udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req) +{ + u8 *buf; + unsigned buf_space; + unsigned bytes = 0; + unsigned finished = 0; + + /* received number bytes */ + bytes = readl(&ep->regs->sts); + bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE); + + buf_space = req->req.length - req->req.actual; + buf = req->req.buf + req->req.actual; + if (bytes > buf_space) { + if ((buf_space % ep->ep.maxpacket) != 0) { + DBG(ep->dev, + "%s: rx %d bytes, rx-buf space = %d bytesn\n", + ep->ep.name, bytes, buf_space); + req->req.status = -EOVERFLOW; + } + bytes = buf_space; + } + req->req.actual += bytes; + + /* last packet ? */ + if (((bytes % ep->ep.maxpacket) != 0) || (!bytes) + || ((req->req.actual == req->req.length) && !req->req.zero)) + finished = 1; + + /* read rx fifo bytes */ + VDBG(ep->dev, "ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes); + udc_rxfifo_read_bytes(ep->dev, buf, bytes); + + return finished; +} + +/* create/re-init a DMA descriptor or a DMA descriptor chain */ +static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp) +{ + int retval = 0; + u32 tmp; + + VDBG(ep->dev, "prep_dma\n"); + VDBG(ep->dev, "prep_dma ep%d req->td_data=%p\n", + ep->num, req->td_data); + + /* set buffer pointer */ + req->td_data->bufptr = req->req.dma; + + /* set last bit */ + req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L); + + /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */ + if (use_dma_ppb) { + + retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp); + if (retval != 0) { + if (retval == -ENOMEM) + DBG(ep->dev, "Out of DMA memory\n"); + return retval; + } + if (ep->in) { + if (req->req.length == ep->ep.maxpacket) { + /* write tx bytes */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + ep->ep.maxpacket, + UDC_DMA_IN_STS_TXBYTES); + + } + } + + } + + if (ep->in) { + VDBG(ep->dev, "IN: use_dma_ppb=%d req->req.len=%d " + "maxpacket=%d ep%d\n", + use_dma_ppb, req->req.length, + ep->ep.maxpacket, ep->num); + /* + * if bytes < max packet then tx bytes must + * be written in packet per buffer mode + */ + if (!use_dma_ppb || req->req.length < ep->ep.maxpacket + || ep->num == UDC_EP0OUT_IX + || ep->num == UDC_EP0IN_IX) { + /* write tx bytes */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + req->req.length, + UDC_DMA_IN_STS_TXBYTES); + /* reset frame num */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + 0, + UDC_DMA_IN_STS_FRAMENUM); + } + /* set HOST BUSY */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + UDC_DMA_STP_STS_BS_HOST_BUSY, + UDC_DMA_STP_STS_BS); + } else { + VDBG(ep->dev, "OUT set host ready\n"); + /* set HOST READY */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + UDC_DMA_STP_STS_BS_HOST_READY, + UDC_DMA_STP_STS_BS); + + + /* clear NAK by writing CNAK */ + if (ep->naking) { + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->naking = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } + + } + + return retval; +} + +/* Completes request packet ... caller MUST hold lock */ +static void +complete_req(struct udc_ep *ep, struct udc_request *req, int sts) +__releases(ep->dev->lock) +__acquires(ep->dev->lock) +{ + struct udc *dev; + unsigned halted; + + VDBG(ep->dev, "complete_req(): ep%d\n", ep->num); + + dev = ep->dev; + /* unmap DMA */ + if (req->dma_mapping) { + if (ep->in) + pci_unmap_single(dev->pdev, + req->req.dma, + req->req.length, + PCI_DMA_TODEVICE); + else + pci_unmap_single(dev->pdev, + req->req.dma, + req->req.length, + PCI_DMA_FROMDEVICE); + req->dma_mapping = 0; + req->req.dma = DMA_DONT_USE; + } + + halted = ep->halted; + ep->halted = 1; + + /* set new status if pending */ + if (req->req.status == -EINPROGRESS) + req->req.status = sts; + + /* remove from ep queue */ + list_del_init(&req->queue); + + VDBG(ep->dev, "req %p => complete %d bytes at %s with sts %d\n", + &req->req, req->req.length, ep->ep.name, sts); + + spin_unlock(&dev->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&dev->lock); + ep->halted = halted; +} + +/* frees pci pool descriptors of a DMA chain */ +static int udc_free_dma_chain(struct udc *dev, struct udc_request *req) +{ + + int ret_val = 0; + struct udc_data_dma *td; + struct udc_data_dma *td_last = NULL; + unsigned int i; + + DBG(dev, "free chain req = %p\n", req); + + /* do not free first desc., will be done by free for request */ + td_last = req->td_data; + td = phys_to_virt(td_last->next); + + for (i = 1; i < req->chain_len; i++) { + + pci_pool_free(dev->data_requests, td, + (dma_addr_t) td_last->next); + td_last = td; + td = phys_to_virt(td_last->next); + } + + return ret_val; +} + +/* Iterates to the end of a DMA chain and returns last descriptor */ +static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req) +{ + struct udc_data_dma *td; + + td = req->td_data; + while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) { + td = phys_to_virt(td->next); + } + + return td; + +} + +/* Iterates to the end of a DMA chain and counts bytes received */ +static u32 udc_get_ppbdu_rxbytes(struct udc_request *req) +{ + struct udc_data_dma *td; + u32 count; + + td = req->td_data; + /* received number bytes */ + count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES); + + while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) { + td = phys_to_virt(td->next); + /* received number bytes */ + if (td) { + count += AMD_GETBITS(td->status, + UDC_DMA_OUT_STS_RXBYTES); + } + } + + return count; + +} + +/* Creates or re-inits a DMA chain */ +static int udc_create_dma_chain( + struct udc_ep *ep, + struct udc_request *req, + unsigned long buf_len, gfp_t gfp_flags +) +{ + unsigned long bytes = req->req.length; + unsigned int i; + dma_addr_t dma_addr; + struct udc_data_dma *td = NULL; + struct udc_data_dma *last = NULL; + unsigned long txbytes; + unsigned create_new_chain = 0; + unsigned len; + + VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n", + bytes, buf_len); + dma_addr = DMA_DONT_USE; + + /* unset L bit in first desc for OUT */ + if (!ep->in) { + req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L); + } + + /* alloc only new desc's if not already available */ + len = req->req.length / ep->ep.maxpacket; + if (req->req.length % ep->ep.maxpacket) { + len++; + } + + if (len > req->chain_len) { + /* shorter chain already allocated before */ + if (req->chain_len > 1) { + udc_free_dma_chain(ep->dev, req); + } + req->chain_len = len; + create_new_chain = 1; + } + + td = req->td_data; + /* gen. required number of descriptors and buffers */ + for (i = buf_len; i < bytes; i += buf_len) { + /* create or determine next desc. */ + if (create_new_chain) { + + td = pci_pool_alloc(ep->dev->data_requests, + gfp_flags, &dma_addr); + if (!td) + return -ENOMEM; + + td->status = 0; + } else if (i == buf_len) { + /* first td */ + td = (struct udc_data_dma *) phys_to_virt( + req->td_data->next); + td->status = 0; + } else { + td = (struct udc_data_dma *) phys_to_virt(last->next); + td->status = 0; + } + + + if (td) + td->bufptr = req->req.dma + i; /* assign buffer */ + else + break; + + /* short packet ? */ + if ((bytes - i) >= buf_len) { + txbytes = buf_len; + } else { + /* short packet */ + txbytes = bytes - i; + } + + /* link td and assign tx bytes */ + if (i == buf_len) { + if (create_new_chain) { + req->td_data->next = dma_addr; + } else { + /* req->td_data->next = virt_to_phys(td); */ + } + /* write tx bytes */ + if (ep->in) { + /* first desc */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + ep->ep.maxpacket, + UDC_DMA_IN_STS_TXBYTES); + /* second desc */ + td->status = AMD_ADDBITS(td->status, + txbytes, + UDC_DMA_IN_STS_TXBYTES); + } + } else { + if (create_new_chain) { + last->next = dma_addr; + } else { + /* last->next = virt_to_phys(td); */ + } + if (ep->in) { + /* write tx bytes */ + td->status = AMD_ADDBITS(td->status, + txbytes, + UDC_DMA_IN_STS_TXBYTES); + } + } + last = td; + } + /* set last bit */ + if (td) { + td->status |= AMD_BIT(UDC_DMA_IN_STS_L); + /* last desc. points to itself */ + req->td_data_last = td; + } + + return 0; +} + +/* Enabling RX DMA */ +static void udc_set_rde(struct udc *dev) +{ + u32 tmp; + + VDBG(dev, "udc_set_rde()\n"); + /* stop RDE timer */ + if (timer_pending(&udc_timer)) { + set_rde = 0; + mod_timer(&udc_timer, jiffies - 1); + } + /* set RDE */ + tmp = readl(&dev->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_RDE); + writel(tmp, &dev->regs->ctl); +} + +/* Queues a request packet, called by gadget driver */ +static int +udc_queue(struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) +{ + int retval = 0; + u8 open_rxfifo = 0; + unsigned long iflags; + struct udc_ep *ep; + struct udc_request *req; + struct udc *dev; + u32 tmp; + + /* check the inputs */ + req = container_of(usbreq, struct udc_request, req); + + if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf + || !list_empty(&req->queue)) + return -EINVAL; + + ep = container_of(usbep, struct udc_ep, ep); + if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + return -EINVAL; + + VDBG(ep->dev, "udc_queue(): ep%d-in=%d\n", ep->num, ep->in); + dev = ep->dev; + + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + /* map dma (usually done before) */ + if (ep->dma && usbreq->length != 0 + && (usbreq->dma == DMA_DONT_USE || usbreq->dma == 0)) { + VDBG(dev, "DMA map req %p\n", req); + if (ep->in) + usbreq->dma = pci_map_single(dev->pdev, + usbreq->buf, + usbreq->length, + PCI_DMA_TODEVICE); + else + usbreq->dma = pci_map_single(dev->pdev, + usbreq->buf, + usbreq->length, + PCI_DMA_FROMDEVICE); + req->dma_mapping = 1; + } + + VDBG(dev, "%s queue req %p, len %d req->td_data=%p buf %p\n", + usbep->name, usbreq, usbreq->length, + req->td_data, usbreq->buf); + + spin_lock_irqsave(&dev->lock, iflags); + usbreq->actual = 0; + usbreq->status = -EINPROGRESS; + req->dma_done = 0; + + /* on empty queue just do first transfer */ + if (list_empty(&ep->queue)) { + /* zlp */ + if (usbreq->length == 0) { + /* IN zlp's are handled by hardware */ + complete_req(ep, req, 0); + VDBG(dev, "%s: zlp\n", ep->ep.name); + /* + * if set_config or set_intf is waiting for ack by zlp + * then set CSR_DONE + */ + if (dev->set_cfg_not_acked) { + tmp = readl(&dev->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE); + writel(tmp, &dev->regs->ctl); + dev->set_cfg_not_acked = 0; + } + /* setup command is ACK'ed now by zlp */ + if (dev->waiting_zlp_ack_ep0in) { + /* clear NAK by writing CNAK in EP0_IN */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + dev->ep[UDC_EP0IN_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], + UDC_EP0IN_IX); + dev->waiting_zlp_ack_ep0in = 0; + } + goto finished; + } + if (ep->dma) { + retval = prep_dma(ep, req, gfp); + if (retval != 0) + goto finished; + /* write desc pointer to enable DMA */ + if (ep->in) { + /* set HOST READY */ + req->td_data->status = + AMD_ADDBITS(req->td_data->status, + UDC_DMA_IN_STS_BS_HOST_READY, + UDC_DMA_IN_STS_BS); + } + + /* disabled rx dma while descriptor update */ + if (!ep->in) { + /* stop RDE timer */ + if (timer_pending(&udc_timer)) { + set_rde = 0; + mod_timer(&udc_timer, jiffies - 1); + } + /* clear RDE */ + tmp = readl(&dev->regs->ctl); + tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE); + writel(tmp, &dev->regs->ctl); + open_rxfifo = 1; + + /* + * if BNA occurred then let BNA dummy desc. + * point to current desc. + */ + if (ep->bna_occurred) { + VDBG(dev, "copy to BNA dummy desc.\n"); + memcpy(ep->bna_dummy_req->td_data, + req->td_data, + sizeof(struct udc_data_dma)); + } + } + /* write desc pointer */ + writel(req->td_phys, &ep->regs->desptr); + + /* clear NAK by writing CNAK */ + if (ep->naking) { + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->naking = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } + + if (ep->in) { + /* enable ep irq */ + tmp = readl(&dev->regs->ep_irqmsk); + tmp &= AMD_UNMASK_BIT(ep->num); + writel(tmp, &dev->regs->ep_irqmsk); + } + } + + } else if (ep->dma) { + + /* + * prep_dma not used for OUT ep's, this is not possible + * for PPB modes, because of chain creation reasons + */ + if (ep->in) { + retval = prep_dma(ep, req, gfp); + if (retval != 0) + goto finished; + } + } + VDBG(dev, "list_add\n"); + /* add request to ep queue */ + if (req) { + + list_add_tail(&req->queue, &ep->queue); + + /* open rxfifo if out data queued */ + if (open_rxfifo) { + /* enable DMA */ + req->dma_going = 1; + udc_set_rde(dev); + if (ep->num != UDC_EP0OUT_IX) + dev->data_ep_queued = 1; + } + /* stop OUT naking */ + if (!ep->in) { + if (!use_dma && udc_rxfifo_pending) { + DBG(dev, "udc_queue(): pending bytes in" + "rxfifo after nyet\n"); + /* + * read pending bytes afer nyet: + * referring to isr + */ + if (udc_rxfifo_read(ep, req)) { + /* finish */ + complete_req(ep, req, 0); + } + udc_rxfifo_pending = 0; + + } + } + } + +finished: + spin_unlock_irqrestore(&dev->lock, iflags); + return retval; +} + +/* Empty request queue of an endpoint; caller holds spinlock */ +static void empty_req_queue(struct udc_ep *ep) +{ + struct udc_request *req; + + ep->halted = 1; + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, + struct udc_request, + queue); + complete_req(ep, req, -ESHUTDOWN); + } +} + +/* Dequeues a request packet, called by gadget driver */ +static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) +{ + struct udc_ep *ep; + struct udc_request *req; + unsigned halted; + unsigned long iflags; + + ep = container_of(usbep, struct udc_ep, ep); + if (!usbep || !usbreq || (!ep->desc && (ep->num != 0 + && ep->num != UDC_EP0OUT_IX))) + return -EINVAL; + + req = container_of(usbreq, struct udc_request, req); + + spin_lock_irqsave(&ep->dev->lock, iflags); + halted = ep->halted; + ep->halted = 1; + /* request in processing or next one */ + if (ep->queue.next == &req->queue) { + if (ep->dma && req->dma_going) { + if (ep->in) + ep->cancel_transfer = 1; + else { + u32 tmp; + u32 dma_sts; + /* stop potential receive DMA */ + tmp = readl(&udc->regs->ctl); + writel(tmp & AMD_UNMASK_BIT(UDC_DEVCTL_RDE), + &udc->regs->ctl); + /* + * Cancel transfer later in ISR + * if descriptor was touched. + */ + dma_sts = AMD_GETBITS(req->td_data->status, + UDC_DMA_OUT_STS_BS); + if (dma_sts != UDC_DMA_OUT_STS_BS_HOST_READY) + ep->cancel_transfer = 1; + else { + udc_init_bna_dummy(ep->req); + writel(ep->bna_dummy_req->td_phys, + &ep->regs->desptr); + } + writel(tmp, &udc->regs->ctl); + } + } + } + complete_req(ep, req, -ECONNRESET); + ep->halted = halted; + + spin_unlock_irqrestore(&ep->dev->lock, iflags); + return 0; +} + +/* Halt or clear halt of endpoint */ +static int +udc_set_halt(struct usb_ep *usbep, int halt) +{ + struct udc_ep *ep; + u32 tmp; + unsigned long iflags; + int retval = 0; + + if (!usbep) + return -EINVAL; + + pr_debug("set_halt %s: halt=%d\n", usbep->name, halt); + + ep = container_of(usbep, struct udc_ep, ep); + if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) + return -EINVAL; + if (!ep->dev->driver || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) + return -ESHUTDOWN; + + spin_lock_irqsave(&udc_stall_spinlock, iflags); + /* halt or clear halt */ + if (halt) { + if (ep->num == 0) + ep->dev->stall_ep0in = 1; + else { + /* + * set STALL + * rxfifo empty not taken into acount + */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_S); + writel(tmp, &ep->regs->ctl); + ep->halted = 1; + + /* setup poll timer */ + if (!timer_pending(&udc_pollstall_timer)) { + udc_pollstall_timer.expires = jiffies + + HZ * UDC_POLLSTALL_TIMER_USECONDS + / (1000 * 1000); + if (!stop_pollstall_timer) { + DBG(ep->dev, "start polltimer\n"); + add_timer(&udc_pollstall_timer); + } + } + } + } else { + /* ep is halted by set_halt() before */ + if (ep->halted) { + tmp = readl(&ep->regs->ctl); + /* clear stall bit */ + tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); + /* clear NAK by writing CNAK */ + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->halted = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } + } + spin_unlock_irqrestore(&udc_stall_spinlock, iflags); + return retval; +} + +/* gadget interface */ +static const struct usb_ep_ops udc_ep_ops = { + .enable = udc_ep_enable, + .disable = udc_ep_disable, + + .alloc_request = udc_alloc_request, + .free_request = udc_free_request, + + .queue = udc_queue, + .dequeue = udc_dequeue, + + .set_halt = udc_set_halt, + /* fifo ops not implemented */ +}; + +/*-------------------------------------------------------------------------*/ + +/* Get frame counter (not implemented) */ +static int udc_get_frame(struct usb_gadget *gadget) +{ + return -EOPNOTSUPP; +} + +/* Remote wakeup gadget interface */ +static int udc_wakeup(struct usb_gadget *gadget) +{ + struct udc *dev; + + if (!gadget) + return -EINVAL; + dev = container_of(gadget, struct udc, gadget); + udc_remote_wakeup(dev); + + return 0; +} + +/* gadget operations */ +static const struct usb_gadget_ops udc_ops = { + .wakeup = udc_wakeup, + .get_frame = udc_get_frame, +}; + +/* Setups endpoint parameters, adds endpoints to linked list */ +static void make_ep_lists(struct udc *dev) +{ + /* make gadget ep lists */ + INIT_LIST_HEAD(&dev->gadget.ep_list); + list_add_tail(&dev->ep[UDC_EPIN_STATUS_IX].ep.ep_list, + &dev->gadget.ep_list); + list_add_tail(&dev->ep[UDC_EPIN_IX].ep.ep_list, + &dev->gadget.ep_list); + list_add_tail(&dev->ep[UDC_EPOUT_IX].ep.ep_list, + &dev->gadget.ep_list); + + /* fifo config */ + dev->ep[UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE; + if (dev->gadget.speed == USB_SPEED_FULL) + dev->ep[UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE; + else if (dev->gadget.speed == USB_SPEED_HIGH) + dev->ep[UDC_EPIN_IX].fifo_depth = hs_tx_buf; + dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE; +} + +/* init registers at driver load time */ +static int startup_registers(struct udc *dev) +{ + u32 tmp; + + /* init controller by soft reset */ + udc_soft_reset(dev); + + /* mask not needed interrupts */ + udc_mask_unused_interrupts(dev); + + /* put into initial config */ + udc_basic_init(dev); + /* link up all endpoints */ + udc_setup_endpoints(dev); + + /* program speed */ + tmp = readl(&dev->regs->cfg); + if (use_fullspeed) { + tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); + } else { + tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD); + } + writel(tmp, &dev->regs->cfg); + + return 0; +} + +/* Inits UDC context */ +static void udc_basic_init(struct udc *dev) +{ + u32 tmp; + + DBG(dev, "udc_basic_init()\n"); + + dev->gadget.speed = USB_SPEED_UNKNOWN; + + /* stop RDE timer */ + if (timer_pending(&udc_timer)) { + set_rde = 0; + mod_timer(&udc_timer, jiffies - 1); + } + /* stop poll stall timer */ + if (timer_pending(&udc_pollstall_timer)) { + mod_timer(&udc_pollstall_timer, jiffies - 1); + } + /* disable DMA */ + tmp = readl(&dev->regs->ctl); + tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE); + tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE); + writel(tmp, &dev->regs->ctl); + + /* enable dynamic CSR programming */ + tmp = readl(&dev->regs->cfg); + tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG); + /* set self powered */ + tmp |= AMD_BIT(UDC_DEVCFG_SP); + /* set remote wakeupable */ + tmp |= AMD_BIT(UDC_DEVCFG_RWKP); + writel(tmp, &dev->regs->cfg); + + make_ep_lists(dev); + + dev->data_ep_enabled = 0; + dev->data_ep_queued = 0; +} + +/* Sets initial endpoint parameters */ +static void udc_setup_endpoints(struct udc *dev) +{ + struct udc_ep *ep; + u32 tmp; + u32 reg; + + DBG(dev, "udc_setup_endpoints()\n"); + + /* read enum speed */ + tmp = readl(&dev->regs->sts); + tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED); + if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) { + dev->gadget.speed = USB_SPEED_HIGH; + } else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) { + dev->gadget.speed = USB_SPEED_FULL; + } + + /* set basic ep parameters */ + for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { + ep = &dev->ep[tmp]; + ep->dev = dev; + ep->ep.name = ep_string[tmp]; + ep->num = tmp; + /* txfifo size is calculated at enable time */ + ep->txfifo = dev->txfifo; + + /* fifo size */ + if (tmp < UDC_EPIN_NUM) { + ep->fifo_depth = UDC_TXFIFO_SIZE; + ep->in = 1; + } else { + ep->fifo_depth = UDC_RXFIFO_SIZE; + ep->in = 0; + + } + ep->regs = &dev->ep_regs[tmp]; + /* + * ep will be reset only if ep was not enabled before to avoid + * disabling ep interrupts when ENUM interrupt occurs but ep is + * not enabled by gadget driver + */ + if (!ep->desc) { + ep_init(dev->regs, ep); + } + + if (use_dma) { + /* + * ep->dma is not really used, just to indicate that + * DMA is active: remove this + * dma regs = dev control regs + */ + ep->dma = &dev->regs->ctl; + + /* nak OUT endpoints until enable - not for ep0 */ + if (tmp != UDC_EP0IN_IX && tmp != UDC_EP0OUT_IX + && tmp > UDC_EPIN_NUM) { + /* set NAK */ + reg = readl(&dev->ep[tmp].regs->ctl); + reg |= AMD_BIT(UDC_EPCTL_SNAK); + writel(reg, &dev->ep[tmp].regs->ctl); + dev->ep[tmp].naking = 1; + + } + } + } + /* EP0 max packet */ + if (dev->gadget.speed == USB_SPEED_FULL) { + dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE; + dev->ep[UDC_EP0OUT_IX].ep.maxpacket = + UDC_FS_EP0OUT_MAX_PKT_SIZE; + } else if (dev->gadget.speed == USB_SPEED_HIGH) { + dev->ep[UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE; + dev->ep[UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE; + } + + /* + * with suspend bug workaround, ep0 params for gadget driver + * are set at gadget driver bind() call + */ + dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep; + dev->ep[UDC_EP0IN_IX].halted = 0; + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); + + /* init cfg/alt/int */ + dev->cur_config = 0; + dev->cur_intf = 0; + dev->cur_alt = 0; +} + +/* Bringup after Connect event, initial bringup to be ready for ep0 events */ +static void usb_connect(struct udc *dev) +{ + + dev_info(&dev->pdev->dev, "USB Connect\n"); + + dev->connected = 1; + + /* put into initial config */ + udc_basic_init(dev); + + /* enable device setup interrupts */ + udc_enable_dev_setup_interrupts(dev); +} + +/* + * Calls gadget with disconnect event and resets the UDC and makes + * initial bringup to be ready for ep0 events + */ +static void usb_disconnect(struct udc *dev) +{ + + dev_info(&dev->pdev->dev, "USB Disconnect\n"); + + dev->connected = 0; + + /* mask interrupts */ + udc_mask_unused_interrupts(dev); + + /* REVISIT there doesn't seem to be a point to having this + * talk to a tasklet ... do it directly, we already hold + * the spinlock needed to process the disconnect. + */ + + tasklet_schedule(&disconnect_tasklet); +} + +/* Tasklet for disconnect to be outside of interrupt context */ +static void udc_tasklet_disconnect(unsigned long par) +{ + struct udc *dev = (struct udc *)(*((struct udc **) par)); + u32 tmp; + + DBG(dev, "Tasklet disconnect\n"); + spin_lock_irq(&dev->lock); + + if (dev->driver) { + spin_unlock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + + /* empty queues */ + for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { + empty_req_queue(&dev->ep[tmp]); + } + + } + + /* disable ep0 */ + ep_init(dev->regs, + &dev->ep[UDC_EP0IN_IX]); + + + if (!soft_reset_occured) { + /* init controller by soft reset */ + udc_soft_reset(dev); + soft_reset_occured++; + } + + /* re-enable dev interrupts */ + udc_enable_dev_setup_interrupts(dev); + /* back to full speed ? */ + if (use_fullspeed) { + tmp = readl(&dev->regs->cfg); + tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); + writel(tmp, &dev->regs->cfg); + } + + spin_unlock_irq(&dev->lock); +} + +/* Reset the UDC core */ +static void udc_soft_reset(struct udc *dev) +{ + unsigned long flags; + + DBG(dev, "Soft reset\n"); + /* + * reset possible waiting interrupts, because int. + * status is lost after soft reset, + * ep int. status reset + */ + writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts); + /* device int. status reset */ + writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts); + + spin_lock_irqsave(&udc_irq_spinlock, flags); + writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); + readl(&dev->regs->cfg); + spin_unlock_irqrestore(&udc_irq_spinlock, flags); + +} + +/* RDE timer callback to set RDE bit */ +static void udc_timer_function(unsigned long v) +{ + u32 tmp; + + spin_lock_irq(&udc_irq_spinlock); + + if (set_rde > 0) { + /* + * open the fifo if fifo was filled on last timer call + * conditionally + */ + if (set_rde > 1) { + /* set RDE to receive setup data */ + tmp = readl(&udc->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_RDE); + writel(tmp, &udc->regs->ctl); + set_rde = -1; + } else if (readl(&udc->regs->sts) + & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { + /* + * if fifo empty setup polling, do not just + * open the fifo + */ + udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; + if (!stop_timer) { + add_timer(&udc_timer); + } + } else { + /* + * fifo contains data now, setup timer for opening + * the fifo when timer expires to be able to receive + * setup packets, when data packets gets queued by + * gadget layer then timer will forced to expire with + * set_rde=0 (RDE is set in udc_queue()) + */ + set_rde++; + /* debug: lhadmot_timer_start = 221070 */ + udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS; + if (!stop_timer) { + add_timer(&udc_timer); + } + } + + } else + set_rde = -1; /* RDE was set by udc_queue() */ + spin_unlock_irq(&udc_irq_spinlock); + if (stop_timer) + complete(&on_exit); + +} + +/* Handle halt state, used in stall poll timer */ +static void udc_handle_halt_state(struct udc_ep *ep) +{ + u32 tmp; + /* set stall as long not halted */ + if (ep->halted == 1) { + tmp = readl(&ep->regs->ctl); + /* STALL cleared ? */ + if (!(tmp & AMD_BIT(UDC_EPCTL_S))) { + /* + * FIXME: MSC spec requires that stall remains + * even on receivng of CLEAR_FEATURE HALT. So + * we would set STALL again here to be compliant. + * But with current mass storage drivers this does + * not work (would produce endless host retries). + * So we clear halt on CLEAR_FEATURE. + * + DBG(ep->dev, "ep %d: set STALL again\n", ep->num); + tmp |= AMD_BIT(UDC_EPCTL_S); + writel(tmp, &ep->regs->ctl);*/ + + /* clear NAK by writing CNAK */ + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->halted = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } + } +} + +/* Stall timer callback to poll S bit and set it again after */ +static void udc_pollstall_timer_function(unsigned long v) +{ + struct udc_ep *ep; + int halted = 0; + + spin_lock_irq(&udc_stall_spinlock); + /* + * only one IN and OUT endpoints are handled + * IN poll stall + */ + ep = &udc->ep[UDC_EPIN_IX]; + udc_handle_halt_state(ep); + if (ep->halted) + halted = 1; + /* OUT poll stall */ + ep = &udc->ep[UDC_EPOUT_IX]; + udc_handle_halt_state(ep); + if (ep->halted) + halted = 1; + + /* setup timer again when still halted */ + if (!stop_pollstall_timer && halted) { + udc_pollstall_timer.expires = jiffies + + HZ * UDC_POLLSTALL_TIMER_USECONDS + / (1000 * 1000); + add_timer(&udc_pollstall_timer); + } + spin_unlock_irq(&udc_stall_spinlock); + + if (stop_pollstall_timer) + complete(&on_pollstall_exit); +} + +/* Inits endpoint 0 so that SETUP packets are processed */ +static void activate_control_endpoints(struct udc *dev) +{ + u32 tmp; + + DBG(dev, "activate_control_endpoints\n"); + + /* flush fifo */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_F); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + + /* set ep0 directions */ + dev->ep[UDC_EP0IN_IX].in = 1; + dev->ep[UDC_EP0OUT_IX].in = 0; + + /* set buffer size (tx fifo entries) of EP0_IN */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum); + if (dev->gadget.speed == USB_SPEED_FULL) + tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE, + UDC_EPIN_BUFF_SIZE); + else if (dev->gadget.speed == USB_SPEED_HIGH) + tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE, + UDC_EPIN_BUFF_SIZE); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum); + + /* set max packet size of EP0_IN */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt); + if (dev->gadget.speed == USB_SPEED_FULL) + tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE, + UDC_EP_MAX_PKT_SIZE); + else if (dev->gadget.speed == USB_SPEED_HIGH) + tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE, + UDC_EP_MAX_PKT_SIZE); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt); + + /* set max packet size of EP0_OUT */ + tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt); + if (dev->gadget.speed == USB_SPEED_FULL) + tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, + UDC_EP_MAX_PKT_SIZE); + else if (dev->gadget.speed == USB_SPEED_HIGH) + tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, + UDC_EP_MAX_PKT_SIZE); + writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt); + + /* set max packet size of EP0 in UDC CSR */ + tmp = readl(&dev->csr->ne[0]); + if (dev->gadget.speed == USB_SPEED_FULL) + tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, + UDC_CSR_NE_MAX_PKT); + else if (dev->gadget.speed == USB_SPEED_HIGH) + tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, + UDC_CSR_NE_MAX_PKT); + writel(tmp, &dev->csr->ne[0]); + + if (use_dma) { + dev->ep[UDC_EP0OUT_IX].td->status |= + AMD_BIT(UDC_DMA_OUT_STS_L); + /* write dma desc address */ + writel(dev->ep[UDC_EP0OUT_IX].td_stp_dma, + &dev->ep[UDC_EP0OUT_IX].regs->subptr); + writel(dev->ep[UDC_EP0OUT_IX].td_phys, + &dev->ep[UDC_EP0OUT_IX].regs->desptr); + /* stop RDE timer */ + if (timer_pending(&udc_timer)) { + set_rde = 0; + mod_timer(&udc_timer, jiffies - 1); + } + /* stop pollstall timer */ + if (timer_pending(&udc_pollstall_timer)) { + mod_timer(&udc_pollstall_timer, jiffies - 1); + } + /* enable DMA */ + tmp = readl(&dev->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_MODE) + | AMD_BIT(UDC_DEVCTL_RDE) + | AMD_BIT(UDC_DEVCTL_TDE); + if (use_dma_bufferfill_mode) { + tmp |= AMD_BIT(UDC_DEVCTL_BF); + } else if (use_dma_ppb_du) { + tmp |= AMD_BIT(UDC_DEVCTL_DU); + } + writel(tmp, &dev->regs->ctl); + } + + /* clear NAK by writing CNAK for EP0IN */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + dev->ep[UDC_EP0IN_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX); + + /* clear NAK by writing CNAK for EP0OUT */ + tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl); + dev->ep[UDC_EP0OUT_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX); +} + +/* Make endpoint 0 ready for control traffic */ +static int setup_ep0(struct udc *dev) +{ + activate_control_endpoints(dev); + /* enable ep0 interrupts */ + udc_enable_ep0_interrupts(dev); + /* enable device setup interrupts */ + udc_enable_dev_setup_interrupts(dev); + + return 0; +} + +/* Called by gadget driver to register itself */ +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + struct udc *dev = udc; + int retval; + u32 tmp; + + if (!driver || !driver->bind || !driver->setup + || driver->speed != USB_SPEED_HIGH) + return -EINVAL; + if (!dev) + return -ENODEV; + if (dev->driver) + return -EBUSY; + + driver->driver.bus = NULL; + dev->driver = driver; + dev->gadget.dev.driver = &driver->driver; + + retval = driver->bind(&dev->gadget); + + /* Some gadget drivers use both ep0 directions. + * NOTE: to gadget driver, ep0 is just one endpoint... + */ + dev->ep[UDC_EP0OUT_IX].ep.driver_data = + dev->ep[UDC_EP0IN_IX].ep.driver_data; + + if (retval) { + DBG(dev, "binding to %s returning %d\n", + driver->driver.name, retval); + dev->driver = NULL; + dev->gadget.dev.driver = NULL; + return retval; + } + + /* get ready for ep0 traffic */ + setup_ep0(dev); + + /* clear SD */ + tmp = readl(&dev->regs->ctl); + tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD); + writel(tmp, &dev->regs->ctl); + + usb_connect(dev); + + return 0; +} +EXPORT_SYMBOL(usb_gadget_register_driver); + +/* shutdown requests and disconnect from gadget */ +static void +shutdown(struct udc *dev, struct usb_gadget_driver *driver) +__releases(dev->lock) +__acquires(dev->lock) +{ + int tmp; + + /* empty queues and init hardware */ + udc_basic_init(dev); + for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { + empty_req_queue(&dev->ep[tmp]); + } + + if (dev->gadget.speed != USB_SPEED_UNKNOWN) { + spin_unlock(&dev->lock); + driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + } + /* init */ + udc_setup_endpoints(dev); +} + +/* Called by gadget driver to unregister itself */ +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct udc *dev = udc; + unsigned long flags; + u32 tmp; + + if (!dev) + return -ENODEV; + if (!driver || driver != dev->driver || !driver->unbind) + return -EINVAL; + + spin_lock_irqsave(&dev->lock, flags); + udc_mask_unused_interrupts(dev); + shutdown(dev, driver); + spin_unlock_irqrestore(&dev->lock, flags); + + driver->unbind(&dev->gadget); + dev->driver = NULL; + + /* set SD */ + tmp = readl(&dev->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_SD); + writel(tmp, &dev->regs->ctl); + + + DBG(dev, "%s: unregistered\n", driver->driver.name); + + return 0; +} +EXPORT_SYMBOL(usb_gadget_unregister_driver); + + +/* Clear pending NAK bits */ +static void udc_process_cnak_queue(struct udc *dev) +{ + u32 tmp; + u32 reg; + + /* check epin's */ + DBG(dev, "CNAK pending queue processing\n"); + for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) { + if (cnak_pending & (1 << tmp)) { + DBG(dev, "CNAK pending for ep%d\n", tmp); + /* clear NAK by writing CNAK */ + reg = readl(&dev->ep[tmp].regs->ctl); + reg |= AMD_BIT(UDC_EPCTL_CNAK); + writel(reg, &dev->ep[tmp].regs->ctl); + dev->ep[tmp].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num); + } + } + /* ... and ep0out */ + if (cnak_pending & (1 << UDC_EP0OUT_IX)) { + DBG(dev, "CNAK pending for ep%d\n", UDC_EP0OUT_IX); + /* clear NAK by writing CNAK */ + reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); + reg |= AMD_BIT(UDC_EPCTL_CNAK); + writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl); + dev->ep[UDC_EP0OUT_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], + dev->ep[UDC_EP0OUT_IX].num); + } +} + +/* Enabling RX DMA after setup packet */ +static void udc_ep0_set_rde(struct udc *dev) +{ + if (use_dma) { + /* + * only enable RXDMA when no data endpoint enabled + * or data is queued + */ + if (!dev->data_ep_enabled || dev->data_ep_queued) { + udc_set_rde(dev); + } else { + /* + * setup timer for enabling RDE (to not enable + * RXFIFO DMA for data endpoints to early) + */ + if (set_rde != 0 && !timer_pending(&udc_timer)) { + udc_timer.expires = + jiffies + HZ/UDC_RDE_TIMER_DIV; + set_rde = 1; + if (!stop_timer) { + add_timer(&udc_timer); + } + } + } + } +} + + +/* Interrupt handler for data OUT traffic */ +static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix) +{ + irqreturn_t ret_val = IRQ_NONE; + u32 tmp; + struct udc_ep *ep; + struct udc_request *req; + unsigned int count; + struct udc_data_dma *td = NULL; + unsigned dma_done; + + VDBG(dev, "ep%d irq\n", ep_ix); + ep = &dev->ep[ep_ix]; + + tmp = readl(&ep->regs->sts); + if (use_dma) { + /* BNA event ? */ + if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { + DBG(dev, "BNA ep%dout occured - DESPTR = %x \n", + ep->num, readl(&ep->regs->desptr)); + /* clear BNA */ + writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts); + if (!ep->cancel_transfer) + ep->bna_occurred = 1; + else + ep->cancel_transfer = 0; + ret_val = IRQ_HANDLED; + goto finished; + } + } + /* HE event ? */ + if (tmp & AMD_BIT(UDC_EPSTS_HE)) { + dev_err(&dev->pdev->dev, "HE ep%dout occured\n", ep->num); + + /* clear HE */ + writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); + ret_val = IRQ_HANDLED; + goto finished; + } + + if (!list_empty(&ep->queue)) { + + /* next request */ + req = list_entry(ep->queue.next, + struct udc_request, queue); + } else { + req = NULL; + udc_rxfifo_pending = 1; + } + VDBG(dev, "req = %p\n", req); + /* fifo mode */ + if (!use_dma) { + + /* read fifo */ + if (req && udc_rxfifo_read(ep, req)) { + ret_val = IRQ_HANDLED; + + /* finish */ + complete_req(ep, req, 0); + /* next request */ + if (!list_empty(&ep->queue) && !ep->halted) { + req = list_entry(ep->queue.next, + struct udc_request, queue); + } else + req = NULL; + } + + /* DMA */ + } else if (!ep->cancel_transfer && req != NULL) { + ret_val = IRQ_HANDLED; + + /* check for DMA done */ + if (!use_dma_ppb) { + dma_done = AMD_GETBITS(req->td_data->status, + UDC_DMA_OUT_STS_BS); + /* packet per buffer mode - rx bytes */ + } else { + /* + * if BNA occurred then recover desc. from + * BNA dummy desc. + */ + if (ep->bna_occurred) { + VDBG(dev, "Recover desc. from BNA dummy\n"); + memcpy(req->td_data, ep->bna_dummy_req->td_data, + sizeof(struct udc_data_dma)); + ep->bna_occurred = 0; + udc_init_bna_dummy(ep->req); + } + td = udc_get_last_dma_desc(req); + dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS); + } + if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) { + /* buffer fill mode - rx bytes */ + if (!use_dma_ppb) { + /* received number bytes */ + count = AMD_GETBITS(req->td_data->status, + UDC_DMA_OUT_STS_RXBYTES); + VDBG(dev, "rx bytes=%u\n", count); + /* packet per buffer mode - rx bytes */ + } else { + VDBG(dev, "req->td_data=%p\n", req->td_data); + VDBG(dev, "last desc = %p\n", td); + /* received number bytes */ + if (use_dma_ppb_du) { + /* every desc. counts bytes */ + count = udc_get_ppbdu_rxbytes(req); + } else { + /* last desc. counts bytes */ + count = AMD_GETBITS(td->status, + UDC_DMA_OUT_STS_RXBYTES); + if (!count && req->req.length + == UDC_DMA_MAXPACKET) { + /* + * on 64k packets the RXBYTES + * field is zero + */ + count = UDC_DMA_MAXPACKET; + } + } + VDBG(dev, "last desc rx bytes=%u\n", count); + } + + tmp = req->req.length - req->req.actual; + if (count > tmp) { + if ((tmp % ep->ep.maxpacket) != 0) { + DBG(dev, "%s: rx %db, space=%db\n", + ep->ep.name, count, tmp); + req->req.status = -EOVERFLOW; + } + count = tmp; + } + req->req.actual += count; + req->dma_going = 0; + /* complete request */ + complete_req(ep, req, 0); + + /* next request */ + if (!list_empty(&ep->queue) && !ep->halted) { + req = list_entry(ep->queue.next, + struct udc_request, + queue); + /* + * DMA may be already started by udc_queue() + * called by gadget drivers completion + * routine. This happens when queue + * holds one request only. + */ + if (req->dma_going == 0) { + /* next dma */ + if (prep_dma(ep, req, GFP_ATOMIC) != 0) + goto finished; + /* write desc pointer */ + writel(req->td_phys, + &ep->regs->desptr); + req->dma_going = 1; + /* enable DMA */ + udc_set_rde(dev); + } + } else { + /* + * implant BNA dummy descriptor to allow + * RXFIFO opening by RDE + */ + if (ep->bna_dummy_req) { + /* write desc pointer */ + writel(ep->bna_dummy_req->td_phys, + &ep->regs->desptr); + ep->bna_occurred = 0; + } + + /* + * schedule timer for setting RDE if queue + * remains empty to allow ep0 packets pass + * through + */ + if (set_rde != 0 + && !timer_pending(&udc_timer)) { + udc_timer.expires = + jiffies + + HZ*UDC_RDE_TIMER_SECONDS; + set_rde = 1; + if (!stop_timer) { + add_timer(&udc_timer); + } + } + if (ep->num != UDC_EP0OUT_IX) + dev->data_ep_queued = 0; + } + + } else { + /* + * RX DMA must be reenabled for each desc in PPBDU mode + * and must be enabled for PPBNDU mode in case of BNA + */ + udc_set_rde(dev); + } + + } else if (ep->cancel_transfer) { + ret_val = IRQ_HANDLED; + ep->cancel_transfer = 0; + } + + /* check pending CNAKS */ + if (cnak_pending) { + /* CNAk processing when rxfifo empty only */ + if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { + udc_process_cnak_queue(dev); + } + } + + /* clear OUT bits in ep status */ + writel(UDC_EPSTS_OUT_CLEAR, &ep->regs->sts); +finished: + return ret_val; +} + +/* Interrupt handler for data IN traffic */ +static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) +{ + irqreturn_t ret_val = IRQ_NONE; + u32 tmp; + u32 epsts; + struct udc_ep *ep; + struct udc_request *req; + struct udc_data_dma *td; + unsigned dma_done; + unsigned len; + + ep = &dev->ep[ep_ix]; + + epsts = readl(&ep->regs->sts); + if (use_dma) { + /* BNA ? */ + if (epsts & AMD_BIT(UDC_EPSTS_BNA)) { + dev_err(&dev->pdev->dev, + "BNA ep%din occured - DESPTR = %08lx \n", + ep->num, + (unsigned long) readl(&ep->regs->desptr)); + + /* clear BNA */ + writel(epsts, &ep->regs->sts); + ret_val = IRQ_HANDLED; + goto finished; + } + } + /* HE event ? */ + if (epsts & AMD_BIT(UDC_EPSTS_HE)) { + dev_err(&dev->pdev->dev, + "HE ep%dn occured - DESPTR = %08lx \n", + ep->num, (unsigned long) readl(&ep->regs->desptr)); + + /* clear HE */ + writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); + ret_val = IRQ_HANDLED; + goto finished; + } + + /* DMA completion */ + if (epsts & AMD_BIT(UDC_EPSTS_TDC)) { + VDBG(dev, "TDC set- completion\n"); + ret_val = IRQ_HANDLED; + if (!ep->cancel_transfer && !list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, + struct udc_request, queue); + if (req) { + /* + * length bytes transfered + * check dma done of last desc. in PPBDU mode + */ + if (use_dma_ppb_du) { + td = udc_get_last_dma_desc(req); + if (td) { + dma_done = + AMD_GETBITS(td->status, + UDC_DMA_IN_STS_BS); + /* don't care DMA done */ + req->req.actual = + req->req.length; + } + } else { + /* assume all bytes transferred */ + req->req.actual = req->req.length; + } + + if (req->req.actual == req->req.length) { + /* complete req */ + complete_req(ep, req, 0); + req->dma_going = 0; + /* further request available ? */ + if (list_empty(&ep->queue)) { + /* disable interrupt */ + tmp = readl( + &dev->regs->ep_irqmsk); + tmp |= AMD_BIT(ep->num); + writel(tmp, + &dev->regs->ep_irqmsk); + } + + } + } + } + ep->cancel_transfer = 0; + + } + /* + * status reg has IN bit set and TDC not set (if TDC was handled, + * IN must not be handled (UDC defect) ? + */ + if ((epsts & AMD_BIT(UDC_EPSTS_IN)) + && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) { + ret_val = IRQ_HANDLED; + if (!list_empty(&ep->queue)) { + /* next request */ + req = list_entry(ep->queue.next, + struct udc_request, queue); + /* FIFO mode */ + if (!use_dma) { + /* write fifo */ + udc_txfifo_write(ep, &req->req); + len = req->req.length - req->req.actual; + if (len > ep->ep.maxpacket) + len = ep->ep.maxpacket; + req->req.actual += len; + if (req->req.actual == req->req.length + || (len != ep->ep.maxpacket)) { + /* complete req */ + complete_req(ep, req, 0); + } + /* DMA */ + } else if (req && !req->dma_going) { + VDBG(dev, "IN DMA : req=%p req->td_data=%p\n", + req, req->td_data); + if (req->td_data) { + + req->dma_going = 1; + + /* + * unset L bit of first desc. + * for chain + */ + if (use_dma_ppb && req->req.length > + ep->ep.maxpacket) { + req->td_data->status &= + AMD_CLEAR_BIT( + UDC_DMA_IN_STS_L); + } + + /* write desc pointer */ + writel(req->td_phys, &ep->regs->desptr); + + /* set HOST READY */ + req->td_data->status = + AMD_ADDBITS( + req->td_data->status, + UDC_DMA_IN_STS_BS_HOST_READY, + UDC_DMA_IN_STS_BS); + + /* set poll demand bit */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_P); + writel(tmp, &ep->regs->ctl); + } + } + + } + } + /* clear status bits */ + writel(epsts, &ep->regs->sts); + +finished: + return ret_val; + +} + +/* Interrupt handler for Control OUT traffic */ +static irqreturn_t udc_control_out_isr(struct udc *dev) +__releases(dev->lock) +__acquires(dev->lock) +{ + irqreturn_t ret_val = IRQ_NONE; + u32 tmp; + int setup_supported; + u32 count; + int set = 0; + struct udc_ep *ep; + struct udc_ep *ep_tmp; + + ep = &dev->ep[UDC_EP0OUT_IX]; + + /* clear irq */ + writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts); + + tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts); + /* check BNA and clear if set */ + if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { + VDBG(dev, "ep0: BNA set\n"); + writel(AMD_BIT(UDC_EPSTS_BNA), + &dev->ep[UDC_EP0OUT_IX].regs->sts); + ep->bna_occurred = 1; + ret_val = IRQ_HANDLED; + goto finished; + } + + /* type of data: SETUP or DATA 0 bytes */ + tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT); + VDBG(dev, "data_typ = %x\n", tmp); + + /* setup data */ + if (tmp == UDC_EPSTS_OUT_SETUP) { + ret_val = IRQ_HANDLED; + + ep->dev->stall_ep0in = 0; + dev->waiting_zlp_ack_ep0in = 0; + + /* set NAK for EP0_IN */ + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_SNAK); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + dev->ep[UDC_EP0IN_IX].naking = 1; + /* get setup data */ + if (use_dma) { + + /* clear OUT bits in ep status */ + writel(UDC_EPSTS_OUT_CLEAR, + &dev->ep[UDC_EP0OUT_IX].regs->sts); + + setup_data.data[0] = + dev->ep[UDC_EP0OUT_IX].td_stp->data12; + setup_data.data[1] = + dev->ep[UDC_EP0OUT_IX].td_stp->data34; + /* set HOST READY */ + dev->ep[UDC_EP0OUT_IX].td_stp->status = + UDC_DMA_STP_STS_BS_HOST_READY; + } else { + /* read fifo */ + udc_rxfifo_read_dwords(dev, setup_data.data, 2); + } + + /* determine direction of control data */ + if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) { + dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IX].ep; + /* enable RDE */ + udc_ep0_set_rde(dev); + set = 0; + } else { + dev->gadget.ep0 = &dev->ep[UDC_EP0OUT_IX].ep; + /* + * implant BNA dummy descriptor to allow RXFIFO opening + * by RDE + */ + if (ep->bna_dummy_req) { + /* write desc pointer */ + writel(ep->bna_dummy_req->td_phys, + &dev->ep[UDC_EP0OUT_IX].regs->desptr); + ep->bna_occurred = 0; + } + + set = 1; + dev->ep[UDC_EP0OUT_IX].naking = 1; + /* + * setup timer for enabling RDE (to not enable + * RXFIFO DMA for data to early) + */ + set_rde = 1; + if (!timer_pending(&udc_timer)) { + udc_timer.expires = jiffies + + HZ/UDC_RDE_TIMER_DIV; + if (!stop_timer) { + add_timer(&udc_timer); + } + } + } + + /* + * mass storage reset must be processed here because + * next packet may be a CLEAR_FEATURE HALT which would not + * clear the stall bit when no STALL handshake was received + * before (autostall can cause this) + */ + if (setup_data.data[0] == UDC_MSCRES_DWORD0 + && setup_data.data[1] == UDC_MSCRES_DWORD1) { + DBG(dev, "MSC Reset\n"); + /* + * clear stall bits + * only one IN and OUT endpoints are handled + */ + ep_tmp = &udc->ep[UDC_EPIN_IX]; + udc_set_halt(&ep_tmp->ep, 0); + ep_tmp = &udc->ep[UDC_EPOUT_IX]; + udc_set_halt(&ep_tmp->ep, 0); + } + + /* call gadget with setup data received */ + spin_unlock(&dev->lock); + setup_supported = dev->driver->setup(&dev->gadget, + &setup_data.request); + spin_lock(&dev->lock); + + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + /* ep0 in returns data (not zlp) on IN phase */ + if (setup_supported >= 0 && setup_supported < + UDC_EP0IN_MAXPACKET) { + /* clear NAK by writing CNAK in EP0_IN */ + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + dev->ep[UDC_EP0IN_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX); + + /* if unsupported request then stall */ + } else if (setup_supported < 0) { + tmp |= AMD_BIT(UDC_EPCTL_S); + writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); + } else + dev->waiting_zlp_ack_ep0in = 1; + + + /* clear NAK by writing CNAK in EP0_OUT */ + if (!set) { + tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl); + dev->ep[UDC_EP0OUT_IX].naking = 0; + UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX); + } + + if (!use_dma) { + /* clear OUT bits in ep status */ + writel(UDC_EPSTS_OUT_CLEAR, + &dev->ep[UDC_EP0OUT_IX].regs->sts); + } + + /* data packet 0 bytes */ + } else if (tmp == UDC_EPSTS_OUT_DATA) { + /* clear OUT bits in ep status */ + writel(UDC_EPSTS_OUT_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts); + + /* get setup data: only 0 packet */ + if (use_dma) { + /* no req if 0 packet, just reactivate */ + if (list_empty(&dev->ep[UDC_EP0OUT_IX].queue)) { + VDBG(dev, "ZLP\n"); + + /* set HOST READY */ + dev->ep[UDC_EP0OUT_IX].td->status = + AMD_ADDBITS( + dev->ep[UDC_EP0OUT_IX].td->status, + UDC_DMA_OUT_STS_BS_HOST_READY, + UDC_DMA_OUT_STS_BS); + /* enable RDE */ + udc_ep0_set_rde(dev); + ret_val = IRQ_HANDLED; + + } else { + /* control write */ + ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX); + /* re-program desc. pointer for possible ZLPs */ + writel(dev->ep[UDC_EP0OUT_IX].td_phys, + &dev->ep[UDC_EP0OUT_IX].regs->desptr); + /* enable RDE */ + udc_ep0_set_rde(dev); + } + } else { + + /* received number bytes */ + count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts); + count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE); + /* out data for fifo mode not working */ + count = 0; + + /* 0 packet or real data ? */ + if (count != 0) { + ret_val |= udc_data_out_isr(dev, UDC_EP0OUT_IX); + } else { + /* dummy read confirm */ + readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm); + ret_val = IRQ_HANDLED; + } + } + } + + /* check pending CNAKS */ + if (cnak_pending) { + /* CNAk processing when rxfifo empty only */ + if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { + udc_process_cnak_queue(dev); + } + } + +finished: + return ret_val; +} + +/* Interrupt handler for Control IN traffic */ +static irqreturn_t udc_control_in_isr(struct udc *dev) +{ + irqreturn_t ret_val = IRQ_NONE; + u32 tmp; + struct udc_ep *ep; + struct udc_request *req; + unsigned len; + + ep = &dev->ep[UDC_EP0IN_IX]; + + /* clear irq */ + writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts); + + tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->sts); + /* DMA completion */ + if (tmp & AMD_BIT(UDC_EPSTS_TDC)) { + VDBG(dev, "isr: TDC clear \n"); + ret_val = IRQ_HANDLED; + + /* clear TDC bit */ + writel(AMD_BIT(UDC_EPSTS_TDC), + &dev->ep[UDC_EP0IN_IX].regs->sts); + + /* status reg has IN bit set ? */ + } else if (tmp & AMD_BIT(UDC_EPSTS_IN)) { + ret_val = IRQ_HANDLED; + + if (ep->dma) { + /* clear IN bit */ + writel(AMD_BIT(UDC_EPSTS_IN), + &dev->ep[UDC_EP0IN_IX].regs->sts); + } + if (dev->stall_ep0in) { + DBG(dev, "stall ep0in\n"); + /* halt ep0in */ + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_S); + writel(tmp, &ep->regs->ctl); + } else { + if (!list_empty(&ep->queue)) { + /* next request */ + req = list_entry(ep->queue.next, + struct udc_request, queue); + + if (ep->dma) { + /* write desc pointer */ + writel(req->td_phys, &ep->regs->desptr); + /* set HOST READY */ + req->td_data->status = + AMD_ADDBITS( + req->td_data->status, + UDC_DMA_STP_STS_BS_HOST_READY, + UDC_DMA_STP_STS_BS); + + /* set poll demand bit */ + tmp = + readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_P); + writel(tmp, + &dev->ep[UDC_EP0IN_IX].regs->ctl); + + /* all bytes will be transferred */ + req->req.actual = req->req.length; + + /* complete req */ + complete_req(ep, req, 0); + + } else { + /* write fifo */ + udc_txfifo_write(ep, &req->req); + + /* lengh bytes transfered */ + len = req->req.length - req->req.actual; + if (len > ep->ep.maxpacket) + len = ep->ep.maxpacket; + + req->req.actual += len; + if (req->req.actual == req->req.length + || (len != ep->ep.maxpacket)) { + /* complete req */ + complete_req(ep, req, 0); + } + } + + } + } + ep->halted = 0; + dev->stall_ep0in = 0; + if (!ep->dma) { + /* clear IN bit */ + writel(AMD_BIT(UDC_EPSTS_IN), + &dev->ep[UDC_EP0IN_IX].regs->sts); + } + } + + return ret_val; +} + + +/* Interrupt handler for global device events */ +static irqreturn_t udc_dev_isr(struct udc *dev, u32 dev_irq) +__releases(dev->lock) +__acquires(dev->lock) +{ + irqreturn_t ret_val = IRQ_NONE; + u32 tmp; + u32 cfg; + struct udc_ep *ep; + u16 i; + u8 udc_csr_epix; + + /* SET_CONFIG irq ? */ + if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) { + ret_val = IRQ_HANDLED; + + /* read config value */ + tmp = readl(&dev->regs->sts); + cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG); + DBG(dev, "SET_CONFIG interrupt: config=%d\n", cfg); + dev->cur_config = cfg; + dev->set_cfg_not_acked = 1; + + /* make usb request for gadget driver */ + memset(&setup_data, 0 , sizeof(union udc_setup_data)); + setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION; + setup_data.request.wValue = dev->cur_config; + + /* programm the NE registers */ + for (i = 0; i < UDC_EP_NUM; i++) { + ep = &dev->ep[i]; + if (ep->in) { + + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num; + + + /* OUT ep */ + } else { + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; + } + + tmp = readl(&dev->csr->ne[udc_csr_epix]); + /* ep cfg */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, + UDC_CSR_NE_CFG); + /* write reg */ + writel(tmp, &dev->csr->ne[udc_csr_epix]); + + /* clear stall bits */ + ep->halted = 0; + tmp = readl(&ep->regs->ctl); + tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); + writel(tmp, &ep->regs->ctl); + } + /* call gadget zero with setup data received */ + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &setup_data.request); + spin_lock(&dev->lock); + + } /* SET_INTERFACE ? */ + if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) { + ret_val = IRQ_HANDLED; + + dev->set_cfg_not_acked = 1; + /* read interface and alt setting values */ + tmp = readl(&dev->regs->sts); + dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT); + dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF); + + /* make usb request for gadget driver */ + memset(&setup_data, 0 , sizeof(union udc_setup_data)); + setup_data.request.bRequest = USB_REQ_SET_INTERFACE; + setup_data.request.bRequestType = USB_RECIP_INTERFACE; + setup_data.request.wValue = dev->cur_alt; + setup_data.request.wIndex = dev->cur_intf; + + DBG(dev, "SET_INTERFACE interrupt: alt=%d intf=%d\n", + dev->cur_alt, dev->cur_intf); + + /* programm the NE registers */ + for (i = 0; i < UDC_EP_NUM; i++) { + ep = &dev->ep[i]; + if (ep->in) { + + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num; + + + /* OUT ep */ + } else { + /* ep ix in UDC CSR register space */ + udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; + } + + /* UDC CSR reg */ + /* set ep values */ + tmp = readl(&dev->csr->ne[udc_csr_epix]); + /* ep interface */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, + UDC_CSR_NE_INTF); + /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */ + /* ep alt */ + tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, + UDC_CSR_NE_ALT); + /* write reg */ + writel(tmp, &dev->csr->ne[udc_csr_epix]); + + /* clear stall bits */ + ep->halted = 0; + tmp = readl(&ep->regs->ctl); + tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); + writel(tmp, &ep->regs->ctl); + } + + /* call gadget zero with setup data received */ + spin_unlock(&dev->lock); + tmp = dev->driver->setup(&dev->gadget, &setup_data.request); + spin_lock(&dev->lock); + + } /* USB reset */ + if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) { + DBG(dev, "USB Reset interrupt\n"); + ret_val = IRQ_HANDLED; + + /* allow soft reset when suspend occurs */ + soft_reset_occured = 0; + + dev->waiting_zlp_ack_ep0in = 0; + dev->set_cfg_not_acked = 0; + + /* mask not needed interrupts */ + udc_mask_unused_interrupts(dev); + + /* call gadget to resume and reset configs etc. */ + spin_unlock(&dev->lock); + if (dev->sys_suspended && dev->driver->resume) { + dev->driver->resume(&dev->gadget); + dev->sys_suspended = 0; + } + dev->driver->disconnect(&dev->gadget); + spin_lock(&dev->lock); + + /* disable ep0 to empty req queue */ + empty_req_queue(&dev->ep[UDC_EP0IN_IX]); + ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]); + + /* soft reset when rxfifo not empty */ + tmp = readl(&dev->regs->sts); + if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) + && !soft_reset_after_usbreset_occured) { + udc_soft_reset(dev); + soft_reset_after_usbreset_occured++; + } + + /* + * DMA reset to kill potential old DMA hw hang, + * POLL bit is already reset by ep_init() through + * disconnect() + */ + DBG(dev, "DMA machine reset\n"); + tmp = readl(&dev->regs->cfg); + writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg); + writel(tmp, &dev->regs->cfg); + + /* put into initial config */ + udc_basic_init(dev); + + /* enable device setup interrupts */ + udc_enable_dev_setup_interrupts(dev); + + /* enable suspend interrupt */ + tmp = readl(&dev->regs->irqmsk); + tmp &= AMD_UNMASK_BIT(UDC_DEVINT_US); + writel(tmp, &dev->regs->irqmsk); + + } /* USB suspend */ + if (dev_irq & AMD_BIT(UDC_DEVINT_US)) { + DBG(dev, "USB Suspend interrupt\n"); + ret_val = IRQ_HANDLED; + if (dev->driver->suspend) { + spin_unlock(&dev->lock); + dev->sys_suspended = 1; + dev->driver->suspend(&dev->gadget); + spin_lock(&dev->lock); + } + } /* new speed ? */ + if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) { + DBG(dev, "ENUM interrupt\n"); + ret_val = IRQ_HANDLED; + soft_reset_after_usbreset_occured = 0; + + /* disable ep0 to empty req queue */ + empty_req_queue(&dev->ep[UDC_EP0IN_IX]); + ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]); + + /* link up all endpoints */ + udc_setup_endpoints(dev); + if (dev->gadget.speed == USB_SPEED_HIGH) { + dev_info(&dev->pdev->dev, "Connect: speed = %s\n", + "high"); + } else if (dev->gadget.speed == USB_SPEED_FULL) { + dev_info(&dev->pdev->dev, "Connect: speed = %s\n", + "full"); + } + + /* init ep 0 */ + activate_control_endpoints(dev); + + /* enable ep0 interrupts */ + udc_enable_ep0_interrupts(dev); + } + /* session valid change interrupt */ + if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) { + DBG(dev, "USB SVC interrupt\n"); + ret_val = IRQ_HANDLED; + + /* check that session is not valid to detect disconnect */ + tmp = readl(&dev->regs->sts); + if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) { + /* disable suspend interrupt */ + tmp = readl(&dev->regs->irqmsk); + tmp |= AMD_BIT(UDC_DEVINT_US); + writel(tmp, &dev->regs->irqmsk); + DBG(dev, "USB Disconnect (session valid low)\n"); + /* cleanup on disconnect */ + usb_disconnect(udc); + } + + } + + return ret_val; +} + +/* Interrupt Service Routine, see Linux Kernel Doc for parameters */ +static irqreturn_t udc_irq(int irq, void *pdev) +{ + struct udc *dev = pdev; + u32 reg; + u16 i; + u32 ep_irq; + irqreturn_t ret_val = IRQ_NONE; + + spin_lock(&dev->lock); + + /* check for ep irq */ + reg = readl(&dev->regs->ep_irqsts); + if (reg) { + if (reg & AMD_BIT(UDC_EPINT_OUT_EP0)) + ret_val |= udc_control_out_isr(dev); + if (reg & AMD_BIT(UDC_EPINT_IN_EP0)) + ret_val |= udc_control_in_isr(dev); + + /* + * data endpoint + * iterate ep's + */ + for (i = 1; i < UDC_EP_NUM; i++) { + ep_irq = 1 << i; + if (!(reg & ep_irq) || i == UDC_EPINT_OUT_EP0) + continue; + + /* clear irq status */ + writel(ep_irq, &dev->regs->ep_irqsts); + + /* irq for out ep ? */ + if (i > UDC_EPIN_NUM) + ret_val |= udc_data_out_isr(dev, i); + else + ret_val |= udc_data_in_isr(dev, i); + } + + } + + + /* check for dev irq */ + reg = readl(&dev->regs->irqsts); + if (reg) { + /* clear irq */ + writel(reg, &dev->regs->irqsts); + ret_val |= udc_dev_isr(dev, reg); + } + + + spin_unlock(&dev->lock); + return ret_val; +} + +/* Tears down device */ +static void gadget_release(struct device *pdev) +{ + struct amd5536udc *dev = dev_get_drvdata(pdev); + kfree(dev); +} + +/* Cleanup on device remove */ +static void udc_remove(struct udc *dev) +{ + /* remove timer */ + stop_timer++; + if (timer_pending(&udc_timer)) + wait_for_completion(&on_exit); + if (udc_timer.data) + del_timer_sync(&udc_timer); + /* remove pollstall timer */ + stop_pollstall_timer++; + if (timer_pending(&udc_pollstall_timer)) + wait_for_completion(&on_pollstall_exit); + if (udc_pollstall_timer.data) + del_timer_sync(&udc_pollstall_timer); + udc = NULL; +} + +/* Reset all pci context */ +static void udc_pci_remove(struct pci_dev *pdev) +{ + struct udc *dev; + + dev = pci_get_drvdata(pdev); + + /* gadget driver must not be registered */ + BUG_ON(dev->driver != NULL); + + /* dma pool cleanup */ + if (dev->data_requests) + pci_pool_destroy(dev->data_requests); + + if (dev->stp_requests) { + /* cleanup DMA desc's for ep0in */ + pci_pool_free(dev->stp_requests, + dev->ep[UDC_EP0OUT_IX].td_stp, + dev->ep[UDC_EP0OUT_IX].td_stp_dma); + pci_pool_free(dev->stp_requests, + dev->ep[UDC_EP0OUT_IX].td, + dev->ep[UDC_EP0OUT_IX].td_phys); + + pci_pool_destroy(dev->stp_requests); + } + + /* reset controller */ + writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); + if (dev->irq_registered) + free_irq(pdev->irq, dev); + if (dev->regs) + iounmap(dev->regs); + if (dev->mem_region) + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (dev->active) + pci_disable_device(pdev); + + device_unregister(&dev->gadget.dev); + pci_set_drvdata(pdev, NULL); + + udc_remove(dev); +} + +/* create dma pools on init */ +static int init_dma_pools(struct udc *dev) +{ + struct udc_stp_dma *td_stp; + struct udc_data_dma *td_data; + int retval; + + /* consistent DMA mode setting ? */ + if (use_dma_ppb) { + use_dma_bufferfill_mode = 0; + } else { + use_dma_ppb_du = 0; + use_dma_bufferfill_mode = 1; + } + + /* DMA setup */ + dev->data_requests = dma_pool_create("data_requests", NULL, + sizeof(struct udc_data_dma), 0, 0); + if (!dev->data_requests) { + DBG(dev, "can't get request data pool\n"); + retval = -ENOMEM; + goto finished; + } + + /* EP0 in dma regs = dev control regs */ + dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl; + + /* dma desc for setup data */ + dev->stp_requests = dma_pool_create("setup requests", NULL, + sizeof(struct udc_stp_dma), 0, 0); + if (!dev->stp_requests) { + DBG(dev, "can't get stp request pool\n"); + retval = -ENOMEM; + goto finished; + } + /* setup */ + td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL, + &dev->ep[UDC_EP0OUT_IX].td_stp_dma); + if (td_stp == NULL) { + retval = -ENOMEM; + goto finished; + } + dev->ep[UDC_EP0OUT_IX].td_stp = td_stp; + + /* data: 0 packets !? */ + td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL, + &dev->ep[UDC_EP0OUT_IX].td_phys); + if (td_data == NULL) { + retval = -ENOMEM; + goto finished; + } + dev->ep[UDC_EP0OUT_IX].td = td_data; + return 0; + +finished: + return retval; +} + +/* Called by pci bus driver to init pci context */ +static int udc_pci_probe( + struct pci_dev *pdev, + const struct pci_device_id *id +) +{ + struct udc *dev; + unsigned long resource; + unsigned long len; + int retval = 0; + + /* one udc only */ + if (udc) { + dev_dbg(&pdev->dev, "already probed\n"); + return -EBUSY; + } + + /* init */ + dev = kzalloc(sizeof(struct udc), GFP_KERNEL); + if (!dev) { + retval = -ENOMEM; + goto finished; + } + memset(dev, 0, sizeof(struct udc)); + + /* pci setup */ + if (pci_enable_device(pdev) < 0) { + retval = -ENODEV; + goto finished; + } + dev->active = 1; + + /* PCI resource allocation */ + resource = pci_resource_start(pdev, 0); + len = pci_resource_len(pdev, 0); + + if (!request_mem_region(resource, len, name)) { + dev_dbg(&pdev->dev, "pci device used already\n"); + retval = -EBUSY; + goto finished; + } + dev->mem_region = 1; + + dev->virt_addr = ioremap_nocache(resource, len); + if (dev->virt_addr == NULL) { + dev_dbg(&pdev->dev, "start address cannot be mapped\n"); + retval = -EFAULT; + goto finished; + } + + if (!pdev->irq) { + dev_err(&dev->pdev->dev, "irq not set\n"); + retval = -ENODEV; + goto finished; + } + + if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { + dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); + retval = -EBUSY; + goto finished; + } + dev->irq_registered = 1; + + pci_set_drvdata(pdev, dev); + + /* chip revision */ + dev->chiprev = 0; + + pci_set_master(pdev); + pci_set_mwi(pdev); + + /* chip rev for Hs AMD5536 */ + pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) &dev->chiprev); + /* init dma pools */ + if (use_dma) { + retval = init_dma_pools(dev); + if (retval != 0) + goto finished; + } + + dev->phys_addr = resource; + dev->irq = pdev->irq; + dev->pdev = pdev; + dev->gadget.dev.parent = &pdev->dev; + dev->gadget.dev.dma_mask = pdev->dev.dma_mask; + + /* general probing */ + if (udc_probe(dev) == 0) + return 0; + +finished: + if (dev) + udc_pci_remove(pdev); + return retval; +} + +/* general probe */ +static int udc_probe(struct udc *dev) +{ + char tmp[128]; + u32 reg; + int retval; + + /* mark timer as not initialized */ + udc_timer.data = 0; + udc_pollstall_timer.data = 0; + + /* device struct setup */ + spin_lock_init(&dev->lock); + dev->gadget.ops = &udc_ops; + + strcpy(dev->gadget.dev.bus_id, "gadget"); + dev->gadget.dev.release = gadget_release; + dev->gadget.name = name; + dev->gadget.name = name; + dev->gadget.is_dualspeed = 1; + + /* udc csr registers base */ + dev->csr = dev->virt_addr + UDC_CSR_ADDR; + /* dev registers base */ + dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR; + /* ep registers base */ + dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR; + /* fifo's base */ + dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR); + dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); + + /* init registers, interrupts, ... */ + startup_registers(dev); + + dev_info(&dev->pdev->dev, "%s\n", mod_desc); + + snprintf(tmp, sizeof tmp, "%d", dev->irq); + dev_info(&dev->pdev->dev, + "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n", + tmp, dev->phys_addr, dev->chiprev, + (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1"); + strcpy(tmp, UDC_DRIVER_VERSION_STRING); + if (dev->chiprev == UDC_HSA0_REV) { + dev_err(&dev->pdev->dev, "chip revision is A0; too old\n"); + retval = -ENODEV; + goto finished; + } + dev_info(&dev->pdev->dev, + "driver version: %s(for Geode5536 B1)\n", tmp); + udc = dev; + + retval = device_register(&dev->gadget.dev); + if (retval) + goto finished; + + /* timer init */ + init_timer(&udc_timer); + udc_timer.function = udc_timer_function; + udc_timer.data = 1; + /* timer pollstall init */ + init_timer(&udc_pollstall_timer); + udc_pollstall_timer.function = udc_pollstall_timer_function; + udc_pollstall_timer.data = 1; + + /* set SD */ + reg = readl(&dev->regs->ctl); + reg |= AMD_BIT(UDC_DEVCTL_SD); + writel(reg, &dev->regs->ctl); + + /* print dev register info */ + print_regs(dev); + + return 0; + +finished: + return retval; +} + +/* Initiates a remote wakeup */ +static int udc_remote_wakeup(struct udc *dev) +{ + unsigned long flags; + u32 tmp; + + DBG(dev, "UDC initiates remote wakeup\n"); + + spin_lock_irqsave(&dev->lock, flags); + + tmp = readl(&dev->regs->ctl); + tmp |= AMD_BIT(UDC_DEVCTL_RES); + writel(tmp, &dev->regs->ctl); + tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES); + writel(tmp, &dev->regs->ctl); + + spin_unlock_irqrestore(&dev->lock, flags); + return 0; +} + +/* PCI device parameters */ +static const struct pci_device_id pci_id[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), + .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, + .class_mask = 0xffffffff, + }, + {}, +}; +MODULE_DEVICE_TABLE(pci, pci_id); + +/* PCI functions */ +static struct pci_driver udc_pci_driver = { + .name = (char *) name, + .id_table = pci_id, + .probe = udc_pci_probe, + .remove = udc_pci_remove, +}; + +/* Inits driver */ +static int __init init(void) +{ + return pci_register_driver(&udc_pci_driver); +} +module_init(init); + +/* Cleans driver */ +static void __exit cleanup(void) +{ + pci_unregister_driver(&udc_pci_driver); +} +module_exit(cleanup); + +MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); +MODULE_AUTHOR("Thomas Dahlmann"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h new file mode 100644 index 000000000000..4bbabbbfc93f --- /dev/null +++ b/drivers/usb/gadget/amd5536udc.h @@ -0,0 +1,626 @@ +/* + * amd5536.h -- header for AMD 5536 UDC high/full speed USB device controller + * + * Copyright (C) 2007 AMD (http://www.amd.com) + * Author: Thomas Dahlmann + * + * 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 AMD5536UDC_H +#define AMD5536UDC_H + +/* various constants */ +#define UDC_RDE_TIMER_SECONDS 1 +#define UDC_RDE_TIMER_DIV 10 +#define UDC_POLLSTALL_TIMER_USECONDS 500 + +/* Hs AMD5536 chip rev. */ +#define UDC_HSA0_REV 1 +#define UDC_HSB1_REV 2 + +/* + * SETUP usb commands + * needed, because some SETUP's are handled in hw, but must be passed to + * gadget driver above + * SET_CONFIG + */ +#define UDC_SETCONFIG_DWORD0 0x00000900 +#define UDC_SETCONFIG_DWORD0_VALUE_MASK 0xffff0000 +#define UDC_SETCONFIG_DWORD0_VALUE_OFS 16 + +#define UDC_SETCONFIG_DWORD1 0x00000000 + +/* SET_INTERFACE */ +#define UDC_SETINTF_DWORD0 0x00000b00 +#define UDC_SETINTF_DWORD0_ALT_MASK 0xffff0000 +#define UDC_SETINTF_DWORD0_ALT_OFS 16 + +#define UDC_SETINTF_DWORD1 0x00000000 +#define UDC_SETINTF_DWORD1_INTF_MASK 0x0000ffff +#define UDC_SETINTF_DWORD1_INTF_OFS 0 + +/* Mass storage reset */ +#define UDC_MSCRES_DWORD0 0x0000ff21 +#define UDC_MSCRES_DWORD1 0x00000000 + +/* Global CSR's -------------------------------------------------------------*/ +#define UDC_CSR_ADDR 0x500 + +/* EP NE bits */ +/* EP number */ +#define UDC_CSR_NE_NUM_MASK 0x0000000f +#define UDC_CSR_NE_NUM_OFS 0 +/* EP direction */ +#define UDC_CSR_NE_DIR_MASK 0x00000010 +#define UDC_CSR_NE_DIR_OFS 4 +/* EP type */ +#define UDC_CSR_NE_TYPE_MASK 0x00000060 +#define UDC_CSR_NE_TYPE_OFS 5 +/* EP config number */ +#define UDC_CSR_NE_CFG_MASK 0x00000780 +#define UDC_CSR_NE_CFG_OFS 7 +/* EP interface number */ +#define UDC_CSR_NE_INTF_MASK 0x00007800 +#define UDC_CSR_NE_INTF_OFS 11 +/* EP alt setting */ +#define UDC_CSR_NE_ALT_MASK 0x00078000 +#define UDC_CSR_NE_ALT_OFS 15 + +/* max pkt */ +#define UDC_CSR_NE_MAX_PKT_MASK 0x3ff80000 +#define UDC_CSR_NE_MAX_PKT_OFS 19 + +/* Device Config Register ---------------------------------------------------*/ +#define UDC_DEVCFG_ADDR 0x400 + +#define UDC_DEVCFG_SOFTRESET 31 +#define UDC_DEVCFG_HNPSFEN 30 +#define UDC_DEVCFG_DMARST 29 +#define UDC_DEVCFG_SET_DESC 18 +#define UDC_DEVCFG_CSR_PRG 17 +#define UDC_DEVCFG_STATUS 7 +#define UDC_DEVCFG_DIR 6 +#define UDC_DEVCFG_PI 5 +#define UDC_DEVCFG_SS 4 +#define UDC_DEVCFG_SP 3 +#define UDC_DEVCFG_RWKP 2 + +#define UDC_DEVCFG_SPD_MASK 0x3 +#define UDC_DEVCFG_SPD_OFS 0 +#define UDC_DEVCFG_SPD_HS 0x0 +#define UDC_DEVCFG_SPD_FS 0x1 +#define UDC_DEVCFG_SPD_LS 0x2 +/*#define UDC_DEVCFG_SPD_FS 0x3*/ + + +/* Device Control Register --------------------------------------------------*/ +#define UDC_DEVCTL_ADDR 0x404 + +#define UDC_DEVCTL_THLEN_MASK 0xff000000 +#define UDC_DEVCTL_THLEN_OFS 24 + +#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000 +#define UDC_DEVCTL_BRLEN_OFS 16 + +#define UDC_DEVCTL_CSR_DONE 13 +#define UDC_DEVCTL_DEVNAK 12 +#define UDC_DEVCTL_SD 10 +#define UDC_DEVCTL_MODE 9 +#define UDC_DEVCTL_BREN 8 +#define UDC_DEVCTL_THE 7 +#define UDC_DEVCTL_BF 6 +#define UDC_DEVCTL_BE 5 +#define UDC_DEVCTL_DU 4 +#define UDC_DEVCTL_TDE 3 +#define UDC_DEVCTL_RDE 2 +#define UDC_DEVCTL_RES 0 + + +/* Device Status Register ---------------------------------------------------*/ +#define UDC_DEVSTS_ADDR 0x408 + +#define UDC_DEVSTS_TS_MASK 0xfffc0000 +#define UDC_DEVSTS_TS_OFS 18 + +#define UDC_DEVSTS_SESSVLD 17 +#define UDC_DEVSTS_PHY_ERROR 16 +#define UDC_DEVSTS_RXFIFO_EMPTY 15 + +#define UDC_DEVSTS_ENUM_SPEED_MASK 0x00006000 +#define UDC_DEVSTS_ENUM_SPEED_OFS 13 +#define UDC_DEVSTS_ENUM_SPEED_FULL 1 +#define UDC_DEVSTS_ENUM_SPEED_HIGH 0 + +#define UDC_DEVSTS_SUSP 12 + +#define UDC_DEVSTS_ALT_MASK 0x00000f00 +#define UDC_DEVSTS_ALT_OFS 8 + +#define UDC_DEVSTS_INTF_MASK 0x000000f0 +#define UDC_DEVSTS_INTF_OFS 4 + +#define UDC_DEVSTS_CFG_MASK 0x0000000f +#define UDC_DEVSTS_CFG_OFS 0 + + +/* Device Interrupt Register ------------------------------------------------*/ +#define UDC_DEVINT_ADDR 0x40c + +#define UDC_DEVINT_SVC 7 +#define UDC_DEVINT_ENUM 6 +#define UDC_DEVINT_SOF 5 +#define UDC_DEVINT_US 4 +#define UDC_DEVINT_UR 3 +#define UDC_DEVINT_ES 2 +#define UDC_DEVINT_SI 1 +#define UDC_DEVINT_SC 0 + +/* Device Interrupt Mask Register -------------------------------------------*/ +#define UDC_DEVINT_MSK_ADDR 0x410 + +#define UDC_DEVINT_MSK 0x7f + +/* Endpoint Interrupt Register ----------------------------------------------*/ +#define UDC_EPINT_ADDR 0x414 + +#define UDC_EPINT_OUT_MASK 0xffff0000 +#define UDC_EPINT_OUT_OFS 16 +#define UDC_EPINT_IN_MASK 0x0000ffff +#define UDC_EPINT_IN_OFS 0 + +#define UDC_EPINT_IN_EP0 0 +#define UDC_EPINT_IN_EP1 1 +#define UDC_EPINT_IN_EP2 2 +#define UDC_EPINT_IN_EP3 3 +#define UDC_EPINT_OUT_EP0 16 +#define UDC_EPINT_OUT_EP1 17 +#define UDC_EPINT_OUT_EP2 18 +#define UDC_EPINT_OUT_EP3 19 + +#define UDC_EPINT_EP0_ENABLE_MSK 0x001e001e + +/* Endpoint Interrupt Mask Register -----------------------------------------*/ +#define UDC_EPINT_MSK_ADDR 0x418 + +#define UDC_EPINT_OUT_MSK_MASK 0xffff0000 +#define UDC_EPINT_OUT_MSK_OFS 16 +#define UDC_EPINT_IN_MSK_MASK 0x0000ffff +#define UDC_EPINT_IN_MSK_OFS 0 + +#define UDC_EPINT_MSK_DISABLE_ALL 0xffffffff +/* mask non-EP0 endpoints */ +#define UDC_EPDATAINT_MSK_DISABLE 0xfffefffe +/* mask all dev interrupts */ +#define UDC_DEV_MSK_DISABLE 0x7f + +/* Endpoint-specific CSR's --------------------------------------------------*/ +#define UDC_EPREGS_ADDR 0x0 +#define UDC_EPIN_REGS_ADDR 0x0 +#define UDC_EPOUT_REGS_ADDR 0x200 + +#define UDC_EPCTL_ADDR 0x0 + +#define UDC_EPCTL_RRDY 9 +#define UDC_EPCTL_CNAK 8 +#define UDC_EPCTL_SNAK 7 +#define UDC_EPCTL_NAK 6 + +#define UDC_EPCTL_ET_MASK 0x00000030 +#define UDC_EPCTL_ET_OFS 4 +#define UDC_EPCTL_ET_CONTROL 0 +#define UDC_EPCTL_ET_ISO 1 +#define UDC_EPCTL_ET_BULK 2 +#define UDC_EPCTL_ET_INTERRUPT 3 + +#define UDC_EPCTL_P 3 +#define UDC_EPCTL_SN 2 +#define UDC_EPCTL_F 1 +#define UDC_EPCTL_S 0 + +/* Endpoint Status Registers ------------------------------------------------*/ +#define UDC_EPSTS_ADDR 0x4 + +#define UDC_EPSTS_RX_PKT_SIZE_MASK 0x007ff800 +#define UDC_EPSTS_RX_PKT_SIZE_OFS 11 + +#define UDC_EPSTS_TDC 10 +#define UDC_EPSTS_HE 9 +#define UDC_EPSTS_BNA 7 +#define UDC_EPSTS_IN 6 + +#define UDC_EPSTS_OUT_MASK 0x00000030 +#define UDC_EPSTS_OUT_OFS 4 +#define UDC_EPSTS_OUT_DATA 1 +#define UDC_EPSTS_OUT_DATA_CLEAR 0x10 +#define UDC_EPSTS_OUT_SETUP 2 +#define UDC_EPSTS_OUT_SETUP_CLEAR 0x20 +#define UDC_EPSTS_OUT_CLEAR 0x30 + +/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/ +#define UDC_EPIN_BUFF_SIZE_ADDR 0x8 +#define UDC_EPOUT_FRAME_NUMBER_ADDR 0x8 + +#define UDC_EPIN_BUFF_SIZE_MASK 0x0000ffff +#define UDC_EPIN_BUFF_SIZE_OFS 0 +/* EP0in txfifo = 128 bytes*/ +#define UDC_EPIN0_BUFF_SIZE 32 +/* EP0in fullspeed txfifo = 128 bytes*/ +#define UDC_FS_EPIN0_BUFF_SIZE 32 + +/* fifo size mult = fifo size / max packet */ +#define UDC_EPIN_BUFF_SIZE_MULT 2 + +/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */ +#define UDC_EPIN_BUFF_SIZE 256 +/* EPin small INT data fifo size = 128 bytes */ +#define UDC_EPIN_SMALLINT_BUFF_SIZE 32 + +/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */ +#define UDC_FS_EPIN_BUFF_SIZE 32 + +#define UDC_EPOUT_FRAME_NUMBER_MASK 0x0000ffff +#define UDC_EPOUT_FRAME_NUMBER_OFS 0 + +/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/ +#define UDC_EPOUT_BUFF_SIZE_ADDR 0x0c +#define UDC_EP_MAX_PKT_SIZE_ADDR 0x0c + +#define UDC_EPOUT_BUFF_SIZE_MASK 0xffff0000 +#define UDC_EPOUT_BUFF_SIZE_OFS 16 +#define UDC_EP_MAX_PKT_SIZE_MASK 0x0000ffff +#define UDC_EP_MAX_PKT_SIZE_OFS 0 +/* EP0in max packet size = 64 bytes */ +#define UDC_EP0IN_MAX_PKT_SIZE 64 +/* EP0out max packet size = 64 bytes */ +#define UDC_EP0OUT_MAX_PKT_SIZE 64 +/* EP0in fullspeed max packet size = 64 bytes */ +#define UDC_FS_EP0IN_MAX_PKT_SIZE 64 +/* EP0out fullspeed max packet size = 64 bytes */ +#define UDC_FS_EP0OUT_MAX_PKT_SIZE 64 + +/* + * Endpoint dma descriptors ------------------------------------------------ + * + * Setup data, Status dword + */ +#define UDC_DMA_STP_STS_CFG_MASK 0x0fff0000 +#define UDC_DMA_STP_STS_CFG_OFS 16 +#define UDC_DMA_STP_STS_CFG_ALT_MASK 0x000f0000 +#define UDC_DMA_STP_STS_CFG_ALT_OFS 16 +#define UDC_DMA_STP_STS_CFG_INTF_MASK 0x00f00000 +#define UDC_DMA_STP_STS_CFG_INTF_OFS 20 +#define UDC_DMA_STP_STS_CFG_NUM_MASK 0x0f000000 +#define UDC_DMA_STP_STS_CFG_NUM_OFS 24 +#define UDC_DMA_STP_STS_RX_MASK 0x30000000 +#define UDC_DMA_STP_STS_RX_OFS 28 +#define UDC_DMA_STP_STS_BS_MASK 0xc0000000 +#define UDC_DMA_STP_STS_BS_OFS 30 +#define UDC_DMA_STP_STS_BS_HOST_READY 0 +#define UDC_DMA_STP_STS_BS_DMA_BUSY 1 +#define UDC_DMA_STP_STS_BS_DMA_DONE 2 +#define UDC_DMA_STP_STS_BS_HOST_BUSY 3 +/* IN data, Status dword */ +#define UDC_DMA_IN_STS_TXBYTES_MASK 0x0000ffff +#define UDC_DMA_IN_STS_TXBYTES_OFS 0 +#define UDC_DMA_IN_STS_FRAMENUM_MASK 0x07ff0000 +#define UDC_DMA_IN_STS_FRAMENUM_OFS 0 +#define UDC_DMA_IN_STS_L 27 +#define UDC_DMA_IN_STS_TX_MASK 0x30000000 +#define UDC_DMA_IN_STS_TX_OFS 28 +#define UDC_DMA_IN_STS_BS_MASK 0xc0000000 +#define UDC_DMA_IN_STS_BS_OFS 30 +#define UDC_DMA_IN_STS_BS_HOST_READY 0 +#define UDC_DMA_IN_STS_BS_DMA_BUSY 1 +#define UDC_DMA_IN_STS_BS_DMA_DONE 2 +#define UDC_DMA_IN_STS_BS_HOST_BUSY 3 +/* OUT data, Status dword */ +#define UDC_DMA_OUT_STS_RXBYTES_MASK 0x0000ffff +#define UDC_DMA_OUT_STS_RXBYTES_OFS 0 +#define UDC_DMA_OUT_STS_FRAMENUM_MASK 0x07ff0000 +#define UDC_DMA_OUT_STS_FRAMENUM_OFS 0 +#define UDC_DMA_OUT_STS_L 27 +#define UDC_DMA_OUT_STS_RX_MASK 0x30000000 +#define UDC_DMA_OUT_STS_RX_OFS 28 +#define UDC_DMA_OUT_STS_BS_MASK 0xc0000000 +#define UDC_DMA_OUT_STS_BS_OFS 30 +#define UDC_DMA_OUT_STS_BS_HOST_READY 0 +#define UDC_DMA_OUT_STS_BS_DMA_BUSY 1 +#define UDC_DMA_OUT_STS_BS_DMA_DONE 2 +#define UDC_DMA_OUT_STS_BS_HOST_BUSY 3 +/* max ep0in packet */ +#define UDC_EP0IN_MAXPACKET 1000 +/* max dma packet */ +#define UDC_DMA_MAXPACKET 65536 + +/* un-usable DMA address */ +#define DMA_DONT_USE (~(dma_addr_t) 0 ) + +/* other Endpoint register addresses and values-----------------------------*/ +#define UDC_EP_SUBPTR_ADDR 0x10 +#define UDC_EP_DESPTR_ADDR 0x14 +#define UDC_EP_WRITE_CONFIRM_ADDR 0x1c + +/* EP number as layouted in AHB space */ +#define UDC_EP_NUM 32 +#define UDC_EPIN_NUM 16 +#define UDC_EPIN_NUM_USED 5 +#define UDC_EPOUT_NUM 16 +/* EP number of EP's really used = EP0 + 8 data EP's */ +#define UDC_USED_EP_NUM 9 +/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */ +#define UDC_CSR_EP_OUT_IX_OFS 12 + +#define UDC_EP0OUT_IX 16 +#define UDC_EP0IN_IX 0 + +/* Rx fifo address and size = 1k -------------------------------------------*/ +#define UDC_RXFIFO_ADDR 0x800 +#define UDC_RXFIFO_SIZE 0x400 + +/* Tx fifo address and size = 1.5k -----------------------------------------*/ +#define UDC_TXFIFO_ADDR 0xc00 +#define UDC_TXFIFO_SIZE 0x600 + +/* default data endpoints --------------------------------------------------*/ +#define UDC_EPIN_STATUS_IX 1 +#define UDC_EPIN_IX 2 +#define UDC_EPOUT_IX 18 + +/* general constants -------------------------------------------------------*/ +#define UDC_DWORD_BYTES 4 +#define UDC_BITS_PER_BYTE_SHIFT 3 +#define UDC_BYTE_MASK 0xff +#define UDC_BITS_PER_BYTE 8 + +/*---------------------------------------------------------------------------*/ +/* UDC CSR's */ +struct udc_csrs { + + /* sca - setup command address */ + u32 sca; + + /* ep ne's */ + u32 ne[UDC_USED_EP_NUM]; +} __attribute__ ((packed)); + +/* AHB subsystem CSR registers */ +struct udc_regs { + + /* device configuration */ + u32 cfg; + + /* device control */ + u32 ctl; + + /* device status */ + u32 sts; + + /* device interrupt */ + u32 irqsts; + + /* device interrupt mask */ + u32 irqmsk; + + /* endpoint interrupt */ + u32 ep_irqsts; + + /* endpoint interrupt mask */ + u32 ep_irqmsk; +} __attribute__ ((packed)); + +/* endpoint specific registers */ +struct udc_ep_regs { + + /* endpoint control */ + u32 ctl; + + /* endpoint status */ + u32 sts; + + /* endpoint buffer size in/ receive packet frame number out */ + u32 bufin_framenum; + + /* endpoint buffer size out/max packet size */ + u32 bufout_maxpkt; + + /* endpoint setup buffer pointer */ + u32 subptr; + + /* endpoint data descriptor pointer */ + u32 desptr; + + /* reserverd */ + u32 reserved; + + /* write/read confirmation */ + u32 confirm; + +} __attribute__ ((packed)); + +/* control data DMA desc */ +struct udc_stp_dma { + /* status quadlet */ + u32 status; + /* reserved */ + u32 _reserved; + /* first setup word */ + u32 data12; + /* second setup word */ + u32 data34; +} __attribute__ ((aligned (16))); + +/* normal data DMA desc */ +struct udc_data_dma { + /* status quadlet */ + u32 status; + /* reserved */ + u32 _reserved; + /* buffer pointer */ + u32 bufptr; + /* next descriptor pointer */ + u32 next; +} __attribute__ ((aligned (16))); + +/* request packet */ +struct udc_request { + /* embedded gadget ep */ + struct usb_request req; + + /* flags */ + unsigned dma_going : 1, + dma_mapping : 1, + dma_done : 1; + /* phys. address */ + dma_addr_t td_phys; + /* first dma desc. of chain */ + struct udc_data_dma *td_data; + /* last dma desc. of chain */ + struct udc_data_dma *td_data_last; + struct list_head queue; + + /* chain length */ + unsigned chain_len; + +}; + +/* UDC specific endpoint parameters */ +struct udc_ep { + struct usb_ep ep; + struct udc_ep_regs __iomem *regs; + u32 __iomem *txfifo; + u32 __iomem *dma; + dma_addr_t td_phys; + dma_addr_t td_stp_dma; + struct udc_stp_dma *td_stp; + struct udc_data_dma *td; + /* temp request */ + struct udc_request *req; + unsigned req_used; + unsigned req_completed; + /* dummy DMA desc for BNA dummy */ + struct udc_request *bna_dummy_req; + unsigned bna_occurred; + + /* NAK state */ + unsigned naking; + + struct udc *dev; + + /* queue for requests */ + struct list_head queue; + const struct usb_endpoint_descriptor *desc; + unsigned halted; + unsigned cancel_transfer; + unsigned num : 5, + fifo_depth : 14, + in : 1; +}; + +/* device struct */ +struct udc { + struct usb_gadget gadget; + spinlock_t lock; /* protects all state */ + /* all endpoints */ + struct udc_ep ep[UDC_EP_NUM]; + struct usb_gadget_driver *driver; + /* operational flags */ + unsigned active : 1, + stall_ep0in : 1, + waiting_zlp_ack_ep0in : 1, + set_cfg_not_acked : 1, + irq_registered : 1, + data_ep_enabled : 1, + data_ep_queued : 1, + mem_region : 1, + sys_suspended : 1, + connected; + + u16 chiprev; + + /* registers */ + struct pci_dev *pdev; + struct udc_csrs __iomem *csr; + struct udc_regs __iomem *regs; + struct udc_ep_regs __iomem *ep_regs; + u32 __iomem *rxfifo; + u32 __iomem *txfifo; + + /* DMA desc pools */ + struct pci_pool *data_requests; + struct pci_pool *stp_requests; + + /* device data */ + unsigned long phys_addr; + void __iomem *virt_addr; + unsigned irq; + + /* states */ + u16 cur_config; + u16 cur_intf; + u16 cur_alt; +}; + +/* setup request data */ +union udc_setup_data { + u32 data[2]; + struct usb_ctrlrequest request; +}; + +/* + *--------------------------------------------------------------------------- + * SET and GET bitfields in u32 values + * via constants for mask/offset: + * is the text between + * UDC_ and _MASK|_OFS of appropiate + * constant + * + * set bitfield value in u32 u32Val + */ +#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name) \ + (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK)))) \ + | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS)) \ + & ((u32) bitfield_stub_name##_MASK))) + +/* + * set bitfield value in zero-initialized u32 u32Val + * => bitfield bits in u32Val are all zero + */ +#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name) \ + ((u32Val) \ + | (((bitfield_val) << ((u32) bitfield_stub_name##_OFS)) \ + & ((u32) bitfield_stub_name##_MASK))) + +/* get bitfield value from u32 u32Val */ +#define AMD_GETBITS(u32Val, bitfield_stub_name) \ + ((u32Val & ((u32) bitfield_stub_name##_MASK)) \ + >> ((u32) bitfield_stub_name##_OFS)) + +/* SET and GET bits in u32 values ------------------------------------------*/ +#define AMD_BIT(bit_stub_name) (1 << bit_stub_name) +#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name)) +#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name)) + +/* debug macros ------------------------------------------------------------*/ + +#define DBG(udc , args...) dev_dbg(&(udc)->pdev->dev, args) + +#ifdef UDC_VERBOSE +#define VDBG DBG +#else +#define VDBG(udc , args...) do {} while (0) +#endif + +#endif /* #ifdef AMD5536UDC_H */ diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index dbaf867436df..a3376739a81b 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -305,6 +305,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_AMD5536UDC +#define DEV_CONFIG_CDC +#endif + /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 53e9139ba388..e7fbefefe7b0 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -17,6 +17,12 @@ #define gadget_is_net2280(g) 0 #endif +#ifdef CONFIG_USB_GADGET_AMD5536UDC +#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name) +#else +#define gadget_is_amd5536udc(g) 0 +#endif + #ifdef CONFIG_USB_GADGET_DUMMY_HCD #define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name) #else @@ -202,6 +208,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x18; else if (gadget_is_fsl_usb2(gadget)) return 0x19; + else if (gadget_is_amd5536udc(gadget)) + return 0x20; else if (gadget_is_m66592(gadget)) return 0x20; return -ENOENT; -- cgit v1.2.2 From 167a675a8caa249f8bc9053c02d711545d1f7662 Mon Sep 17 00:00:00 2001 From: Thomas Dahlmann Date: Thu, 12 Jul 2007 09:30:39 -0700 Subject: USB: MAINTAINERS entry for amd5536udc MAINTAINERS entry for amd5536udc driver. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fbe0dca1c0ed..f49c5563f060 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -329,6 +329,12 @@ P: Ivan Kokshaysky M: ink@jurassic.park.msu.ru S: Maintained for 2.4; PCI support for 2.6. +AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER +P: Thomas Dahlmann +M: thomas.dahlmann@amd.com +L: info-linux@geode.amd.com +S: Supported + AMD GEODE PROCESSOR/CHIPSET SUPPORT P: Jordan Crouse M: info-linux@geode.amd.com -- cgit v1.2.2 From 0d46c0079a8eeed25105fa374f79862842ee80c1 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 16 Jul 2007 22:17:25 +0200 Subject: USB: Remove pointless conditional in drivers/usb/serial/io_ti.c::edge_shutdown() Coverity scan found (CID: 1708) this in drivers/usb/serial/io_ti.c::edge_shutdown() : ... 2797 for (i=0; i < serial->num_ports; ++i) { 2798 edge_port = usb_get_serial_port_data(serial->port[i]); 2799 edge_remove_sysfs_attrs(edge_port->port); 2800 if (edge_port) { 2801 edge_buf_free(edge_port->ep_out_buf); 2802 kfree(edge_port); 2803 } 2804 usb_set_serial_port_data(serial->port[i], NULL); 2805 } ... It's complaining that we dereference 'edge_port' in line 2799 which makes the test of that pointer against NULL in 2800 pointless, since if edge_port was actually NULL we'd have crashed already before reaching line 2800. Reading the edge_open() function it seems to me that the pointer returned by usb_get_serial_port_data(serial->port[i]) and stored in 'edge_port' can never actually be NULL here, so the test is entirely superfluous (even if it could be NULL it would be pointless here, ignoring the then possible crash in that case, since both edge_buf_free() and kfree() can handle being passed NULL pointers. This patch removes the pointless conditional (and also makes a few tiny style corrections now that I was in the area anyway). Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0d3903691e8c..b8670905bc3a 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2794,16 +2794,14 @@ static void edge_shutdown (struct usb_serial *serial) dbg ("%s", __FUNCTION__); - for (i=0; i < serial->num_ports; ++i) { + for (i = 0; i < serial->num_ports; ++i) { edge_port = usb_get_serial_port_data(serial->port[i]); edge_remove_sysfs_attrs(edge_port->port); - if (edge_port) { - edge_buf_free(edge_port->ep_out_buf); - kfree(edge_port); - } + edge_buf_free(edge_port->ep_out_buf); + kfree(edge_port); usb_set_serial_port_data(serial->port[i], NULL); } - kfree (usb_get_serial_data(serial)); + kfree(usb_get_serial_data(serial)); usb_set_serial_data(serial, NULL); } -- cgit v1.2.2 From d8fbba2f59c0c131a1babf5a66f003faee02e01a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 Jul 2007 15:30:20 -0400 Subject: USB: usb-storage: unusual_devs entry for Nikon D100 This patch (as938) adds an unusual_devs entry for the Nikon DSC D100. Signed-off-by: Alan Stern Cc: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 26fd196869b9..a624e72f81dc 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -313,6 +313,13 @@ UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, US_SC_DEVICE, US_PR_DEVICE,NULL, US_FL_NOT_LOCKABLE ), +/* Reported by Stefan de Konink */ +UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200, + "NIKON", + "NIKON DSC D100", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Reported by Andreas Bockhold */ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, "NIKON", -- cgit v1.2.2 From 598f22e11bef8171f2244128bf0341da38fe8a23 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 17 Jul 2007 21:01:17 +0900 Subject: USB: m66592-udc: fixes some problems This patch incorporates some updates from the review of the Renesas m66592-udc driver. Updates include: - Fix some locking bugs; and add a few sparse annotations - Don't #define __iomem ! - Lots of whitespace fixes (most of the patch by volume) - Some #include file trimmage - Other checkpatch.pl and sparse updates - Alphabetized and slightly-more-informative Kconfig - Don't use the ID which was assigned to the amd5536udc driver. - Remove pointless suspend/resume methods updating obsolete field. - Some section fixups - Fix some leak bugs - Fix byteswapping Signed-off-by: David Brownell Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 36 +-- drivers/usb/gadget/gadget_chips.h | 2 +- drivers/usb/gadget/m66592-udc.c | 255 ++++++++-------- drivers/usb/gadget/m66592-udc.h | 610 +++++++++++++++++++------------------- 4 files changed, 450 insertions(+), 453 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1553e9a649cd..767aed5b4bea 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -177,6 +177,24 @@ config USB_PXA2XX_SMALL default y if USB_ETH default y if USB_G_SERIAL +config USB_GADGET_M66592 + boolean "Renesas M66592 USB Peripheral Controller" + select USB_GADGET_DUALSPEED + help + M66592 is a discrete USB peripheral controller chip that + supports both full and high speed USB 2.0 data transfers. + It has seven configurable endpoints, and endpoint zero. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "m66592_udc" and force all + gadget drivers to also be dynamically linked. + +config USB_M66592 + tristate + depends on USB_GADGET_M66592 + default USB_GADGET + select USB_GADGET_SELECTED + config USB_GADGET_GOKU boolean "Toshiba TC86C001 'Goku-S'" depends on PCI @@ -282,24 +300,6 @@ config USB_AT91 depends on USB_GADGET_AT91 default USB_GADGET -config USB_GADGET_M66592 - boolean "M66592 driver" - select USB_GADGET_DUALSPEED - help - M66592 is a USB 2.0 peripheral controller. - - It has seven configurable endpoints, and endpoint zero. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "m66592_udc" and force all - gadget drivers to also be dynamically linked. - -config USB_M66592 - tristate - depends on USB_GADGET_M66592 - default USB_GADGET - select USB_GADGET_SELECTED - config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index e7fbefefe7b0..f7f159c1002b 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -211,6 +211,6 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) else if (gadget_is_amd5536udc(gadget)) return 0x20; else if (gadget_is_m66592(gadget)) - return 0x20; + return 0x21; return -ENOENT; } diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 0174a322e007..700dda8a9157 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -21,26 +21,18 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include #include + #include #include -#include -#include -#include - #include "m66592-udc.h" -MODULE_DESCRIPTION("M66592 USB gadget driiver"); + +MODULE_DESCRIPTION("M66592 USB gadget driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yoshihiro Shimoda"); @@ -49,16 +41,21 @@ MODULE_AUTHOR("Yoshihiro Shimoda"); /* module parameters */ static unsigned short clock = M66592_XTAL24; module_param(clock, ushort, 0644); -MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)"); +MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " + "(default=16384)"); + static unsigned short vif = M66592_LDRV; module_param(vif, ushort, 0644); -MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)"); -static unsigned short endian = 0; +MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)"); + +static unsigned short endian; module_param(endian, ushort, 0644); -MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)"); +MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)"); + static unsigned short irq_sense = M66592_INTL; module_param(irq_sense, ushort, 0644); -MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)"); +MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 " + "(default=2)"); static const char udc_name[] = "m66592_udc"; static const char *m66592_ep_name[] = { @@ -72,8 +69,8 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags); static void transfer_complete(struct m66592_ep *ep, - struct m66592_request *req, - int status); + struct m66592_request *req, int status); + /*-------------------------------------------------------------------------*/ static inline u16 get_usb_speed(struct m66592 *m66592) { @@ -81,25 +78,25 @@ static inline u16 get_usb_speed(struct m66592 *m66592) } static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum, - unsigned long reg) + unsigned long reg) { u16 tmp; tmp = m66592_read(m66592, M66592_INTENB0); m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE, - M66592_INTENB0); + M66592_INTENB0); m66592_bset(m66592, (1 << pipenum), reg); m66592_write(m66592, tmp, M66592_INTENB0); } static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum, - unsigned long reg) + unsigned long reg) { u16 tmp; tmp = m66592_read(m66592, M66592_INTENB0); m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE, - M66592_INTENB0); + M66592_INTENB0); m66592_bclr(m66592, (1 << pipenum), reg); m66592_write(m66592, tmp, M66592_INTENB0); } @@ -108,17 +105,19 @@ static void m66592_usb_connect(struct m66592 *m66592) { m66592_bset(m66592, M66592_CTRE, M66592_INTENB0); m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL, - M66592_INTENB0); + M66592_INTENB0); m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0); m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG); } static void m66592_usb_disconnect(struct m66592 *m66592) +__releases(m66592->lock) +__acquires(m66592->lock) { m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0); m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL, - M66592_INTENB0); + M66592_INTENB0); m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0); m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); @@ -148,7 +147,7 @@ static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum) } static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum, - u16 pid) + u16 pid) { unsigned long offset; @@ -250,7 +249,7 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum) } static int pipe_buffer_setting(struct m66592 *m66592, - struct m66592_pipe_info *info) + struct m66592_pipe_info *info) { u16 bufnum = 0, buf_bsize = 0; u16 pipecfg = 0; @@ -287,7 +286,7 @@ static int pipe_buffer_setting(struct m66592 *m66592, } if (m66592->bi_bufnum > M66592_MAX_BUFNUM) { printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n", - m66592->bi_bufnum); + m66592->bi_bufnum); return -ENOMEM; } @@ -328,7 +327,7 @@ static void pipe_buffer_release(struct m66592 *m66592, m66592->bulk--; } else printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n", - info->pipe); + info->pipe); } static void pipe_initialize(struct m66592_ep *ep) @@ -350,8 +349,8 @@ static void pipe_initialize(struct m66592_ep *ep) } static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, - const struct usb_endpoint_descriptor *desc, - u16 pipenum, int dma) + const struct usb_endpoint_descriptor *desc, + u16 pipenum, int dma) { if ((pipenum != 0) && dma) { if (m66592->num_dma == 0) { @@ -385,7 +384,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ep->pipectr = get_pipectr_addr(pipenum); ep->pipenum = pipenum; - ep->ep.maxpacket = desc->wMaxPacketSize; + ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); m66592->pipenum2ep[pipenum] = ep; m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep; INIT_LIST_HEAD(&ep->queue); @@ -407,7 +406,7 @@ static void m66592_ep_release(struct m66592_ep *ep) } static int alloc_pipe_config(struct m66592_ep *ep, - const struct usb_endpoint_descriptor *desc) + const struct usb_endpoint_descriptor *desc) { struct m66592 *m66592 = ep->m66592; struct m66592_pipe_info info; @@ -419,15 +418,15 @@ static int alloc_pipe_config(struct m66592_ep *ep, BUG_ON(ep->pipenum); - switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { case USB_ENDPOINT_XFER_BULK: if (m66592->bulk >= M66592_MAX_NUM_BULK) { if (m66592->isochronous >= M66592_MAX_NUM_ISOC) { printk(KERN_ERR "bulk pipe is insufficient\n"); return -ENODEV; } else { - info.pipe = M66592_BASE_PIPENUM_ISOC + - m66592->isochronous; + info.pipe = M66592_BASE_PIPENUM_ISOC + + m66592->isochronous; counter = &m66592->isochronous; } } else { @@ -462,7 +461,7 @@ static int alloc_pipe_config(struct m66592_ep *ep, ep->type = info.type; info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - info.maxpacket = desc->wMaxPacketSize; + info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); info.interval = desc->bInterval; if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) info.dir_in = 1; @@ -525,8 +524,8 @@ static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req) pipe_change(m66592, ep->pipenum); m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0, - (M66592_ISEL | M66592_CURPIPE), - M66592_CFIFOSEL); + (M66592_ISEL | M66592_CURPIPE), + M66592_CFIFOSEL); m66592_write(m66592, M66592_BCLR, ep->fifoctr); if (req->req.length == 0) { m66592_bset(m66592, M66592_BVAL, ep->fifoctr); @@ -561,8 +560,8 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req) if (ep->pipenum == 0) { m66592_mdfy(m66592, M66592_PIPE0, - (M66592_ISEL | M66592_CURPIPE), - M66592_CFIFOSEL); + (M66592_ISEL | M66592_CURPIPE), + M66592_CFIFOSEL); m66592_write(m66592, M66592_BCLR, ep->fifoctr); pipe_start(m66592, pipenum); pipe_irq_enable(m66592, pipenum); @@ -572,8 +571,9 @@ static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req) pipe_change(m66592, pipenum); m66592_bset(m66592, M66592_TRENB, ep->fifosel); m66592_write(m66592, - (req->req.length + ep->ep.maxpacket - 1) / - ep->ep.maxpacket, ep->fifotrn); + (req->req.length + ep->ep.maxpacket - 1) + / ep->ep.maxpacket, + ep->fifotrn); } pipe_start(m66592, pipenum); /* trigger once */ pipe_irq_enable(m66592, pipenum); @@ -614,7 +614,7 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req) static void init_controller(struct m66592 *m66592) { m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), - M66592_PINCFG); + M66592_PINCFG); m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG); @@ -634,7 +634,7 @@ static void init_controller(struct m66592 *m66592) m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1); m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, - M66592_DMA0CFG); + M66592_DMA0CFG); } static void disable_controller(struct m66592 *m66592) @@ -659,8 +659,9 @@ static void m66592_start_xclock(struct m66592 *m66592) /*-------------------------------------------------------------------------*/ static void transfer_complete(struct m66592_ep *ep, - struct m66592_request *req, - int status) + struct m66592_request *req, int status) +__releases(m66592->lock) +__acquires(m66592->lock) { int restart = 0; @@ -680,8 +681,9 @@ static void transfer_complete(struct m66592_ep *ep, if (!list_empty(&ep->queue)) restart = 1; - if (likely(req->req.complete)) - req->req.complete(&ep->ep, &req->req); + spin_unlock(&ep->m66592->lock); + req->req.complete(&ep->ep, &req->req); + spin_lock(&ep->m66592->lock); if (restart) { req = list_entry(ep->queue.next, struct m66592_request, queue); @@ -693,7 +695,7 @@ static void transfer_complete(struct m66592_ep *ep, static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req) { int i; - volatile u16 tmp; + u16 tmp; unsigned bufsize; size_t size; void *buf; @@ -731,8 +733,9 @@ static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req) req->req.actual += size; /* check transfer finish */ - if ((!req->req.zero && (req->req.actual == req->req.length)) || - (size % ep->ep.maxpacket) || (size == 0)) { + if ((!req->req.zero && (req->req.actual == req->req.length)) + || (size % ep->ep.maxpacket) + || (size == 0)) { disable_irq_ready(m66592, pipenum); disable_irq_empty(m66592, pipenum); } else { @@ -768,16 +771,19 @@ static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req) /* write fifo */ if (req->req.buf) { m66592_write_fifo(m66592, ep->fifoaddr, buf, size); - if ((size == 0) || ((size % ep->ep.maxpacket) != 0) || - ((bufsize != ep->ep.maxpacket) && (bufsize > size))) + if ((size == 0) + || ((size % ep->ep.maxpacket) != 0) + || ((bufsize != ep->ep.maxpacket) + && (bufsize > size))) m66592_bset(m66592, M66592_BVAL, ep->fifoctr); } /* update parameters */ req->req.actual += size; /* check transfer finish */ - if ((!req->req.zero && (req->req.actual == req->req.length)) || - (size % ep->ep.maxpacket) || (size == 0)) { + if ((!req->req.zero && (req->req.actual == req->req.length)) + || (size % ep->ep.maxpacket) + || (size == 0)) { disable_irq_ready(m66592, pipenum); enable_irq_empty(m66592, pipenum); } else { @@ -821,8 +827,9 @@ static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req) req->req.actual += size; /* check transfer finish */ - if ((!req->req.zero && (req->req.actual == req->req.length)) || - (size % ep->ep.maxpacket) || (size == 0)) { + if ((!req->req.zero && (req->req.actual == req->req.length)) + || (size % ep->ep.maxpacket) + || (size == 0)) { pipe_stop(m66592, pipenum); pipe_irq_disable(m66592, pipenum); finish = 1; @@ -850,7 +857,7 @@ static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb) if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) { m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS); m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE, - M66592_CFIFOSEL); + M66592_CFIFOSEL); ep = &m66592->ep[0]; req = list_entry(ep->queue.next, struct m66592_request, queue); @@ -909,23 +916,26 @@ static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb) } static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) +__releases(m66592->lock) +__acquires(m66592->lock) { struct m66592_ep *ep; u16 pid; u16 status = 0; + u16 w_index = le16_to_cpu(ctrl->wIndex); switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - status = 1; /* selfpower */ + status = 1 << USB_DEVICE_SELF_POWERED; break; case USB_RECIP_INTERFACE: status = 0; break; case USB_RECIP_ENDPOINT: - ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; + ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; pid = control_reg_get_pid(m66592, ep->pipenum); if (pid == M66592_PID_STALL) - status = 1; + status = 1 << USB_ENDPOINT_HALT; else status = 0; break; @@ -934,11 +944,13 @@ static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) return; /* exit */ } - *m66592->ep0_buf = status; - m66592->ep0_req->buf = m66592->ep0_buf; + m66592->ep0_data = cpu_to_le16(status); + m66592->ep0_req->buf = &m66592->ep0_data; m66592->ep0_req->length = 2; /* AV: what happens if we get called again before that gets through? */ + spin_unlock(&m66592->lock); m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL); + spin_lock(&m66592->lock); } static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) @@ -953,8 +965,9 @@ static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) case USB_RECIP_ENDPOINT: { struct m66592_ep *ep; struct m66592_request *req; + u16 w_index = le16_to_cpu(ctrl->wIndex); - ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; + ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; pipe_stop(m66592, ep->pipenum); control_reg_sqclr(m66592, ep->pipenum); @@ -989,8 +1002,9 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) break; case USB_RECIP_ENDPOINT: { struct m66592_ep *ep; + u16 w_index = le16_to_cpu(ctrl->wIndex); - ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; + ep = m66592->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK]; pipe_stall(m66592, ep->pipenum); control_end(m66592, 1); @@ -1066,14 +1080,16 @@ static void irq_device_state(struct m66592 *m66592) } if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG) m66592_update_usb_speed(m66592); - if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) && - m66592->gadget.speed == USB_SPEED_UNKNOWN) + if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) + && m66592->gadget.speed == USB_SPEED_UNKNOWN) m66592_update_usb_speed(m66592); m66592->old_dvsq = dvsq; } static void irq_control_stage(struct m66592 *m66592) +__releases(m66592->lock) +__acquires(m66592->lock) { struct usb_ctrlrequest ctrl; u16 ctsq; @@ -1095,8 +1111,10 @@ static void irq_control_stage(struct m66592 *m66592) case M66592_CS_WRDS: case M66592_CS_WRND: if (setup_packet(m66592, &ctrl)) { + spin_unlock(&m66592->lock); if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0) pipe_stall(m66592, 0); + spin_lock(&m66592->lock); } break; case M66592_CS_RDSS: @@ -1119,6 +1137,8 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) u16 savepipe; u16 mask0; + spin_lock(&m66592->lock); + intsts0 = m66592_read(m66592, M66592_INTSTS0); intenb0 = m66592_read(m66592, M66592_INTENB0); @@ -1134,27 +1154,27 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) bempenb = m66592_read(m66592, M66592_BEMPENB); if (mask0 & M66592_VBINT) { - m66592_write(m66592, (u16)~M66592_VBINT, - M66592_INTSTS0); + m66592_write(m66592, 0xffff & ~M66592_VBINT, + M66592_INTSTS0); m66592_start_xclock(m66592); /* start vbus sampling */ m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0) - & M66592_VBSTS; + & M66592_VBSTS; m66592->scount = M66592_MAX_SAMPLING; mod_timer(&m66592->timer, - jiffies + msecs_to_jiffies(50)); + jiffies + msecs_to_jiffies(50)); } if (intsts0 & M66592_DVSQ) irq_device_state(m66592); - if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) && - (brdysts & brdyenb)) { + if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) + && (brdysts & brdyenb)) { irq_pipe_ready(m66592, brdysts, brdyenb); } - if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) && - (bempsts & bempenb)) { + if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) + && (bempsts & bempenb)) { irq_pipe_empty(m66592, bempsts, bempenb); } @@ -1164,6 +1184,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) m66592_write(m66592, savepipe, M66592_CFIFOSEL); + spin_unlock(&m66592->lock); return IRQ_HANDLED; } @@ -1191,13 +1212,13 @@ static void m66592_timer(unsigned long _m66592) m66592_usb_disconnect(m66592); } else { mod_timer(&m66592->timer, - jiffies + msecs_to_jiffies(50)); + jiffies + msecs_to_jiffies(50)); } } else { m66592->scount = M66592_MAX_SAMPLING; m66592->old_vbus = tmp; mod_timer(&m66592->timer, - jiffies + msecs_to_jiffies(50)); + jiffies + msecs_to_jiffies(50)); } } spin_unlock_irqrestore(&m66592->lock, flags); @@ -1335,11 +1356,6 @@ out: return ret; } -static int m66592_fifo_status(struct usb_ep *_ep) -{ - return -EOPNOTSUPP; -} - static void m66592_fifo_flush(struct usb_ep *_ep) { struct m66592_ep *ep; @@ -1365,7 +1381,6 @@ static struct usb_ep_ops m66592_ep_ops = { .dequeue = m66592_dequeue, .set_halt = m66592_set_halt, - .fifo_status = m66592_fifo_status, .fifo_flush = m66592_fifo_flush, }; @@ -1377,11 +1392,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) struct m66592 *m66592 = the_controller; int retval; - if (!driver || - driver->speed != USB_SPEED_HIGH || - !driver->bind || - !driver->unbind || - !driver->setup) + if (!driver + || driver->speed != USB_SPEED_HIGH + || !driver->bind + || !driver->setup) return -EINVAL; if (!m66592) return -ENODEV; @@ -1413,8 +1427,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS; m66592->scount = M66592_MAX_SAMPLING; - mod_timer(&m66592->timer, - jiffies + msecs_to_jiffies(50)); + mod_timer(&m66592->timer, jiffies + msecs_to_jiffies(50)); } return 0; @@ -1432,6 +1445,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) struct m66592 *m66592 = the_controller; unsigned long flags; + if (driver != m66592->driver || !driver->unbind) + return -EINVAL; + spin_lock_irqsave(&m66592->lock, flags); if (m66592->gadget.speed != USB_SPEED_UNKNOWN) m66592_usb_disconnect(m66592); @@ -1461,46 +1477,35 @@ static struct usb_gadget_ops m66592_gadget_ops = { .get_frame = m66592_get_frame, }; -#if defined(CONFIG_PM) -static int m66592_suspend(struct platform_device *pdev, pm_message_t state) -{ - pdev->dev.power.power_state = state; - return 0; -} - -static int m66592_resume(struct platform_device *pdev) -{ - pdev->dev.power.power_state = PMSG_ON; - return 0; -} -#else /* if defined(CONFIG_PM) */ -#define m66592_suspend NULL -#define m66592_resume NULL -#endif - -static int __init_or_module m66592_remove(struct platform_device *pdev) +static int __exit m66592_remove(struct platform_device *pdev) { struct m66592 *m66592 = dev_get_drvdata(&pdev->dev); del_timer_sync(&m66592->timer); iounmap(m66592->reg); free_irq(platform_get_irq(pdev, 0), m66592); + m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); kfree(m66592); return 0; } +static void nop_completion(struct usb_ep *ep, struct usb_request *r) +{ +} + #define resource_len(r) (((r)->end - (r)->start) + 1) + static int __init m66592_probe(struct platform_device *pdev) { - struct resource *res = NULL; - int irq = -1; + struct resource *res; + int irq; void __iomem *reg = NULL; struct m66592 *m66592 = NULL; int ret = 0; int i; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - (char *)udc_name); + (char *)udc_name); if (!res) { ret = -ENODEV; printk(KERN_ERR "platform_get_resource_byname error.\n"); @@ -1548,7 +1553,7 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->bi_bufnum = M66592_BASE_BUFNUM; ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED, - udc_name, m66592); + udc_name, m66592); if (ret < 0) { printk(KERN_ERR "request_irq error (%d)\n", ret); goto clean_up; @@ -1563,7 +1568,7 @@ static int __init m66592_probe(struct platform_device *pdev) if (i != 0) { INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list); list_add_tail(&m66592->ep[i].ep.ep_list, - &m66592->gadget.ep_list); + &m66592->gadget.ep_list); } ep->m66592 = m66592; INIT_LIST_HEAD(&ep->queue); @@ -1583,20 +1588,18 @@ static int __init m66592_probe(struct platform_device *pdev) the_controller = m66592; - /* AV: leaks */ m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL); if (m66592->ep0_req == NULL) - goto clean_up; - /* AV: leaks, and do we really need it separately allocated? */ - m66592->ep0_buf = kzalloc(2, GFP_KERNEL); - if (m66592->ep0_buf == NULL) - goto clean_up; + goto clean_up2; + m66592->ep0_req->complete = nop_completion; init_controller(m66592); - printk("driver %s, %s\n", udc_name, DRIVER_VERSION); + dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); return 0; +clean_up2: + free_irq(irq, m66592); clean_up: if (m66592) { if (m66592->ep0_req) @@ -1611,10 +1614,7 @@ clean_up: /*-------------------------------------------------------------------------*/ static struct platform_driver m66592_driver = { - .probe = m66592_probe, - .remove = m66592_remove, - .suspend = m66592_suspend, - .resume = m66592_resume, + .remove = __exit_p(m66592_remove), .driver = { .name = (char *) udc_name, }, @@ -1622,7 +1622,7 @@ static struct platform_driver m66592_driver = { static int __init m66592_udc_init(void) { - return platform_driver_register(&m66592_driver); + return platform_driver_probe(&m66592_driver, m66592_probe); } module_init(m66592_udc_init); @@ -1631,4 +1631,3 @@ static void __exit m66592_udc_cleanup(void) platform_driver_unregister(&m66592_driver); } module_exit(m66592_udc_cleanup); - diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 26b54f8b8945..bfa0c645f229 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -24,73 +24,73 @@ #define __M66592_UDC_H__ #define M66592_SYSCFG 0x00 -#define M66592_XTAL 0xC000 /* b15-14: Crystal selection */ -#define M66592_XTAL48 0x8000 /* 48MHz */ -#define M66592_XTAL24 0x4000 /* 24MHz */ -#define M66592_XTAL12 0x0000 /* 12MHz */ -#define M66592_XCKE 0x2000 /* b13: External clock enable */ -#define M66592_RCKE 0x1000 /* b12: Register clock enable */ -#define M66592_PLLC 0x0800 /* b11: PLL control */ -#define M66592_SCKE 0x0400 /* b10: USB clock enable */ -#define M66592_ATCKM 0x0100 /* b8: Automatic supply functional enable */ -#define M66592_HSE 0x0080 /* b7: Hi-speed enable */ -#define M66592_DCFM 0x0040 /* b6: Controller function select */ -#define M66592_DMRPD 0x0020 /* b5: D- pull down control */ -#define M66592_DPRPU 0x0010 /* b4: D+ pull up control */ -#define M66592_FSRPC 0x0004 /* b2: Full-speed receiver enable */ -#define M66592_PCUT 0x0002 /* b1: Low power sleep enable */ -#define M66592_USBE 0x0001 /* b0: USB module operation enable */ +#define M66592_XTAL 0xC000 /* b15-14: Crystal selection */ +#define M66592_XTAL48 0x8000 /* 48MHz */ +#define M66592_XTAL24 0x4000 /* 24MHz */ +#define M66592_XTAL12 0x0000 /* 12MHz */ +#define M66592_XCKE 0x2000 /* b13: External clock enable */ +#define M66592_RCKE 0x1000 /* b12: Register clock enable */ +#define M66592_PLLC 0x0800 /* b11: PLL control */ +#define M66592_SCKE 0x0400 /* b10: USB clock enable */ +#define M66592_ATCKM 0x0100 /* b8: Automatic clock supply */ +#define M66592_HSE 0x0080 /* b7: Hi-speed enable */ +#define M66592_DCFM 0x0040 /* b6: Controller function select */ +#define M66592_DMRPD 0x0020 /* b5: D- pull down control */ +#define M66592_DPRPU 0x0010 /* b4: D+ pull up control */ +#define M66592_FSRPC 0x0004 /* b2: Full-speed receiver enable */ +#define M66592_PCUT 0x0002 /* b1: Low power sleep enable */ +#define M66592_USBE 0x0001 /* b0: USB module operation enable */ #define M66592_SYSSTS 0x02 -#define M66592_LNST 0x0003 /* b1-0: D+, D- line status */ -#define M66592_SE1 0x0003 /* SE1 */ -#define M66592_KSTS 0x0002 /* K State */ -#define M66592_JSTS 0x0001 /* J State */ -#define M66592_SE0 0x0000 /* SE0 */ +#define M66592_LNST 0x0003 /* b1-0: D+, D- line status */ +#define M66592_SE1 0x0003 /* SE1 */ +#define M66592_KSTS 0x0002 /* K State */ +#define M66592_JSTS 0x0001 /* J State */ +#define M66592_SE0 0x0000 /* SE0 */ #define M66592_DVSTCTR 0x04 -#define M66592_WKUP 0x0100 /* b8: Remote wakeup */ -#define M66592_RWUPE 0x0080 /* b7: Remote wakeup sense */ -#define M66592_USBRST 0x0040 /* b6: USB reset enable */ -#define M66592_RESUME 0x0020 /* b5: Resume enable */ -#define M66592_UACT 0x0010 /* b4: USB bus enable */ -#define M66592_RHST 0x0003 /* b1-0: Reset handshake status */ -#define M66592_HSMODE 0x0003 /* Hi-Speed mode */ -#define M66592_FSMODE 0x0002 /* Full-Speed mode */ -#define M66592_HSPROC 0x0001 /* HS handshake is processing */ +#define M66592_WKUP 0x0100 /* b8: Remote wakeup */ +#define M66592_RWUPE 0x0080 /* b7: Remote wakeup sense */ +#define M66592_USBRST 0x0040 /* b6: USB reset enable */ +#define M66592_RESUME 0x0020 /* b5: Resume enable */ +#define M66592_UACT 0x0010 /* b4: USB bus enable */ +#define M66592_RHST 0x0003 /* b1-0: Reset handshake status */ +#define M66592_HSMODE 0x0003 /* Hi-Speed mode */ +#define M66592_FSMODE 0x0002 /* Full-Speed mode */ +#define M66592_HSPROC 0x0001 /* HS handshake is processing */ #define M66592_TESTMODE 0x06 -#define M66592_UTST 0x000F /* b4-0: Test select */ -#define M66592_H_TST_PACKET 0x000C /* HOST TEST Packet */ -#define M66592_H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ -#define M66592_H_TST_K 0x000A /* HOST TEST K */ -#define M66592_H_TST_J 0x0009 /* HOST TEST J */ -#define M66592_H_TST_NORMAL 0x0000 /* HOST Normal Mode */ -#define M66592_P_TST_PACKET 0x0004 /* PERI TEST Packet */ -#define M66592_P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ -#define M66592_P_TST_K 0x0002 /* PERI TEST K */ -#define M66592_P_TST_J 0x0001 /* PERI TEST J */ -#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ +#define M66592_UTST 0x000F /* b4-0: Test select */ +#define M66592_H_TST_PACKET 0x000C /* HOST TEST Packet */ +#define M66592_H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ +#define M66592_H_TST_K 0x000A /* HOST TEST K */ +#define M66592_H_TST_J 0x0009 /* HOST TEST J */ +#define M66592_H_TST_NORMAL 0x0000 /* HOST Normal Mode */ +#define M66592_P_TST_PACKET 0x0004 /* PERI TEST Packet */ +#define M66592_P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ +#define M66592_P_TST_K 0x0002 /* PERI TEST K */ +#define M66592_P_TST_J 0x0001 /* PERI TEST J */ +#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ #define M66592_PINCFG 0x0A -#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ -#define M66592_BIGEND 0x0100 /* b8: Big endian mode */ +#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ +#define M66592_BIGEND 0x0100 /* b8: Big endian mode */ #define M66592_DMA0CFG 0x0C #define M66592_DMA1CFG 0x0E -#define M66592_DREQA 0x4000 /* b14: Dreq active select */ -#define M66592_BURST 0x2000 /* b13: Burst mode */ -#define M66592_DACKA 0x0400 /* b10: Dack active select */ -#define M66592_DFORM 0x0380 /* b9-7: DMA mode select */ -#define M66592_CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ -#define M66592_CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ -#define M66592_CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ -#define M66592_SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ -#define M66592_SPLIT_DACK_DSTB 0x0300 /* DACK + DSTB0 mode (SPLIT bus) */ -#define M66592_DENDA 0x0040 /* b6: Dend active select */ -#define M66592_PKTM 0x0020 /* b5: Packet mode */ -#define M66592_DENDE 0x0010 /* b4: Dend enable */ -#define M66592_OBUS 0x0004 /* b2: OUTbus mode */ +#define M66592_DREQA 0x4000 /* b14: Dreq active select */ +#define M66592_BURST 0x2000 /* b13: Burst mode */ +#define M66592_DACKA 0x0400 /* b10: Dack active select */ +#define M66592_DFORM 0x0380 /* b9-7: DMA mode select */ +#define M66592_CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ +#define M66592_CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ +#define M66592_CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ +#define M66592_SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ +#define M66592_SPLIT_DACK_DSTB 0x0300 /* DACK + DSTB0 mode (SPLIT bus) */ +#define M66592_DENDA 0x0040 /* b6: Dend active select */ +#define M66592_PKTM 0x0020 /* b5: Packet mode */ +#define M66592_DENDE 0x0010 /* b4: Dend enable */ +#define M66592_OBUS 0x0004 /* b2: OUTbus mode */ #define M66592_CFIFO 0x10 #define M66592_D0FIFO 0x14 @@ -99,300 +99,300 @@ #define M66592_CFIFOSEL 0x1E #define M66592_D0FIFOSEL 0x24 #define M66592_D1FIFOSEL 0x2A -#define M66592_RCNT 0x8000 /* b15: Read count mode */ -#define M66592_REW 0x4000 /* b14: Buffer rewind */ -#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ -#define M66592_DREQE 0x1000 /* b12: DREQ output enable */ -#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO access */ -#define M66592_MBW_8 0x0000 /* 8bit */ -#define M66592_MBW_16 0x0400 /* 16bit */ -#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ -#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ -#define M66592_DEZPM 0x0080 /* b7: Zero-length packet additional mode */ -#define M66592_ISEL 0x0020 /* b5: DCP FIFO port direction select */ -#define M66592_CURPIPE 0x0007 /* b2-0: PIPE select */ +#define M66592_RCNT 0x8000 /* b15: Read count mode */ +#define M66592_REW 0x4000 /* b14: Buffer rewind */ +#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ +#define M66592_DREQE 0x1000 /* b12: DREQ output enable */ +#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */ +#define M66592_MBW_8 0x0000 /* 8bit */ +#define M66592_MBW_16 0x0400 /* 16bit */ +#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ +#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ +#define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */ +#define M66592_ISEL 0x0020 /* b5: DCP FIFO port direction select */ +#define M66592_CURPIPE 0x0007 /* b2-0: PIPE select */ #define M66592_CFIFOCTR 0x20 #define M66592_D0FIFOCTR 0x26 #define M66592_D1FIFOCTR 0x2c -#define M66592_BVAL 0x8000 /* b15: Buffer valid flag */ -#define M66592_BCLR 0x4000 /* b14: Buffer clear */ -#define M66592_FRDY 0x2000 /* b13: FIFO ready */ -#define M66592_DTLN 0x0FFF /* b11-0: FIFO received data length */ +#define M66592_BVAL 0x8000 /* b15: Buffer valid flag */ +#define M66592_BCLR 0x4000 /* b14: Buffer clear */ +#define M66592_FRDY 0x2000 /* b13: FIFO ready */ +#define M66592_DTLN 0x0FFF /* b11-0: FIFO received data length */ #define M66592_CFIFOSIE 0x22 -#define M66592_TGL 0x8000 /* b15: Buffer toggle */ -#define M66592_SCLR 0x4000 /* b14: Buffer clear */ -#define M66592_SBUSY 0x2000 /* b13: SIE_FIFO busy */ +#define M66592_TGL 0x8000 /* b15: Buffer toggle */ +#define M66592_SCLR 0x4000 /* b14: Buffer clear */ +#define M66592_SBUSY 0x2000 /* b13: SIE_FIFO busy */ #define M66592_D0FIFOTRN 0x28 #define M66592_D1FIFOTRN 0x2E -#define M66592_TRNCNT 0xFFFF /* b15-0: Transaction counter */ +#define M66592_TRNCNT 0xFFFF /* b15-0: Transaction counter */ #define M66592_INTENB0 0x30 -#define M66592_VBSE 0x8000 /* b15: VBUS interrupt */ -#define M66592_RSME 0x4000 /* b14: Resume interrupt */ -#define M66592_SOFE 0x2000 /* b13: Frame update interrupt */ -#define M66592_DVSE 0x1000 /* b12: Device state transition interrupt */ -#define M66592_CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define M66592_BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define M66592_NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define M66592_BRDYE 0x0100 /* b8: Buffer ready interrupt */ -#define M66592_URST 0x0080 /* b7: USB reset detected interrupt */ -#define M66592_SADR 0x0040 /* b6: Set address executed interrupt */ -#define M66592_SCFG 0x0020 /* b5: Set configuration executed interrupt */ -#define M66592_SUSP 0x0010 /* b4: Suspend detected interrupt */ -#define M66592_WDST 0x0008 /* b3: Control write data stage completed interrupt */ -#define M66592_RDST 0x0004 /* b2: Control read data stage completed interrupt */ -#define M66592_CMPL 0x0002 /* b1: Control transfer complete interrupt */ -#define M66592_SERR 0x0001 /* b0: Sequence error interrupt */ +#define M66592_VBSE 0x8000 /* b15: VBUS interrupt */ +#define M66592_RSME 0x4000 /* b14: Resume interrupt */ +#define M66592_SOFE 0x2000 /* b13: Frame update interrupt */ +#define M66592_DVSE 0x1000 /* b12: Device state transition interrupt */ +#define M66592_CTRE 0x0800 /* b11: Control transfer stage transition irq */ +#define M66592_BEMPE 0x0400 /* b10: Buffer empty interrupt */ +#define M66592_NRDYE 0x0200 /* b9: Buffer not ready interrupt */ +#define M66592_BRDYE 0x0100 /* b8: Buffer ready interrupt */ +#define M66592_URST 0x0080 /* b7: USB reset detected interrupt */ +#define M66592_SADR 0x0040 /* b6: Set address executed interrupt */ +#define M66592_SCFG 0x0020 /* b5: Set configuration executed interrupt */ +#define M66592_SUSP 0x0010 /* b4: Suspend detected interrupt */ +#define M66592_WDST 0x0008 /* b3: Control write data stage completed irq */ +#define M66592_RDST 0x0004 /* b2: Control read data stage completed irq */ +#define M66592_CMPL 0x0002 /* b1: Control transfer complete interrupt */ +#define M66592_SERR 0x0001 /* b0: Sequence error interrupt */ #define M66592_INTENB1 0x32 -#define M66592_BCHGE 0x4000 /* b14: USB us chenge interrupt */ -#define M66592_DTCHE 0x1000 /* b12: Detach sense interrupt */ -#define M66592_SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ -#define M66592_SACKE 0x0010 /* b4: SETUP ACK interrupt */ -#define M66592_BRDYM 0x0004 /* b2: BRDY clear timing */ -#define M66592_INTL 0x0002 /* b1: Interrupt sense select */ -#define M66592_PCSE 0x0001 /* b0: PCUT enable by CS assert */ +#define M66592_BCHGE 0x4000 /* b14: USB us chenge interrupt */ +#define M66592_DTCHE 0x1000 /* b12: Detach sense interrupt */ +#define M66592_SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ +#define M66592_SACKE 0x0010 /* b4: SETUP ACK interrupt */ +#define M66592_BRDYM 0x0004 /* b2: BRDY clear timing */ +#define M66592_INTL 0x0002 /* b1: Interrupt sense select */ +#define M66592_PCSE 0x0001 /* b0: PCUT enable by CS assert */ #define M66592_BRDYENB 0x36 #define M66592_BRDYSTS 0x46 -#define M66592_BRDY7 0x0080 /* b7: PIPE7 */ -#define M66592_BRDY6 0x0040 /* b6: PIPE6 */ -#define M66592_BRDY5 0x0020 /* b5: PIPE5 */ -#define M66592_BRDY4 0x0010 /* b4: PIPE4 */ -#define M66592_BRDY3 0x0008 /* b3: PIPE3 */ -#define M66592_BRDY2 0x0004 /* b2: PIPE2 */ -#define M66592_BRDY1 0x0002 /* b1: PIPE1 */ -#define M66592_BRDY0 0x0001 /* b1: PIPE0 */ +#define M66592_BRDY7 0x0080 /* b7: PIPE7 */ +#define M66592_BRDY6 0x0040 /* b6: PIPE6 */ +#define M66592_BRDY5 0x0020 /* b5: PIPE5 */ +#define M66592_BRDY4 0x0010 /* b4: PIPE4 */ +#define M66592_BRDY3 0x0008 /* b3: PIPE3 */ +#define M66592_BRDY2 0x0004 /* b2: PIPE2 */ +#define M66592_BRDY1 0x0002 /* b1: PIPE1 */ +#define M66592_BRDY0 0x0001 /* b1: PIPE0 */ #define M66592_NRDYENB 0x38 #define M66592_NRDYSTS 0x48 -#define M66592_NRDY7 0x0080 /* b7: PIPE7 */ -#define M66592_NRDY6 0x0040 /* b6: PIPE6 */ -#define M66592_NRDY5 0x0020 /* b5: PIPE5 */ -#define M66592_NRDY4 0x0010 /* b4: PIPE4 */ -#define M66592_NRDY3 0x0008 /* b3: PIPE3 */ -#define M66592_NRDY2 0x0004 /* b2: PIPE2 */ -#define M66592_NRDY1 0x0002 /* b1: PIPE1 */ -#define M66592_NRDY0 0x0001 /* b1: PIPE0 */ +#define M66592_NRDY7 0x0080 /* b7: PIPE7 */ +#define M66592_NRDY6 0x0040 /* b6: PIPE6 */ +#define M66592_NRDY5 0x0020 /* b5: PIPE5 */ +#define M66592_NRDY4 0x0010 /* b4: PIPE4 */ +#define M66592_NRDY3 0x0008 /* b3: PIPE3 */ +#define M66592_NRDY2 0x0004 /* b2: PIPE2 */ +#define M66592_NRDY1 0x0002 /* b1: PIPE1 */ +#define M66592_NRDY0 0x0001 /* b1: PIPE0 */ #define M66592_BEMPENB 0x3A #define M66592_BEMPSTS 0x4A -#define M66592_BEMP7 0x0080 /* b7: PIPE7 */ -#define M66592_BEMP6 0x0040 /* b6: PIPE6 */ -#define M66592_BEMP5 0x0020 /* b5: PIPE5 */ -#define M66592_BEMP4 0x0010 /* b4: PIPE4 */ -#define M66592_BEMP3 0x0008 /* b3: PIPE3 */ -#define M66592_BEMP2 0x0004 /* b2: PIPE2 */ -#define M66592_BEMP1 0x0002 /* b1: PIPE1 */ -#define M66592_BEMP0 0x0001 /* b0: PIPE0 */ +#define M66592_BEMP7 0x0080 /* b7: PIPE7 */ +#define M66592_BEMP6 0x0040 /* b6: PIPE6 */ +#define M66592_BEMP5 0x0020 /* b5: PIPE5 */ +#define M66592_BEMP4 0x0010 /* b4: PIPE4 */ +#define M66592_BEMP3 0x0008 /* b3: PIPE3 */ +#define M66592_BEMP2 0x0004 /* b2: PIPE2 */ +#define M66592_BEMP1 0x0002 /* b1: PIPE1 */ +#define M66592_BEMP0 0x0001 /* b0: PIPE0 */ #define M66592_SOFCFG 0x3C -#define M66592_SOFM 0x000C /* b3-2: SOF palse mode */ -#define M66592_SOF_125US 0x0008 /* SOF OUT 125us uFrame Signal */ -#define M66592_SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ -#define M66592_SOF_DISABLE 0x0000 /* SOF OUT Disable */ +#define M66592_SOFM 0x000C /* b3-2: SOF palse mode */ +#define M66592_SOF_125US 0x0008 /* SOF OUT 125us uFrame Signal */ +#define M66592_SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ +#define M66592_SOF_DISABLE 0x0000 /* SOF OUT Disable */ #define M66592_INTSTS0 0x40 -#define M66592_VBINT 0x8000 /* b15: VBUS interrupt */ -#define M66592_RESM 0x4000 /* b14: Resume interrupt */ -#define M66592_SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define M66592_DVST 0x1000 /* b12: Device state transition interrupt */ -#define M66592_CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define M66592_BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define M66592_NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define M66592_BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define M66592_VBSTS 0x0080 /* b7: VBUS input port */ -#define M66592_DVSQ 0x0070 /* b6-4: Device state */ -#define M66592_DS_SPD_CNFG 0x0070 /* Suspend Configured */ -#define M66592_DS_SPD_ADDR 0x0060 /* Suspend Address */ -#define M66592_DS_SPD_DFLT 0x0050 /* Suspend Default */ -#define M66592_DS_SPD_POWR 0x0040 /* Suspend Powered */ -#define M66592_DS_SUSP 0x0040 /* Suspend */ -#define M66592_DS_CNFG 0x0030 /* Configured */ -#define M66592_DS_ADDS 0x0020 /* Address */ -#define M66592_DS_DFLT 0x0010 /* Default */ -#define M66592_DS_POWR 0x0000 /* Powered */ -#define M66592_DVSQS 0x0030 /* b5-4: Device state */ -#define M66592_VALID 0x0008 /* b3: Setup packet detected flag */ -#define M66592_CTSQ 0x0007 /* b2-0: Control transfer stage */ -#define M66592_CS_SQER 0x0006 /* Sequence error */ -#define M66592_CS_WRND 0x0005 /* Control write nodata status stage */ -#define M66592_CS_WRSS 0x0004 /* Control write status stage */ -#define M66592_CS_WRDS 0x0003 /* Control write data stage */ -#define M66592_CS_RDSS 0x0002 /* Control read status stage */ -#define M66592_CS_RDDS 0x0001 /* Control read data stage */ -#define M66592_CS_IDST 0x0000 /* Idle or setup stage */ +#define M66592_VBINT 0x8000 /* b15: VBUS interrupt */ +#define M66592_RESM 0x4000 /* b14: Resume interrupt */ +#define M66592_SOFR 0x2000 /* b13: SOF frame update interrupt */ +#define M66592_DVST 0x1000 /* b12: Device state transition */ +#define M66592_CTRT 0x0800 /* b11: Control stage transition */ +#define M66592_BEMP 0x0400 /* b10: Buffer empty interrupt */ +#define M66592_NRDY 0x0200 /* b9: Buffer not ready interrupt */ +#define M66592_BRDY 0x0100 /* b8: Buffer ready interrupt */ +#define M66592_VBSTS 0x0080 /* b7: VBUS input port */ +#define M66592_DVSQ 0x0070 /* b6-4: Device state */ +#define M66592_DS_SPD_CNFG 0x0070 /* Suspend Configured */ +#define M66592_DS_SPD_ADDR 0x0060 /* Suspend Address */ +#define M66592_DS_SPD_DFLT 0x0050 /* Suspend Default */ +#define M66592_DS_SPD_POWR 0x0040 /* Suspend Powered */ +#define M66592_DS_SUSP 0x0040 /* Suspend */ +#define M66592_DS_CNFG 0x0030 /* Configured */ +#define M66592_DS_ADDS 0x0020 /* Address */ +#define M66592_DS_DFLT 0x0010 /* Default */ +#define M66592_DS_POWR 0x0000 /* Powered */ +#define M66592_DVSQS 0x0030 /* b5-4: Device state */ +#define M66592_VALID 0x0008 /* b3: Setup packet detected flag */ +#define M66592_CTSQ 0x0007 /* b2-0: Control transfer stage */ +#define M66592_CS_SQER 0x0006 /* Sequence error */ +#define M66592_CS_WRND 0x0005 /* Control write nodata status */ +#define M66592_CS_WRSS 0x0004 /* Control write status stage */ +#define M66592_CS_WRDS 0x0003 /* Control write data stage */ +#define M66592_CS_RDSS 0x0002 /* Control read status stage */ +#define M66592_CS_RDDS 0x0001 /* Control read data stage */ +#define M66592_CS_IDST 0x0000 /* Idle or setup stage */ #define M66592_INTSTS1 0x42 -#define M66592_BCHG 0x4000 /* b14: USB bus chenge interrupt */ -#define M66592_DTCH 0x1000 /* b12: Detach sense interrupt */ -#define M66592_SIGN 0x0020 /* b5: SETUP IGNORE interrupt */ -#define M66592_SACK 0x0010 /* b4: SETUP ACK interrupt */ +#define M66592_BCHG 0x4000 /* b14: USB bus chenge interrupt */ +#define M66592_DTCH 0x1000 /* b12: Detach sense interrupt */ +#define M66592_SIGN 0x0020 /* b5: SETUP IGNORE interrupt */ +#define M66592_SACK 0x0010 /* b4: SETUP ACK interrupt */ #define M66592_FRMNUM 0x4C -#define M66592_OVRN 0x8000 /* b15: Overrun error */ -#define M66592_CRCE 0x4000 /* b14: Received data error */ -#define M66592_SOFRM 0x0800 /* b11: SOF output mode */ -#define M66592_FRNM 0x07FF /* b10-0: Frame number */ +#define M66592_OVRN 0x8000 /* b15: Overrun error */ +#define M66592_CRCE 0x4000 /* b14: Received data error */ +#define M66592_SOFRM 0x0800 /* b11: SOF output mode */ +#define M66592_FRNM 0x07FF /* b10-0: Frame number */ #define M66592_UFRMNUM 0x4E -#define M66592_UFRNM 0x0007 /* b2-0: Micro frame number */ +#define M66592_UFRNM 0x0007 /* b2-0: Micro frame number */ #define M66592_RECOVER 0x50 -#define M66592_STSRECOV 0x0700 /* Status recovery */ -#define M66592_STSR_HI 0x0400 /* FULL(0) or HI(1) Speed */ -#define M66592_STSR_DEFAULT 0x0100 /* Default state */ -#define M66592_STSR_ADDRESS 0x0200 /* Address state */ -#define M66592_STSR_CONFIG 0x0300 /* Configured state */ -#define M66592_USBADDR 0x007F /* b6-0: USB address */ +#define M66592_STSRECOV 0x0700 /* Status recovery */ +#define M66592_STSR_HI 0x0400 /* FULL(0) or HI(1) Speed */ +#define M66592_STSR_DEFAULT 0x0100 /* Default state */ +#define M66592_STSR_ADDRESS 0x0200 /* Address state */ +#define M66592_STSR_CONFIG 0x0300 /* Configured state */ +#define M66592_USBADDR 0x007F /* b6-0: USB address */ #define M66592_USBREQ 0x54 -#define M66592_bRequest 0xFF00 /* b15-8: bRequest */ -#define M66592_GET_STATUS 0x0000 -#define M66592_CLEAR_FEATURE 0x0100 -#define M66592_ReqRESERVED 0x0200 -#define M66592_SET_FEATURE 0x0300 -#define M66592_ReqRESERVED1 0x0400 -#define M66592_SET_ADDRESS 0x0500 -#define M66592_GET_DESCRIPTOR 0x0600 -#define M66592_SET_DESCRIPTOR 0x0700 -#define M66592_GET_CONFIGURATION 0x0800 -#define M66592_SET_CONFIGURATION 0x0900 -#define M66592_GET_INTERFACE 0x0A00 -#define M66592_SET_INTERFACE 0x0B00 -#define M66592_SYNCH_FRAME 0x0C00 -#define M66592_bmRequestType 0x00FF /* b7-0: bmRequestType */ -#define M66592_bmRequestTypeDir 0x0080 /* b7 : Data transfer direction */ -#define M66592_HOST_TO_DEVICE 0x0000 -#define M66592_DEVICE_TO_HOST 0x0080 -#define M66592_bmRequestTypeType 0x0060 /* b6-5: Type */ -#define M66592_STANDARD 0x0000 -#define M66592_CLASS 0x0020 -#define M66592_VENDOR 0x0040 -#define M66592_bmRequestTypeRecip 0x001F /* b4-0: Recipient */ -#define M66592_DEVICE 0x0000 -#define M66592_INTERFACE 0x0001 -#define M66592_ENDPOINT 0x0002 +#define M66592_bRequest 0xFF00 /* b15-8: bRequest */ +#define M66592_GET_STATUS 0x0000 +#define M66592_CLEAR_FEATURE 0x0100 +#define M66592_ReqRESERVED 0x0200 +#define M66592_SET_FEATURE 0x0300 +#define M66592_ReqRESERVED1 0x0400 +#define M66592_SET_ADDRESS 0x0500 +#define M66592_GET_DESCRIPTOR 0x0600 +#define M66592_SET_DESCRIPTOR 0x0700 +#define M66592_GET_CONFIGURATION 0x0800 +#define M66592_SET_CONFIGURATION 0x0900 +#define M66592_GET_INTERFACE 0x0A00 +#define M66592_SET_INTERFACE 0x0B00 +#define M66592_SYNCH_FRAME 0x0C00 +#define M66592_bmRequestType 0x00FF /* b7-0: bmRequestType */ +#define M66592_bmRequestTypeDir 0x0080 /* b7 : Data direction */ +#define M66592_HOST_TO_DEVICE 0x0000 +#define M66592_DEVICE_TO_HOST 0x0080 +#define M66592_bmRequestTypeType 0x0060 /* b6-5: Type */ +#define M66592_STANDARD 0x0000 +#define M66592_CLASS 0x0020 +#define M66592_VENDOR 0x0040 +#define M66592_bmRequestTypeRecip 0x001F /* b4-0: Recipient */ +#define M66592_DEVICE 0x0000 +#define M66592_INTERFACE 0x0001 +#define M66592_ENDPOINT 0x0002 #define M66592_USBVAL 0x56 -#define M66592_wValue 0xFFFF /* b15-0: wValue */ +#define M66592_wValue 0xFFFF /* b15-0: wValue */ /* Standard Feature Selector */ -#define M66592_ENDPOINT_HALT 0x0000 -#define M66592_DEVICE_REMOTE_WAKEUP 0x0001 -#define M66592_TEST_MODE 0x0002 +#define M66592_ENDPOINT_HALT 0x0000 +#define M66592_DEVICE_REMOTE_WAKEUP 0x0001 +#define M66592_TEST_MODE 0x0002 /* Descriptor Types */ -#define M66592_DT_TYPE 0xFF00 -#define M66592_GET_DT_TYPE(v) (((v) & DT_TYPE) >> 8) -#define M66592_DT_DEVICE 0x01 -#define M66592_DT_CONFIGURATION 0x02 -#define M66592_DT_STRING 0x03 -#define M66592_DT_INTERFACE 0x04 -#define M66592_DT_ENDPOINT 0x05 -#define M66592_DT_DEVICE_QUALIFIER 0x06 -#define M66592_DT_OTHER_SPEED_CONFIGURATION 0x07 -#define M66592_DT_INTERFACE_POWER 0x08 -#define M66592_DT_INDEX 0x00FF -#define M66592_CONF_NUM 0x00FF -#define M66592_ALT_SET 0x00FF +#define M66592_DT_TYPE 0xFF00 +#define M66592_GET_DT_TYPE(v) (((v) & DT_TYPE) >> 8) +#define M66592_DT_DEVICE 0x01 +#define M66592_DT_CONFIGURATION 0x02 +#define M66592_DT_STRING 0x03 +#define M66592_DT_INTERFACE 0x04 +#define M66592_DT_ENDPOINT 0x05 +#define M66592_DT_DEVICE_QUALIFIER 0x06 +#define M66592_DT_OTHER_SPEED_CONFIGURATION 0x07 +#define M66592_DT_INTERFACE_POWER 0x08 +#define M66592_DT_INDEX 0x00FF +#define M66592_CONF_NUM 0x00FF +#define M66592_ALT_SET 0x00FF #define M66592_USBINDEX 0x58 -#define M66592_wIndex 0xFFFF /* b15-0: wIndex */ -#define M66592_TEST_SELECT 0xFF00 /* b15-b8: Test Mode Selectors */ -#define M66592_TEST_J 0x0100 /* Test_J */ -#define M66592_TEST_K 0x0200 /* Test_K */ -#define M66592_TEST_SE0_NAK 0x0300 /* Test_SE0_NAK */ -#define M66592_TEST_PACKET 0x0400 /* Test_Packet */ -#define M66592_TEST_FORCE_ENABLE 0x0500 /* Test_Force_Enable */ -#define M66592_TEST_STSelectors 0x0600 /* Standard test selectors */ -#define M66592_TEST_Reserved 0x4000 /* Reserved */ -#define M66592_TEST_VSTModes 0xC000 /* Vendor-specific test modes */ -#define M66592_EP_DIR 0x0080 /* b7: Endpoint Direction */ -#define M66592_EP_DIR_IN 0x0080 -#define M66592_EP_DIR_OUT 0x0000 +#define M66592_wIndex 0xFFFF /* b15-0: wIndex */ +#define M66592_TEST_SELECT 0xFF00 /* b15-b8: Test Mode */ +#define M66592_TEST_J 0x0100 /* Test_J */ +#define M66592_TEST_K 0x0200 /* Test_K */ +#define M66592_TEST_SE0_NAK 0x0300 /* Test_SE0_NAK */ +#define M66592_TEST_PACKET 0x0400 /* Test_Packet */ +#define M66592_TEST_FORCE_ENABLE 0x0500 /* Test_Force_Enable */ +#define M66592_TEST_STSelectors 0x0600 /* Standard test selectors */ +#define M66592_TEST_Reserved 0x4000 /* Reserved */ +#define M66592_TEST_VSTModes 0xC000 /* Vendor-specific tests */ +#define M66592_EP_DIR 0x0080 /* b7: Endpoint Direction */ +#define M66592_EP_DIR_IN 0x0080 +#define M66592_EP_DIR_OUT 0x0000 #define M66592_USBLENG 0x5A -#define M66592_wLength 0xFFFF /* b15-0: wLength */ +#define M66592_wLength 0xFFFF /* b15-0: wLength */ #define M66592_DCPCFG 0x5C -#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */ -#define M66592_DIR 0x0010 /* b4: Control transfer DIR select */ +#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode */ +#define M66592_DIR 0x0010 /* b4: Control transfer DIR select */ #define M66592_DCPMAXP 0x5E -#define M66592_DEVSEL 0xC000 /* b15-14: Device address select */ -#define M66592_DEVICE_0 0x0000 /* Device address 0 */ -#define M66592_DEVICE_1 0x4000 /* Device address 1 */ -#define M66592_DEVICE_2 0x8000 /* Device address 2 */ -#define M66592_DEVICE_3 0xC000 /* Device address 3 */ -#define M66592_MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ +#define M66592_DEVSEL 0xC000 /* b15-14: Device address select */ +#define M66592_DEVICE_0 0x0000 /* Device address 0 */ +#define M66592_DEVICE_1 0x4000 /* Device address 1 */ +#define M66592_DEVICE_2 0x8000 /* Device address 2 */ +#define M66592_DEVICE_3 0xC000 /* Device address 3 */ +#define M66592_MAXP 0x007F /* b6-0: Maxpacket size of ep0 */ #define M66592_DCPCTR 0x60 -#define M66592_BSTS 0x8000 /* b15: Buffer status */ -#define M66592_SUREQ 0x4000 /* b14: Send USB request */ -#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define M66592_CCPL 0x0004 /* b2: Enable control transfer complete */ -#define M66592_PID 0x0003 /* b1-0: Response PID */ -#define M66592_PID_STALL 0x0002 /* STALL */ -#define M66592_PID_BUF 0x0001 /* BUF */ -#define M66592_PID_NAK 0x0000 /* NAK */ +#define M66592_BSTS 0x8000 /* b15: Buffer status */ +#define M66592_SUREQ 0x4000 /* b14: Send USB request */ +#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define M66592_CCPL 0x0004 /* b2: control transfer complete */ +#define M66592_PID 0x0003 /* b1-0: Response PID */ +#define M66592_PID_STALL 0x0002 /* STALL */ +#define M66592_PID_BUF 0x0001 /* BUF */ +#define M66592_PID_NAK 0x0000 /* NAK */ #define M66592_PIPESEL 0x64 -#define M66592_PIPENM 0x0007 /* b2-0: Pipe select */ -#define M66592_PIPE0 0x0000 /* PIPE 0 */ -#define M66592_PIPE1 0x0001 /* PIPE 1 */ -#define M66592_PIPE2 0x0002 /* PIPE 2 */ -#define M66592_PIPE3 0x0003 /* PIPE 3 */ -#define M66592_PIPE4 0x0004 /* PIPE 4 */ -#define M66592_PIPE5 0x0005 /* PIPE 5 */ -#define M66592_PIPE6 0x0006 /* PIPE 6 */ -#define M66592_PIPE7 0x0007 /* PIPE 7 */ +#define M66592_PIPENM 0x0007 /* b2-0: Pipe select */ +#define M66592_PIPE0 0x0000 /* PIPE 0 */ +#define M66592_PIPE1 0x0001 /* PIPE 1 */ +#define M66592_PIPE2 0x0002 /* PIPE 2 */ +#define M66592_PIPE3 0x0003 /* PIPE 3 */ +#define M66592_PIPE4 0x0004 /* PIPE 4 */ +#define M66592_PIPE5 0x0005 /* PIPE 5 */ +#define M66592_PIPE6 0x0006 /* PIPE 6 */ +#define M66592_PIPE7 0x0007 /* PIPE 7 */ #define M66592_PIPECFG 0x66 -#define M66592_TYP 0xC000 /* b15-14: Transfer type */ -#define M66592_ISO 0xC000 /* Isochronous */ -#define M66592_INT 0x8000 /* Interrupt */ -#define M66592_BULK 0x4000 /* Bulk */ -#define M66592_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ -#define M66592_DBLB 0x0200 /* b9: Double buffer mode select */ -#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */ -#define M66592_SHTNAK 0x0080 /* b7: Transfer end NAK */ -#define M66592_DIR 0x0010 /* b4: Transfer direction select */ -#define M66592_DIR_H_OUT 0x0010 /* HOST OUT */ -#define M66592_DIR_P_IN 0x0010 /* PERI IN */ -#define M66592_DIR_H_IN 0x0000 /* HOST IN */ -#define M66592_DIR_P_OUT 0x0000 /* PERI OUT */ -#define M66592_EPNUM 0x000F /* b3-0: Eendpoint number select */ -#define M66592_EP1 0x0001 -#define M66592_EP2 0x0002 -#define M66592_EP3 0x0003 -#define M66592_EP4 0x0004 -#define M66592_EP5 0x0005 -#define M66592_EP6 0x0006 -#define M66592_EP7 0x0007 -#define M66592_EP8 0x0008 -#define M66592_EP9 0x0009 -#define M66592_EP10 0x000A -#define M66592_EP11 0x000B -#define M66592_EP12 0x000C -#define M66592_EP13 0x000D -#define M66592_EP14 0x000E -#define M66592_EP15 0x000F +#define M66592_TYP 0xC000 /* b15-14: Transfer type */ +#define M66592_ISO 0xC000 /* Isochronous */ +#define M66592_INT 0x8000 /* Interrupt */ +#define M66592_BULK 0x4000 /* Bulk */ +#define M66592_BFRE 0x0400 /* b10: Buffer ready interrupt mode */ +#define M66592_DBLB 0x0200 /* b9: Double buffer mode select */ +#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode */ +#define M66592_SHTNAK 0x0080 /* b7: Transfer end NAK */ +#define M66592_DIR 0x0010 /* b4: Transfer direction select */ +#define M66592_DIR_H_OUT 0x0010 /* HOST OUT */ +#define M66592_DIR_P_IN 0x0010 /* PERI IN */ +#define M66592_DIR_H_IN 0x0000 /* HOST IN */ +#define M66592_DIR_P_OUT 0x0000 /* PERI OUT */ +#define M66592_EPNUM 0x000F /* b3-0: Eendpoint number select */ +#define M66592_EP1 0x0001 +#define M66592_EP2 0x0002 +#define M66592_EP3 0x0003 +#define M66592_EP4 0x0004 +#define M66592_EP5 0x0005 +#define M66592_EP6 0x0006 +#define M66592_EP7 0x0007 +#define M66592_EP8 0x0008 +#define M66592_EP9 0x0009 +#define M66592_EP10 0x000A +#define M66592_EP11 0x000B +#define M66592_EP12 0x000C +#define M66592_EP13 0x000D +#define M66592_EP14 0x000E +#define M66592_EP15 0x000F #define M66592_PIPEBUF 0x68 -#define M66592_BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ -#define M66592_BUF_SIZE(x) ((((x) / 64) - 1) << 10) -#define M66592_BUFNMB 0x00FF /* b7-0: Pipe buffer number */ +#define M66592_BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ +#define M66592_BUF_SIZE(x) ((((x) / 64) - 1) << 10) +#define M66592_BUFNMB 0x00FF /* b7-0: Pipe buffer number */ #define M66592_PIPEMAXP 0x6A -#define M66592_MXPS 0x07FF /* b10-0: Maxpacket size */ +#define M66592_MXPS 0x07FF /* b10-0: Maxpacket size */ #define M66592_PIPEPERI 0x6C -#define M66592_IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define M66592_IITV 0x0007 /* b2-0: Isochronous interval */ +#define M66592_IFIS 0x1000 /* b12: ISO in-buffer flush mode */ +#define M66592_IITV 0x0007 /* b2-0: ISO interval */ #define M66592_PIPE1CTR 0x70 #define M66592_PIPE2CTR 0x72 @@ -401,19 +401,17 @@ #define M66592_PIPE5CTR 0x78 #define M66592_PIPE6CTR 0x7A #define M66592_PIPE7CTR 0x7C -#define M66592_BSTS 0x8000 /* b15: Buffer status */ -#define M66592_INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define M66592_ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define M66592_PID 0x0003 /* b1-0: Response PID */ +#define M66592_BSTS 0x8000 /* b15: Buffer status */ +#define M66592_INBUFM 0x4000 /* b14: IN buffer monitor (PIPE 1-5) */ +#define M66592_ACLRM 0x0200 /* b9: Out buffer auto clear mode */ +#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define M66592_PID 0x0003 /* b1-0: Response PID */ #define M66592_INVALID_REG 0x7E -#define __iomem - #define get_pipectr_addr(pipenum) (M66592_PIPE1CTR + (pipenum - 1) * 2) #define M66592_MAX_SAMPLING 10 @@ -449,7 +447,7 @@ struct m66592_ep { struct m66592 *m66592; struct list_head queue; - unsigned busy:1; + unsigned busy:1; unsigned internal_ccpl:1; /* use only control */ /* this member can able to after m66592_enable */ @@ -477,7 +475,7 @@ struct m66592 { struct m66592_ep *epaddr2ep[16]; struct usb_request *ep0_req; /* for internal request */ - u16 *ep0_buf; /* for internal request */ + u16 ep0_data; /* for internal request */ struct timer_list timer; @@ -527,8 +525,8 @@ static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset) } static inline void m66592_read_fifo(struct m66592 *m66592, - unsigned long offset, - void *buf, unsigned long len) + unsigned long offset, + void *buf, unsigned long len) { unsigned long fifoaddr = (unsigned long)m66592->reg + offset; @@ -543,8 +541,8 @@ static inline void m66592_write(struct m66592 *m66592, u16 val, } static inline void m66592_write_fifo(struct m66592 *m66592, - unsigned long offset, - void *buf, unsigned long len) + unsigned long offset, + void *buf, unsigned long len) { unsigned long fifoaddr = (unsigned long)m66592->reg + offset; unsigned long odd = len & 0x0001; @@ -558,7 +556,7 @@ static inline void m66592_write_fifo(struct m66592 *m66592, } static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, - unsigned long offset) + unsigned long offset) { u16 tmp; tmp = m66592_read(m66592, offset); -- cgit v1.2.2 From c35f68a05d0916e89ae2aab1a456f96fea9190cd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: atm: cxacru: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 1bc884051e0f..02c52f8d5dbf 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -456,7 +456,7 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, int* actual_length) { struct timer_list timer; - int status; + int status = urb->status; init_timer(&timer); timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT); @@ -464,7 +464,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, timer.function = cxacru_timeout_kill; add_timer(&timer); wait_for_completion(done); - status = urb->status; del_timer_sync(&timer); if (actual_length) -- cgit v1.2.2 From 9a5a3e95b49c93813476974abaa038c9d36bdd14 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: atm: speedtch: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/speedtch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 638b8009b3bc..eb0615abff68 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -612,7 +612,8 @@ static void speedtch_handle_int(struct urb *int_urb) struct speedtch_instance_data *instance = int_urb->context; struct usbatm_data *usbatm = instance->usbatm; unsigned int count = int_urb->actual_length; - int ret = int_urb->status; + int status = int_urb->status; + int ret; /* The magic interrupt for "up state" */ static const unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 }; @@ -621,8 +622,8 @@ static void speedtch_handle_int(struct urb *int_urb) atm_dbg(usbatm, "%s entered\n", __func__); - if (ret < 0) { - atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, ret); + if (status < 0) { + atm_dbg(usbatm, "%s: nonzero urb status %d!\n", __func__, status); goto fail; } -- cgit v1.2.2 From 508330ebdacb3df07ee2a75aee8caf2c205befc8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: atm: ueagle-atm: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 8f046659b4e9..a1a1c9d467e0 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1308,11 +1308,13 @@ static void uea_intr(struct urb *urb) { struct uea_softc *sc = urb->context; struct intr_pkt *intr = urb->transfer_buffer; + int status = urb->status; + uea_enters(INS_TO_USBDEV(sc)); - if (unlikely(urb->status < 0)) { + if (unlikely(status < 0)) { uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n", - urb->status); + status); return; } -- cgit v1.2.2 From 33fea2b2f523251d29619641451bfebdc35f4950 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: atm: usbatm: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 11e9b15ca45a..e717f5b1caee 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -257,9 +257,10 @@ static void usbatm_complete(struct urb *urb) { struct usbatm_channel *channel = urb->context; unsigned long flags; + int status = urb->status; vdbg("%s: urb 0x%p, status %d, actual_length %d", - __func__, urb, urb->status, urb->actual_length); + __func__, urb, status, urb->actual_length); /* usually in_interrupt(), but not always */ spin_lock_irqsave(&channel->lock, flags); @@ -269,16 +270,16 @@ static void usbatm_complete(struct urb *urb) spin_unlock_irqrestore(&channel->lock, flags); - if (unlikely(urb->status) && + if (unlikely(status) && (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || - urb->status != -EILSEQ )) + status != -EILSEQ )) { - if (urb->status == -ESHUTDOWN) + if (status == -ESHUTDOWN) return; if (printk_ratelimit()) atm_warn(channel->usbatm, "%s: urb 0x%p failed (%d)!\n", - __func__, urb, urb->status); + __func__, urb, status); /* throttle processing in case of an error */ mod_timer(&channel->delay, jiffies + msecs_to_jiffies(THROTTLE_MSECS)); } else -- cgit v1.2.2 From 185d40587d22fe604962fb53c0c9a9f1670feb66 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: class: cdc-acm: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index cd51520c7e72..fe940e0536e0 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -257,9 +257,10 @@ static void acm_ctrl_irq(struct urb *urb) struct usb_cdc_notification *dr = urb->transfer_buffer; unsigned char *data; int newctrl; - int status; + int retval; + int status = urb->status; - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -267,10 +268,10 @@ static void acm_ctrl_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); return; default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, status); goto exit; } @@ -311,10 +312,10 @@ static void acm_ctrl_irq(struct urb *urb) break; } exit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); + __FUNCTION__, retval); } /* data interface returns incoming bytes, or we got unthrottled */ @@ -324,7 +325,8 @@ static void acm_read_bulk(struct urb *urb) struct acm_ru *rcv = urb->context; struct acm *acm = rcv->instance; int status = urb->status; - dbg("Entering acm_read_bulk with status %d", urb->status); + + dbg("Entering acm_read_bulk with status %d", status); if (!ACM_READY(acm)) return; -- cgit v1.2.2 From 18ac3016055b58d676f6148a77dcf539d05ce215 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: class: usblp: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 80ec1039d670..5192cd9356de 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -289,16 +289,17 @@ static int proto_bias = -1; static void usblp_bulk_read(struct urb *urb) { struct usblp *usblp = urb->context; + int status = urb->status; if (usblp->present && usblp->used) { - if (urb->status) + if (status) printk(KERN_WARNING "usblp%d: " "nonzero read bulk status received: %d\n", - usblp->minor, urb->status); + usblp->minor, status); } spin_lock(&usblp->lock); - if (urb->status < 0) - usblp->rstatus = urb->status; + if (status < 0) + usblp->rstatus = status; else usblp->rstatus = urb->actual_length; usblp->rcomplete = 1; @@ -311,16 +312,17 @@ static void usblp_bulk_read(struct urb *urb) static void usblp_bulk_write(struct urb *urb) { struct usblp *usblp = urb->context; + int status = urb->status; if (usblp->present && usblp->used) { - if (urb->status) + if (status) printk(KERN_WARNING "usblp%d: " "nonzero write bulk status received: %d\n", - usblp->minor, urb->status); + usblp->minor, status); } spin_lock(&usblp->lock); - if (urb->status < 0) - usblp->wstatus = urb->status; + if (status < 0) + usblp->wstatus = status; else usblp->wstatus = urb->actual_length; usblp->wcomplete = 1; -- cgit v1.2.2 From 62e5a330dc1354d98f73a82f3d13517805f061f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: storage: onetouch: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/onetouch.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index d35369392fed..dfd42fe9e5f0 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -57,9 +57,10 @@ static void usb_onetouch_irq(struct urb *urb) struct usb_onetouch *onetouch = urb->context; signed char *data = onetouch->data; struct input_dev *dev = onetouch->dev; - int status; + int status = urb->status; + int retval; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ @@ -75,11 +76,11 @@ static void usb_onetouch_irq(struct urb *urb) input_sync(dev); resubmit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + err ("can't resubmit intr, %s-%s/input0, retval %d", onetouch->udev->bus->bus_name, - onetouch->udev->devpath, status); + onetouch->udev->devpath, retval); } static int usb_onetouch_open(struct input_dev *dev) -- cgit v1.2.2 From dd6fa4d755fb1e2822406ab8ce3d28db217acc01 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: image: mdc800: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/mdc800.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 36502a06f73a..d1131a87a5b1 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -284,9 +284,9 @@ static void mdc800_usb_irq (struct urb *urb) int data_received=0, wake_up; unsigned char* b=urb->transfer_buffer; struct mdc800_data* mdc800=urb->context; + int status = urb->status; - if (urb->status >= 0) - { + if (status >= 0) { //dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]); @@ -324,7 +324,7 @@ static void mdc800_usb_irq (struct urb *urb) || ((mdc800->camera_request_ready == 3) && (mdc800->camera_busy)) || - (urb->status < 0) + (status < 0) ); if (wake_up) @@ -376,15 +376,12 @@ static int mdc800_usb_waitForIRQ (int mode, int msec) static void mdc800_usb_write_notify (struct urb *urb) { struct mdc800_data* mdc800=urb->context; + int status = urb->status; - if (urb->status != 0) - { - err ("writing command fails (status=%i)", urb->status); - } + if (status != 0) + err ("writing command fails (status=%i)", status); else - { mdc800->state=READY; - } mdc800->written = 1; wake_up (&mdc800->write_wait); } @@ -396,9 +393,9 @@ static void mdc800_usb_write_notify (struct urb *urb) static void mdc800_usb_download_notify (struct urb *urb) { struct mdc800_data* mdc800=urb->context; + int status = urb->status; - if (urb->status == 0) - { + if (status == 0) { /* Fill output buffer with these data */ memcpy (mdc800->out, urb->transfer_buffer, 64); mdc800->out_count=64; @@ -408,10 +405,8 @@ static void mdc800_usb_download_notify (struct urb *urb) { mdc800->state=READY; } - } - else - { - err ("request bytes fails (status:%i)", urb->status); + } else { + err ("request bytes fails (status:%i)", status); } mdc800->downloaded = 1; wake_up (&mdc800->download_wait); @@ -649,9 +644,9 @@ static int mdc800_device_open (struct inode* inode, struct file *file) retval=0; mdc800->irq_urb->dev = mdc800->dev; - if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL)) - { - err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status); + retval = usb_submit_urb (mdc800->irq_urb, GFP_KERNEL); + if (retval) { + err ("request USB irq fails (submit_retval=%i).", retval); errn = -EIO; goto error_out; } @@ -698,6 +693,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l { size_t left=len, sts=len; /* single transfer size */ char __user *ptr = buf; + int retval; mutex_lock(&mdc800->io_lock); if (mdc800->state == NOT_CONNECTED) @@ -737,9 +733,9 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l /* Download -> Request new bytes */ mdc800->download_urb->dev = mdc800->dev; - if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL)) - { - err ("Can't submit download urb (status=%i)",mdc800->download_urb->status); + retval = usb_submit_urb (mdc800->download_urb, GFP_KERNEL); + if (retval) { + err ("Can't submit download urb (retval=%i)",retval); mutex_unlock(&mdc800->io_lock); return len-left; } @@ -788,6 +784,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos) { size_t i=0; + int retval; mutex_lock(&mdc800->io_lock); if (mdc800->state != READY) @@ -854,9 +851,9 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s mdc800->state=WORKING; memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8); mdc800->write_urb->dev = mdc800->dev; - if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL)) - { - err ("submitting write urb fails (status=%i)", mdc800->write_urb->status); + retval = usb_submit_urb (mdc800->write_urb, GFP_KERNEL); + if (retval) { + err ("submitting write urb fails (retval=%i)", retval); mutex_unlock(&mdc800->io_lock); return -EIO; } -- cgit v1.2.2 From b44cd112a0400d5eb381f3c1a1e7a6925911c835 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: image: microtek: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/microtek.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 51bd80d2b8cc..768b2c11a231 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -189,7 +189,7 @@ static struct usb_driver mts_usb_driver = { #define MTS_DEBUG_INT() \ do { MTS_DEBUG_GOT_HERE(); \ MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \ - MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \ + MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",transfer->status,(int)context->data_length, (int)transfer->actual_length ); \ mts_debug_dump(context->instance);\ } while(0) #else @@ -393,8 +393,6 @@ void mts_int_submit_urb (struct urb* transfer, context ); - transfer->status = 0; - res = usb_submit_urb( transfer, GFP_ATOMIC ); if ( unlikely(res) ) { MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); @@ -444,12 +442,13 @@ static void mts_get_status( struct urb *transfer ) static void mts_data_done( struct urb* transfer ) /* Interrupt context! */ { + int status = transfer->status; MTS_INT_INIT(); if ( context->data_length != transfer->actual_length ) { context->srb->resid = context->data_length - transfer->actual_length; - } else if ( unlikely(transfer->status) ) { - context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; + } else if ( unlikely(status) ) { + context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; } mts_get_status(transfer); @@ -461,10 +460,11 @@ static void mts_data_done( struct urb* transfer ) static void mts_command_done( struct urb *transfer ) /* Interrupt context! */ { + int status = transfer->status; MTS_INT_INIT(); - if ( unlikely(transfer->status) ) { - if (transfer->status == -ENOENT) { + if ( unlikely(status) ) { + if (status == -ENOENT) { /* We are being killed */ MTS_DEBUG_GOT_HERE(); context->srb->result = DID_ABORT<<16; @@ -502,12 +502,13 @@ static void mts_command_done( struct urb *transfer ) static void mts_do_sg (struct urb* transfer) { struct scatterlist * sg; + int status = transfer->status; MTS_INT_INIT(); MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); - if (unlikely(transfer->status)) { - context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; + if (unlikely(status)) { + context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; mts_transfer_cleanup(transfer); } -- cgit v1.2.2 From 3fc3e8269fa5c1f35b518dbe18dc48acef3c7684 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: core: message: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 530e854961ce..25f63f1096b4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -34,13 +34,14 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { struct completion done; unsigned long expire; - int status; + int retval; + int status = urb->status; init_completion(&done); urb->context = &done; urb->actual_length = 0; - status = usb_submit_urb(urb, GFP_NOIO); - if (unlikely(status)) + retval = usb_submit_urb(urb, GFP_NOIO); + if (unlikely(retval)) goto out; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; @@ -55,15 +56,15 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) urb->transfer_buffer_length); usb_kill_urb(urb); - status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status; + retval = status == -ENOENT ? -ETIMEDOUT : status; } else - status = urb->status; + retval = status; out: if (actual_length) *actual_length = urb->actual_length; usb_free_urb(urb); - return status; + return retval; } /*-------------------------------------------------------------------*/ @@ -250,6 +251,7 @@ static void sg_clean (struct usb_sg_request *io) static void sg_complete (struct urb *urb) { struct usb_sg_request *io = urb->context; + int status = urb->status; spin_lock (&io->lock); @@ -265,21 +267,21 @@ static void sg_complete (struct urb *urb) */ if (io->status && (io->status != -ECONNRESET - || urb->status != -ECONNRESET) + || status != -ECONNRESET) && urb->actual_length) { dev_err (io->dev->bus->controller, "dev %s ep%d%s scatterlist error %d/%d\n", io->dev->devpath, usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", - urb->status, io->status); + status, io->status); // BUG (); } - if (io->status == 0 && urb->status && urb->status != -ECONNRESET) { - int i, found, status; + if (io->status == 0 && status && status != -ECONNRESET) { + int i, found, retval; - io->status = urb->status; + io->status = status; /* the previous urbs, and this one, completed already. * unlink pending urbs so they won't rx/tx bad data. @@ -290,13 +292,13 @@ static void sg_complete (struct urb *urb) if (!io->urbs [i] || !io->urbs [i]->dev) continue; if (found) { - status = usb_unlink_urb (io->urbs [i]); - if (status != -EINPROGRESS - && status != -ENODEV - && status != -EBUSY) + retval = usb_unlink_urb (io->urbs [i]); + if (retval != -EINPROGRESS && + retval != -ENODEV && + retval != -EBUSY) dev_err (&io->dev->dev, "%s, unlink --> %d\n", - __FUNCTION__, status); + __FUNCTION__, retval); } else if (urb == io->urbs [i]) found = 1; } -- cgit v1.2.2 From 24497a00114ef42a752d614635168db9e2192f5e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: adtux: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 274d08ecf291..e9fdbc8997b3 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -179,17 +179,18 @@ static void adu_delete(struct adu_device *dev) static void adu_interrupt_in_callback(struct urb *urb) { struct adu_device *dev = urb->context; + int status = urb->status; - dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); + dbg(4," %s : enter, status %d", __FUNCTION__, status); adu_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); spin_lock(&dev->buflock); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) { + if (status != 0) { + if ((status != -ENOENT) && (status != -ECONNRESET)) { dbg(1," %s : nonzero status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } goto exit; } @@ -217,21 +218,22 @@ exit: wake_up_interruptible(&dev->read_wait); adu_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4," %s : leave, status %d", __FUNCTION__, urb->status); + dbg(4," %s : leave, status %d", __FUNCTION__, status); } static void adu_interrupt_out_callback(struct urb *urb) { struct adu_device *dev = urb->context; + int status = urb->status; - dbg(4," %s : enter, status %d", __FUNCTION__, urb->status); + dbg(4," %s : enter, status %d", __FUNCTION__, status); adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status != 0) { - if ((urb->status != -ENOENT) && - (urb->status != -ECONNRESET)) { + if (status != 0) { + if ((status != -ENOENT) && + (status != -ECONNRESET)) { dbg(1, " %s :nonzero status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } goto exit; } @@ -241,7 +243,7 @@ exit: adu_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4," %s : leave, status %d", __FUNCTION__, urb->status); + dbg(4," %s : leave, status %d", __FUNCTION__, status); } static int adu_open(struct inode *inode, struct file *file) -- cgit v1.2.2 From 13f9782d8e2e6a20e5fc44dd758d5747fdfd76ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: appledisplay: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/appledisplay.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index cf70c16f0e3f..b09c83568c1a 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -88,9 +88,10 @@ static void appledisplay_complete(struct urb *urb) { struct appledisplay *pdata = urb->context; unsigned long flags; + int status = urb->status; int retval; - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -102,12 +103,12 @@ static void appledisplay_complete(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + dbg("%s - urb shuttingdown with status: %d", + __FUNCTION__, status); return; default: dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); goto exit; } -- cgit v1.2.2 From 22bea334c941bcece2ddcc79201de4437803e3a5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: auerswald: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/auerswald.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 42d4e6454a77..df7e1ecc810a 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -862,14 +862,16 @@ static void auerswald_ctrlread_wretcomplete (struct urb * urb) pauerbuf_t bp = (pauerbuf_t) urb->context; pauerswald_t cp; int ret; + int status = urb->status; + dbg ("auerswald_ctrlread_wretcomplete called"); - dbg ("complete with status: %d", urb->status); + dbg ("complete with status: %d", status); cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); /* check if it is possible to advance */ - if (!auerswald_status_retry (urb->status) || !cp->usbdev) { + if (!auerswald_status_retry(status) || !cp->usbdev) { /* reuse the buffer */ - err ("control dummy: transmission error %d, can not retry", urb->status); + err ("control dummy: transmission error %d, can not retry", status); auerbuf_releasebuf (bp); /* Wake up all processes waiting for a buffer */ wake_up (&cp->bufferwait); @@ -902,21 +904,23 @@ static void auerswald_ctrlread_complete (struct urb * urb) pauerswald_t cp; pauerscon_t scp; pauerbuf_t bp = (pauerbuf_t) urb->context; + int status = urb->status; int ret; + dbg ("auerswald_ctrlread_complete called"); cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); /* check if there is valid data in this urb */ - if (urb->status) { - dbg ("complete with non-zero status: %d", urb->status); + if (status) { + dbg ("complete with non-zero status: %d", status); /* should we do a retry? */ - if (!auerswald_status_retry (urb->status) + if (!auerswald_status_retry(status) || !cp->usbdev || (cp->version < AUV_RETRY) || (bp->retries >= AU_RETRIES)) { /* reuse the buffer */ - err ("control read: transmission error %d, can not retry", urb->status); + err ("control read: transmission error %d, can not retry", status); auerbuf_releasebuf (bp); /* Wake up all processes waiting for a buffer */ wake_up (&cp->bufferwait); @@ -974,12 +978,13 @@ static void auerswald_int_complete (struct urb * urb) unsigned int channelid; unsigned int bytecount; int ret; + int status = urb->status; pauerbuf_t bp = NULL; pauerswald_t cp = (pauerswald_t) urb->context; dbg ("%s called", __FUNCTION__); - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -987,10 +992,10 @@ static void auerswald_int_complete (struct urb * urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); return; default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + dbg("%s - nonzero urb status received: %d", __FUNCTION__, status); goto exit; } -- cgit v1.2.2 From 84346269f9a05e66ff2973916776a080d566f9ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: ftdi-elan: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 7cc6883a6fa3..538b535e955b 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -747,10 +747,12 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer, static void ftdi_elan_write_bulk_callback(struct urb *urb) { struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context; - if (urb->status && !(urb->status == -ENOENT || urb->status == - -ECONNRESET || urb->status == -ESHUTDOWN)) { + int status = urb->status; + + if (status && !(status == -ENOENT || status == -ECONNRESET || + status == -ESHUTDOWN)) { dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %" - "d\n", urb, urb->status); + "d\n", urb, status); } usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); -- cgit v1.2.2 From fb3abee69de583180348b9029378e31574c31cfd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: iowarrior: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/iowarrior.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 28548d186712..46d9f27ec173 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -158,9 +158,10 @@ static void iowarrior_callback(struct urb *urb) int read_idx; int aux_idx; int offset; - int status; + int status = urb->status; + int retval; - switch (urb->status) { + switch (status) { case 0: /* success */ break; @@ -213,10 +214,10 @@ static void iowarrior_callback(struct urb *urb) wake_up_interruptible(&dev->read_wait); exit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) dev_err(&dev->interface->dev, "%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); + __FUNCTION__, retval); } @@ -226,13 +227,15 @@ exit: static void iowarrior_write_callback(struct urb *urb) { struct iowarrior *dev; + int status = urb->status; + dev = (struct iowarrior *)urb->context; /* sync/async unlink faults aren't errors */ - if (urb->status && - !(urb->status == -ENOENT || - urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { + if (status && + !(status == -ENOENT || + status == -ECONNRESET || status == -ESHUTDOWN)) { dbg("%s - nonzero write bulk status received: %d", - __func__, urb->status); + __func__, status); } /* free up our allocated buffer */ usb_buffer_free(urb->dev, urb->transfer_buffer_length, -- cgit v1.2.2 From 491c021e0beafe4146f6a1c9a1c58bd0fb2a42d0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: ldusb: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 5e950b90c541..8208496dfc63 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -219,16 +219,17 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) struct ld_usb *dev = urb->context; size_t *actual_buffer; unsigned int next_ring_head; + int status = urb->status; int retval; - if (urb->status) { - if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { + if (status) { + if (status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN) { goto exit; } else { dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __FUNCTION__, urb->status); + __FUNCTION__, status); spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } @@ -275,14 +276,15 @@ exit: static void ld_usb_interrupt_out_callback(struct urb *urb) { struct ld_usb *dev = urb->context; + int status = urb->status; /* sync/async unlink faults aren't errors */ - if (urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) + if (status && !(status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN)) dbg_info(&dev->intf->dev, "%s - nonzero write interrupt status received: %d\n", - __FUNCTION__, urb->status); + __FUNCTION__, status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); -- cgit v1.2.2 From 64771a0f19320f73ab4be69db591ba51a17d7748 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: legousbtower: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 2ed0daea894c..561970b889a5 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -742,19 +742,20 @@ exit: static void tower_interrupt_in_callback (struct urb *urb) { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; + int status = urb->status; int retval; - dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: enter, status %d", __FUNCTION__, status); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - if (urb->status) { - if (urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN) { + if (status) { + if (status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN) { goto exit; } else { - dbg(1, "%s: nonzero status received: %d", __FUNCTION__, urb->status); + dbg(1, "%s: nonzero status received: %d", __FUNCTION__, status); goto resubmit; /* maybe we can recover */ } } @@ -788,7 +789,7 @@ exit: wake_up_interruptible (&dev->read_wait); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: leave, status %d", __FUNCTION__, status); } @@ -798,23 +799,24 @@ exit: static void tower_interrupt_out_callback (struct urb *urb) { struct lego_usb_tower *dev = (struct lego_usb_tower *)urb->context; + int status = urb->status; - dbg(4, "%s: enter, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: enter, status %d", __FUNCTION__, status); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ - if (urb->status && !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) { + if (status && !(status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN)) { dbg(1, "%s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); lego_usb_tower_debug_data(5, __FUNCTION__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __FUNCTION__, urb->status); + dbg(4, "%s: leave, status %d", __FUNCTION__, status); } -- cgit v1.2.2 From 2fe8c3f1538e8db2b853f10480584679b0c336f1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: phidgetkit: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 371bf2b1197d..aa9bcceabe74 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -305,9 +305,10 @@ static void interfacekit_irq(struct urb *urb) struct interfacekit *kit = urb->context; unsigned char *buffer = kit->data; int i, level, sensor; - int status; + int retval; + int status = urb->status; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ @@ -377,11 +378,11 @@ static void interfacekit_irq(struct urb *urb) schedule_delayed_work(&kit->do_notify, 0); resubmit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("can't resubmit intr, %s-%s/interfacekit0, status %d", + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + err("can't resubmit intr, %s-%s/interfacekit0, retval %d", kit->udev->bus->bus_name, - kit->udev->devpath, status); + kit->udev->devpath, retval); } static void do_notify(struct work_struct *work) -- cgit v1.2.2 From a95a03811beb4ac4b9ac4a39486b912d07d64d64 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: phidgetmotorcontrol: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetmotorcontrol.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 5727e1ea2f91..df0ebcdb9d6a 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -95,9 +95,10 @@ static void motorcontrol_irq(struct urb *urb) struct motorcontrol *mc = urb->context; unsigned char *buffer = mc->data; int i, level; - int status; + int retval; + int status = urb->status;; - switch (urb->status) { + switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ @@ -151,12 +152,12 @@ static void motorcontrol_irq(struct urb *urb) schedule_delayed_work(&mc->do_notify, 0); resubmit: - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) dev_err(&mc->intf->dev, - "can't resubmit intr, %s-%s/motorcontrol0, status %d", + "can't resubmit intr, %s-%s/motorcontrol0, retval %d", mc->udev->bus->bus_name, - mc->udev->devpath, status); + mc->udev->devpath, retval); } static void do_notify(struct work_struct *work) -- cgit v1.2.2 From 0723af13bf5c6710af99531fc4862622f3c2d637 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: usblcd: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usblcd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 504f7221b0d0..719842032712 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -176,16 +176,17 @@ static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u static void lcd_write_bulk_callback(struct urb *urb) { struct usb_lcd *dev; + int status = urb->status; dev = (struct usb_lcd *)urb->context; /* sync/async unlink faults aren't errors */ - if (urb->status && - !(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) { + if (status && + !(status == -ENOENT || + status == -ECONNRESET || + status == -ESHUTDOWN)) { dbg("USBLCD: %s - nonzero write bulk status received: %d", - __FUNCTION__, urb->status); + __FUNCTION__, status); } /* free up our allocated buffer */ -- cgit v1.2.2 From 59d99785a9f8294f9e38ac677df8526e44462f66 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: usbtest: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index fb321864a92d..e901d31e051b 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -768,8 +768,8 @@ static void ctrl_complete (struct urb *urb) /* some faults are allowed, not required */ if (subcase->expected > 0 && ( - ((urb->status == -subcase->expected /* happened */ - || urb->status == 0)))) /* didn't */ + ((status == -subcase->expected /* happened */ + || status == 0)))) /* didn't */ status = 0; /* sometimes more than one fault is allowed */ else if (subcase->number == 12 && status == -EPIPE) -- cgit v1.2.2 From 82210d377468f59745303b96473e30e60b33434d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Jul 2007 10:58:02 -0700 Subject: USB: misc: uss720: clean up urb->status usage This done in anticipation of removal of urb->status, which will make that patch easier to review and apply in the future. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/uss720.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 1a60f9c473ad..2734fe2b9c43 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -111,12 +111,13 @@ static void async_complete(struct urb *urb) struct uss720_async_request *rq; struct parport *pp; struct parport_uss720_private *priv; + int status = urb->status; rq = urb->context; priv = rq->priv; pp = priv->pp; - if (urb->status) { - err("async_complete: urb error %d", urb->status); + if (status) { + err("async_complete: urb error %d", status); } else if (rq->dr.bRequest == 3) { memcpy(priv->reg, rq->reg, sizeof(priv->reg)); #if 0 -- cgit v1.2.2 From 32aca5600526189dd876e6c92b64fd88cf052c8d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Jul 2007 12:08:02 -0400 Subject: USB: move routines in hcd.c This patch (as939) moves a couple of routine in hcd.c around. The purpose is to put all the general URB- and endpoint-related routines (submit, unlink, giveback, and disable) together in one spot. There are no functional changes. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 82 +++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 963520fbef90..032b118c2883 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1033,18 +1033,6 @@ done: /*-------------------------------------------------------------------------*/ -/* called in any context */ -int usb_hcd_get_frame_number (struct usb_device *udev) -{ - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - - if (!HC_IS_RUNNING (hcd->state)) - return -ESHUTDOWN; - return hcd->driver->get_frame_number (hcd); -} - -/*-------------------------------------------------------------------------*/ - /* this makes the hcd giveback() the urb more quickly, by kicking it * off hardware queues (which may take a while) and returning it as * soon as practical. we've already set up the urb's return status, @@ -1167,6 +1155,35 @@ done: /*-------------------------------------------------------------------------*/ +/** + * usb_hcd_giveback_urb - return URB from HCD to device driver + * @hcd: host controller returning the URB + * @urb: urb being returned to the USB device driver. + * Context: in_interrupt() + * + * This hands the URB from HCD to its USB device driver, using its + * completion function. The HCD has freed all per-urb resources + * (and is done using urb->hcpriv). It also released all HCD locks; + * the device driver won't cause problems if it frees, modifies, + * or resubmits this URB. + */ +void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) +{ + urb_unlink(hcd, urb); + usbmon_urb_complete (&hcd->self, urb); + usb_unanchor_urb(urb); + + /* pass ownership to the completion handler */ + urb->complete (urb); + atomic_dec (&urb->use_count); + if (unlikely (urb->reject)) + wake_up (&usb_kill_urb_queue); + usb_put_urb (urb); +} +EXPORT_SYMBOL (usb_hcd_giveback_urb); + +/*-------------------------------------------------------------------------*/ + /* disables the endpoint: cancels any pending urbs, then synchronizes with * the hcd to make sure all endpoint state is gone from hardware, and then * waits until the endpoint's queue is completely drained. use for @@ -1260,6 +1277,18 @@ rescan: /*-------------------------------------------------------------------------*/ +/* called in any context */ +int usb_hcd_get_frame_number (struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!HC_IS_RUNNING (hcd->state)) + return -ESHUTDOWN; + return hcd->driver->get_frame_number (hcd); +} + +/*-------------------------------------------------------------------------*/ + #ifdef CONFIG_PM int hcd_bus_suspend(struct usb_device *rhdev) @@ -1394,35 +1423,6 @@ EXPORT_SYMBOL (usb_bus_start_enum); /*-------------------------------------------------------------------------*/ -/** - * usb_hcd_giveback_urb - return URB from HCD to device driver - * @hcd: host controller returning the URB - * @urb: urb being returned to the USB device driver. - * Context: in_interrupt() - * - * This hands the URB from HCD to its USB device driver, using its - * completion function. The HCD has freed all per-urb resources - * (and is done using urb->hcpriv). It also released all HCD locks; - * the device driver won't cause problems if it frees, modifies, - * or resubmits this URB. - */ -void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) -{ - urb_unlink(hcd, urb); - usbmon_urb_complete (&hcd->self, urb); - usb_unanchor_urb(urb); - - /* pass ownership to the completion handler */ - urb->complete (urb); - atomic_dec (&urb->use_count); - if (unlikely (urb->reject)) - wake_up (&usb_kill_urb_queue); - usb_put_urb (urb); -} -EXPORT_SYMBOL (usb_hcd_giveback_urb); - -/*-------------------------------------------------------------------------*/ - /** * usb_hcd_irq - hook IRQs to HCD framework (bus glue) * @irq: the IRQ being raised -- cgit v1.2.2 From 809a58b896ba07e771adc76a47c83e4ca1969da8 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Jul 2007 12:14:24 -0400 Subject: USB: change name of spinlock in hcd.c This patch (as940 renames hcd_data_lock in hcd.c to hcd_urb_list_lock, which is more descriptive of the lock's job. It also introduces a convenient inline routine for testing whether a particular USB device is a root hub. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 032b118c2883..42ef1d5f6c8a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -99,12 +99,17 @@ EXPORT_SYMBOL_GPL (usb_bus_list_lock); /* used for controlling access to virtual root hubs */ static DEFINE_SPINLOCK(hcd_root_hub_lock); -/* used when updating hcd data */ -static DEFINE_SPINLOCK(hcd_data_lock); +/* used when updating an endpoint's URB list */ +static DEFINE_SPINLOCK(hcd_urb_list_lock); /* wait queue for synchronous unlinks */ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); +static inline int is_root_hub(struct usb_device *udev) +{ + return (udev->parent == NULL); +} + /*-------------------------------------------------------------------------*/ /* @@ -906,14 +911,13 @@ EXPORT_SYMBOL (usb_calc_bus_time); static void urb_unlink(struct usb_hcd *hcd, struct urb *urb) { unsigned long flags; - int at_root_hub = (urb->dev == hcd->self.root_hub); /* clear all state linking urb to this dev (and hcd) */ - spin_lock_irqsave (&hcd_data_lock, flags); + spin_lock_irqsave(&hcd_urb_list_lock, flags); list_del_init (&urb->urb_list); - spin_unlock_irqrestore (&hcd_data_lock, flags); + spin_unlock_irqrestore(&hcd_urb_list_lock, flags); - if (hcd->self.uses_dma && !at_root_hub) { + if (hcd->self.uses_dma && !is_root_hub(urb->dev)) { if (usb_pipecontrol (urb->pipe) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) dma_unmap_single (hcd->self.controller, urb->setup_dma, @@ -955,7 +959,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) // FIXME: verify that quiescing hc works right (RH cleans up) - spin_lock_irqsave (&hcd_data_lock, flags); + spin_lock_irqsave(&hcd_urb_list_lock, flags); ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) [usb_pipeendpoint(urb->pipe)]; if (unlikely (!ep)) @@ -972,7 +976,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) status = -ESHUTDOWN; break; } - spin_unlock_irqrestore (&hcd_data_lock, flags); + spin_unlock_irqrestore(&hcd_urb_list_lock, flags); if (status) { INIT_LIST_HEAD (&urb->urb_list); usbmon_urb_submit_error(&hcd->self, urb, status); @@ -986,7 +990,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) urb = usb_get_urb (urb); atomic_inc (&urb->use_count); - if (urb->dev == hcd->self.root_hub) { + if (is_root_hub(urb->dev)) { /* NOTE: requirement on hub callers (usbfs and the hub * driver, for now) that URBs' urb->transfer_buffer be * valid and usb_buffer_{sync,unmap}() not be needed, since @@ -1043,7 +1047,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) { int value; - if (urb->dev == hcd->self.root_hub) + if (is_root_hub(urb->dev)) value = usb_rh_urb_dequeue (hcd, urb); else { @@ -1091,11 +1095,11 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) * that it was submitted. But as a rule it can't know whether or * not it's already been unlinked ... so we respect the reversed * lock sequence needed for the usb_hcd_giveback_urb() code paths - * (urb lock, then hcd_data_lock) in case some other CPU is now + * (urb lock, then hcd_urb_list_lock) in case some other CPU is now * unlinking it. */ spin_lock_irqsave (&urb->lock, flags); - spin_lock (&hcd_data_lock); + spin_lock(&hcd_urb_list_lock); sys = &urb->dev->dev; hcd = bus_to_hcd(urb->dev->bus); @@ -1127,17 +1131,16 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) * finish unlinking the initial failed usb_set_address() * or device descriptor fetch. */ - if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) - && hcd->self.root_hub != urb->dev) { + if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && + !is_root_hub(urb->dev)) { dev_warn (hcd->self.controller, "Unlink after no-IRQ? " - "Controller is probably using the wrong IRQ." - "\n"); + "Controller is probably using the wrong IRQ.\n"); set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); } urb->status = status; - spin_unlock (&hcd_data_lock); + spin_unlock(&hcd_urb_list_lock); spin_unlock_irqrestore (&urb->lock, flags); retval = unlink1 (hcd, urb); @@ -1146,7 +1149,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) return retval; done: - spin_unlock (&hcd_data_lock); + spin_unlock(&hcd_urb_list_lock); spin_unlock_irqrestore (&urb->lock, flags); if (retval != -EIDRM && sys && sys->driver) dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); @@ -1203,7 +1206,7 @@ void usb_hcd_endpoint_disable (struct usb_device *udev, /* ep is already gone from udev->ep_{in,out}[]; no more submits */ rescan: - spin_lock (&hcd_data_lock); + spin_lock(&hcd_urb_list_lock); list_for_each_entry (urb, &ep->urb_list, urb_list) { int tmp; @@ -1211,7 +1214,7 @@ rescan: if (urb->status != -EINPROGRESS) continue; usb_get_urb (urb); - spin_unlock (&hcd_data_lock); + spin_unlock(&hcd_urb_list_lock); spin_lock (&urb->lock); tmp = urb->status; @@ -1240,7 +1243,7 @@ rescan: /* list contents may have changed */ goto rescan; } - spin_unlock (&hcd_data_lock); + spin_unlock(&hcd_urb_list_lock); local_irq_enable (); /* synchronize with the hardware, so old configuration state @@ -1257,7 +1260,7 @@ rescan: * endpoint_disable methods. */ while (!list_empty (&ep->urb_list)) { - spin_lock_irq (&hcd_data_lock); + spin_lock_irq(&hcd_urb_list_lock); /* The list may have changed while we acquired the spinlock */ urb = NULL; @@ -1266,7 +1269,7 @@ rescan: urb_list); usb_get_urb (urb); } - spin_unlock_irq (&hcd_data_lock); + spin_unlock_irq(&hcd_urb_list_lock); if (urb) { usb_kill_urb (urb); -- cgit v1.2.2 From e294531dc9f2c1f5291373dcdd5013c0cdcbdee2 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 18 Jul 2007 23:10:34 +0900 Subject: USB: r8a66597-hcd: fixes some problem This patch incorporates some updates. Updates include: - Fix the problem that control transfer might fail - Change from GFP_KERNEL to GFP_ATOMIC - Clean up some coding style issue Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 110 ++++++++++++++++++++-------------------- drivers/usb/host/r8a66597.h | 87 +++++++++++++++---------------- 2 files changed, 96 insertions(+), 101 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index a7a7070c6e2a..d60f1985320c 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -35,10 +35,8 @@ #include #include #include - -#include -#include -#include +#include +#include #include "../core/hcd.h" #include "r8a66597.h" @@ -54,16 +52,21 @@ static const char hcd_name[] = "r8a66597_hcd"; /* module parameters */ static unsigned short clock = XTAL12; module_param(clock, ushort, 0644); -MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)"); +MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " + "(default=0)"); + static unsigned short vif = LDRV; module_param(vif, ushort, 0644); MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)"); -static unsigned short endian = 0; + +static unsigned short endian; module_param(endian, ushort, 0644); -MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)"); +MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)"); + static unsigned short irq_sense = INTL; module_param(irq_sense, ushort, 0644); -MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)"); +MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0 " + "(default=32)"); static void packet_write(struct r8a66597 *r8a66597, u16 pipenum); static int r8a66597_get_frame(struct usb_hcd *hcd); @@ -308,7 +311,7 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597, struct r8a66597_device *dev; int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */ - dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL); + dev = kzalloc(sizeof(struct r8a66597_device), GFP_ATOMIC); if (dev == NULL) return -ENOMEM; @@ -611,33 +614,33 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; memset(array, 0, sizeof(array)); - switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { - case USB_ENDPOINT_XFER_BULK: + switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) array[i++] = 4; else { array[i++] = 3; array[i++] = 5; } - break; - case USB_ENDPOINT_XFER_INT: + break; + case USB_ENDPOINT_XFER_INT: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { array[i++] = 6; array[i++] = 7; array[i++] = 8; } else array[i++] = 9; - break; - case USB_ENDPOINT_XFER_ISOC: + break; + case USB_ENDPOINT_XFER_ISOC: if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) array[i++] = 2; else array[i++] = 1; - break; - default: - err("Illegal type"); - return 0; - } + break; + default: + err("Illegal type"); + return 0; + } i = 1; min = array[0]; @@ -654,7 +657,7 @@ static u16 get_r8a66597_type(__u8 type) { u16 r8a66597_type; - switch(type) { + switch (type) { case USB_ENDPOINT_XFER_BULK: r8a66597_type = R8A66597_BULK; break; @@ -874,7 +877,7 @@ static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port) { r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION) | (1 << USB_PORT_FEAT_C_CONNECTION); - r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port)); + r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); } @@ -917,7 +920,7 @@ static void prepare_setup_packet(struct r8a66597 *r8a66597, r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket, DCPMAXP); - r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1); + r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1); for (i = 0; i < 4; i++) { r8a66597_write(r8a66597, p[i], setup_addr); @@ -948,19 +951,18 @@ static void prepare_packet_read(struct r8a66597 *r8a66597, pipe_irq_disable(r8a66597, td->pipenum); pipe_setting(r8a66597, td); pipe_stop(r8a66597, td->pipe); - r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), - BRDYSTS); + r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS); if (td->pipe->pipetre) { r8a66597_write(r8a66597, TRCLR, - td->pipe->pipetre); + td->pipe->pipetre); r8a66597_write(r8a66597, - (urb->transfer_buffer_length - + td->maxpacket - 1) - / td->maxpacket, - td->pipe->pipetrn); + (urb->transfer_buffer_length + + td->maxpacket - 1) + / td->maxpacket, + td->pipe->pipetrn); r8a66597_bset(r8a66597, TRENB, - td->pipe->pipetre); + td->pipe->pipetre); } pipe_start(r8a66597, td->pipe); @@ -991,7 +993,7 @@ static void prepare_packet_write(struct r8a66597 *r8a66597, if (td->pipe->pipetre) r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre); } - r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS); + r8a66597_write(r8a66597, ~(1 << td->pipenum), BRDYSTS); fifo_change_from_pipe(r8a66597, td->pipe); tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); @@ -1009,21 +1011,21 @@ static void prepare_status_packet(struct r8a66597 *r8a66597, struct urb *urb = td->urb; r8a66597_pipe_toggle(r8a66597, td->pipe, 1); + pipe_stop(r8a66597, td->pipe); if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) { r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); - r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR); - r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); + r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); + r8a66597_write(r8a66597, BCLR, CFIFOCTR); + r8a66597_write(r8a66597, BVAL, CFIFOCTR); enable_irq_empty(r8a66597, 0); } else { r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); r8a66597_write(r8a66597, BCLR, CFIFOCTR); - r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS); - r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); enable_irq_ready(r8a66597, 0); } enable_irq_nrdy(r8a66597, 0); @@ -1269,7 +1271,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) /* write fifo */ if (pipenum > 0) - r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS); + r8a66597_write(r8a66597, ~(1 << pipenum), BEMPSTS); if (urb->transfer_buffer) { r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size); if (!usb_pipebulk(urb->pipe) || td->maxpacket != size) @@ -1362,7 +1364,7 @@ static void irq_pipe_ready(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, BRDYSTS) & r8a66597_read(r8a66597, BRDYENB); - r8a66597_write(r8a66597, (u16)~mask, BRDYSTS); + r8a66597_write(r8a66597, ~mask, BRDYSTS); if (mask & BRDY0) { td = r8a66597_get_td(r8a66597, 0); if (td && td->type == USB_PID_IN) @@ -1397,7 +1399,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, BEMPSTS) & r8a66597_read(r8a66597, BEMPENB); - r8a66597_write(r8a66597, (u16)~mask, BEMPSTS); + r8a66597_write(r8a66597, ~mask, BEMPSTS); if (mask & BEMP0) { cfifo_change(r8a66597, 0); td = r8a66597_get_td(r8a66597, 0); @@ -1434,7 +1436,7 @@ static void irq_pipe_nrdy(struct r8a66597 *r8a66597) mask = r8a66597_read(r8a66597, NRDYSTS) & r8a66597_read(r8a66597, NRDYENB); - r8a66597_write(r8a66597, (u16)~mask, NRDYSTS); + r8a66597_write(r8a66597, ~mask, NRDYSTS); if (mask & NRDY0) { cfifo_change(r8a66597, 0); set_urb_error(r8a66597, 0); @@ -1488,14 +1490,14 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY); if (mask2) { if (mask2 & ATTCH) { - r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2); + r8a66597_write(r8a66597, ~ATTCH, INTSTS2); r8a66597_bclr(r8a66597, ATTCHE, INTENB2); /* start usb bus sampling */ start_root_hub_sampling(r8a66597, 1); } if (mask2 & DTCH) { - r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2); + r8a66597_write(r8a66597, ~DTCH, INTSTS2); r8a66597_bclr(r8a66597, DTCHE, INTENB2); r8a66597_usb_disconnect(r8a66597, 1); } @@ -1503,24 +1505,24 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) if (mask1) { if (mask1 & ATTCH) { - r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1); + r8a66597_write(r8a66597, ~ATTCH, INTSTS1); r8a66597_bclr(r8a66597, ATTCHE, INTENB1); /* start usb bus sampling */ start_root_hub_sampling(r8a66597, 0); } if (mask1 & DTCH) { - r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1); + r8a66597_write(r8a66597, ~DTCH, INTSTS1); r8a66597_bclr(r8a66597, DTCHE, INTENB1); r8a66597_usb_disconnect(r8a66597, 0); } if (mask1 & SIGN) { - r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1); + r8a66597_write(r8a66597, ~SIGN, INTSTS1); set_urb_error(r8a66597, 0); check_next_phase(r8a66597); } if (mask1 & SACK) { - r8a66597_write(r8a66597, (u16)~SACK, INTSTS1); + r8a66597_write(r8a66597, ~SACK, INTSTS1); check_next_phase(r8a66597); } } @@ -1663,13 +1665,9 @@ static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb) static int r8a66597_start(struct usb_hcd *hcd) { struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); - int ret; hcd->state = HC_STATE_RUNNING; - if ((ret = enable_controller(r8a66597)) < 0) - return ret; - - return 0; + return enable_controller(r8a66597); } static void r8a66597_stop(struct usb_hcd *hcd) @@ -1696,13 +1694,12 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb) static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597, struct urb *urb, - struct usb_host_endpoint *hep, - gfp_t mem_flags) + struct usb_host_endpoint *hep) { struct r8a66597_td *td; u16 pipenum; - td = kzalloc(sizeof(struct r8a66597_td), mem_flags); + td = kzalloc(sizeof(struct r8a66597_td), GFP_ATOMIC); if (td == NULL) return NULL; @@ -1741,7 +1738,8 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, } if (!hep->hcpriv) { - hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags); + hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), + GFP_ATOMIC); if (!hep->hcpriv) { ret = -ENOMEM; goto error; @@ -1755,7 +1753,7 @@ static int r8a66597_urb_enqueue(struct usb_hcd *hcd, init_pipe_config(r8a66597, urb); set_address_zero(r8a66597, urb); - td = r8a66597_make_td(r8a66597, urb, hep, mem_flags); + td = r8a66597_make_td(r8a66597, urb, hep); if (td == NULL) { ret = -ENOMEM; goto error; diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index 97c2a71ac7a1..fe9ceb077d9b 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -203,14 +203,14 @@ #define DTLN 0x0FFF /* b11-0: FIFO received data length */ /* Interrupt Enable Register 0 */ -#define VBSE 0x8000 /* b15: VBUS interrupt */ -#define RSME 0x4000 /* b14: Resume interrupt */ -#define SOFE 0x2000 /* b13: Frame update interrupt */ -#define DVSE 0x1000 /* b12: Device state transition interrupt */ -#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ +#define VBSE 0x8000 /* b15: VBUS interrupt */ +#define RSME 0x4000 /* b14: Resume interrupt */ +#define SOFE 0x2000 /* b13: Frame update interrupt */ +#define DVSE 0x1000 /* b12: Device state transition interrupt */ +#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ +#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ /* Interrupt Enable Register 1 */ #define OVRCRE 0x8000 /* b15: Over-current interrupt */ @@ -268,16 +268,16 @@ #define SOF_DISABLE 0x0000 /* SOF OUT Disable */ /* Interrupt Status Register 0 */ -#define VBINT 0x8000 /* b15: VBUS interrupt */ -#define RESM 0x4000 /* b14: Resume interrupt */ -#define SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define DVST 0x1000 /* b12: Device state transition interrupt */ -#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define VBSTS 0x0080 /* b7: VBUS input port */ -#define DVSQ 0x0070 /* b6-4: Device state */ +#define VBINT 0x8000 /* b15: VBUS interrupt */ +#define RESM 0x4000 /* b14: Resume interrupt */ +#define SOFR 0x2000 /* b13: SOF frame update interrupt */ +#define DVST 0x1000 /* b12: Device state transition interrupt */ +#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMP 0x0400 /* b10: Buffer empty interrupt */ +#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDY 0x0100 /* b8: Buffer ready interrupt */ +#define VBSTS 0x0080 /* b7: VBUS input port */ +#define DVSQ 0x0070 /* b6-4: Device state */ #define DS_SPD_CNFG 0x0070 /* Suspend Configured */ #define DS_SPD_ADDR 0x0060 /* Suspend Address */ #define DS_SPD_DFLT 0x0050 /* Suspend Default */ @@ -315,13 +315,10 @@ /* Micro Frame Number Register */ #define UFRNM 0x0007 /* b2-0: Micro frame number */ -/* USB Address / Low Power Status Recovery Register */ -//#define USBADDR 0x007F /* b6-0: USB address */ - /* Default Control Pipe Maxpacket Size Register */ /* Pipe Maxpacket Size Register */ -#define DEVSEL 0xF000 /* b15-14: Device address select */ -#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ +#define DEVSEL 0xF000 /* b15-14: Device address select */ +#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ /* Default Control Pipe Control Register */ #define BSTS 0x8000 /* b15: Buffer status */ @@ -366,21 +363,21 @@ #define MXPS 0x07FF /* b10-0: Maxpacket size */ /* Pipe Cycle Configuration Register */ -#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define IITV 0x0007 /* b2-0: Isochronous interval */ +#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ +#define IITV 0x0007 /* b2-0: Isochronous interval */ /* Pipex Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define ATREPM 0x0400 /* b10: Auto repeat mode */ -#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PID 0x0003 /* b1-0: Response PID */ +#define BSTS 0x8000 /* b15: Buffer status */ +#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ +#define CSCLR 0x2000 /* b13: complete-split status clear */ +#define CSSTS 0x1000 /* b12: complete-split status */ +#define ATREPM 0x0400 /* b10: Auto repeat mode */ +#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ +#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define PBUSY 0x0020 /* b5: pipe busy */ +#define PID 0x0003 /* b1-0: Response PID */ /* PIPExTRE */ #define TRENB 0x0200 /* b9: Transaction counter enable */ @@ -407,15 +404,15 @@ #define make_devsel(addr) (addr << 12) struct r8a66597_pipe_info { - u16 pipenum; - u16 address; /* R8A66597 HCD usb addres */ - u16 epnum; - u16 maxpacket; - u16 type; - u16 bufnum; - u16 buf_bsize; - u16 interval; - u16 dir_in; + u16 pipenum; + u16 address; /* R8A66597 HCD usb addres */ + u16 epnum; + u16 maxpacket; + u16 type; + u16 bufnum; + u16 buf_bsize; + u16 interval; + u16 dir_in; }; struct r8a66597_pipe { -- cgit v1.2.2 From d20da3c39b9d5b04f0258ba74643533268f56e30 Mon Sep 17 00:00:00 2001 From: "S.Caglar Onur" Date: Mon, 16 Jul 2007 13:41:45 +0300 Subject: USB: drivers/usb/storage/dpcm.c whitespace cleanup Following trivial patch converts smarttabs/whitespaces into real tabs. Signed-off-by: S.Caglar Onur Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/dpcm.c | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c index 1628cb258562..9a410b5a6e5b 100644 --- a/drivers/usb/storage/dpcm.c +++ b/drivers/usb/storage/dpcm.c @@ -46,43 +46,43 @@ */ int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { - int ret; + int ret; - if(srb == NULL) - return USB_STOR_TRANSPORT_ERROR; + if (srb == NULL) + return USB_STOR_TRANSPORT_ERROR; - US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun); + US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun); - switch(srb->device->lun) { - case 0: + switch (srb->device->lun) { + case 0: - /* - * LUN 0 corresponds to the CompactFlash card reader. - */ - ret = usb_stor_CB_transport(srb, us); - break; + /* + * LUN 0 corresponds to the CompactFlash card reader. + */ + ret = usb_stor_CB_transport(srb, us); + break; #ifdef CONFIG_USB_STORAGE_SDDR09 - case 1: + case 1: - /* - * LUN 1 corresponds to the SmartMedia card reader. - */ + /* + * LUN 1 corresponds to the SmartMedia card reader. + */ - /* - * Set the LUN to 0 (just in case). - */ - srb->device->lun = 0; us->srb->device->lun = 0; - ret = sddr09_transport(srb, us); - srb->device->lun = 1; us->srb->device->lun = 1; - break; + /* + * Set the LUN to 0 (just in case). + */ + srb->device->lun = 0; us->srb->device->lun = 0; + ret = sddr09_transport(srb, us); + srb->device->lun = 1; us->srb->device->lun = 1; + break; #endif - default: - US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun); - ret = USB_STOR_TRANSPORT_ERROR; - break; - } - return ret; + default: + US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun); + ret = USB_STOR_TRANSPORT_ERROR; + break; + } + return ret; } -- cgit v1.2.2